2009-11-09 23 views
6

Tôi đang làm việc để cải thiện tính bảo mật của trang web của công ty và muốn tạo một mã thông báo để ngăn chặn những nỗ lực giả mạo có thể dễ dàng duy trì đây là những gì tôi nghĩ ra.Tạo một AntiForgeryToken thông qua Dependency Injection

public class AntiForgeryToken 
{ 
    private readonly string _referenceToken; 

    public AntiForgeryToken() 
    { 
     _referenceToken = Guid.NewGuid().ToString(); 
    } 
    public string ReferenceToken 
    { 
     get { return _referenceToken; } 
    } 
} 

Trong lớp cơ sở của tôi cho MasterPage của tôi, tôi đã một HiddenField được bao bọc bởi sở hữu tên: ReferenceToken

protected virtual void Page_Load(object sender, EventArgs e) 
{ 
    if (!Page.IsPostBack) 
    { 
     InjectToken(); 
    } 

    ValidateToken(); 
} 

private void InjectToken() 
{ 
    var token = ObjectFactory.GetInstance<AntiForgeryToken>(); 
    ReferenceToken = token.ReferenceToken; 
} 

private void ValidateToken() 
{ 
    var token = ObjectFactory.GetInstance<AntiForgeryToken>(); 
    if (ReferenceToken.Equals(token.ReferenceToken, SC.InvariantCultureIgnoreCase)) 
      return; 
    ...do stuff for failed token 
} 

Tôi có StructureMap xử lý lưu trữ các dấu hiệu bên trong phiên vì vậy nó vẫn kiên trì mỗi phiên sử dụng, sẽ tất cả của việc này là một thực hiện hợp lệ của một chương trình AntiForgery?

Edit: Dường như có một số nhầm lẫn về câu hỏi của tôi, vâng tôi hiểu ASP.NET MVC đã tích hợp sẵn trong chương trình AntiForgeryToken, câu hỏi này là một cách rõ ràng về cách thức để tái tạo này cho WebForms để ngăn chặn việc sử dụng một cuộc tấn công CSRF (Cross Site Request Forgery). Tôi hiểu điều này không có nghĩa là loại bỏ sự cần thiết cho sự cho phép thích hợp của quyền người dùng.

Tôi sẽ hiển thị liên kết rất lớn @Neal và @solairaja đã đăng: Prevent Cross-Site Request Forgery (CSRF) using ASP.NET MVC’s AntiForgeryToken() helper. Bài viết này giải thích thêm về những gì mà cuộc tấn công CSRF là và cách MVC dừng nó, tuy nhiên giải pháp của họ không thể áp dụng cho các biểu mẫu web, đó là lý do tại sao tôi đã thực hiện riêng của mình.

Sau khi nhìn thấy phản hồi từ @Neal, tôi nghĩ rằng rất có thể đó là câu trả lời được chấp nhận vì tôi không nhận ra rằng tôi có thể lấy mã nguồn thực sự từ công cụ MVC. Nhưng tôi sẽ để lại câu hỏi mở bất cứ ai khác có một số thông tin có giá trị để thêm vào.

+0

Tôi muốn sử dụng các thẻ MVC trong một trang WebForms - ví dụ: bài từ WebForm để MVC và vẫn xác nhận. Xem câu trả lời này: http://stackoverflow.com/questions/1347728/using-an-mvc-htmlhelper-from-a-webform/2553583#2553583 – Keith

Trả lời

4

Chris,

cách tiếp cận của bạn nhiều hay bắt chước ít phương pháp chống giả mạo trong MVC, ngoại trừ họ sử dụng một mã hóa base64 mảng byte được tạo ra từ RNGCryptoServiceProvider và lưu trữ các dấu hiệu cả trong trang (trường mẫu ẩn) và trong một cookie. Tôi khuyên bạn nên di chuyển nhiều logic hơn vào việc triển khai mã thông báo (ví dụ: đóng gói hầu hết logic xác thực bên trong mã thông báo).

Mã để triển khai MVC có thể truy cập miễn phí tại http://aspnet.codeplex.com/sourcecontrol/changeset/view/23011?projectName=aspnet#391757 nếu có thể bạn nên xem xét điều đó cũng như http://blog.codeville.net/2008/09/01/prevent-cross-site-request-forgery-csrf-using-aspnet-mvcs-antiforgerytoken-helper/ để có ý tưởng phân tích +.

+0

Tôi không biết tôi có thể lấy nguồn cho điều đó! Và có tôi có đóng gói tốt hơn của tiêm/xác nhận của các mã thông báo tôi chỉ cần loại bỏ tất cả điều đó vì lợi ích ngắn gọn đặc biệt là khi nó cung cấp không có gì để câu hỏi thực tế của tôi. Tôi cũng sẽ thêm phần cookie để theo dõi việc triển khai nó. –

+1

Việc triển khai hiện tại của bạn là mục đích kép cần thiết cho cookie phiên làm trình giữ chỗ cho cookie chống giả mạo vì vậy không hoàn toàn cần thiết (nhưng không làm giảm tải phiên). – Neal

-1

quy tắc đầu tiên về an ninh: Đừng cố gắng để cuộn an ninh của riêng bạn

Theo tôi được biết mô tả của bạn, điều đó sẽ không phải là một chương trình chống giả mạo hợp lệ. Tất cả kẻ tấn công sẽ cần phải phá vỡ nó sẽ sử dụng tính năng Xem nguồn của trình duyệt của họ để tìm mã thông báo. Sau đó, anh ta hoặc cô ấy có thể đăng bất cứ điều gì họ thích miễn là họ nhớ để gửi mã thông báo đó, và mã của bạn sẽ không biết sự khác biệt.

Xin lỗi nếu tôi hoàn toàn hiểu lầm mô tả của bạn ...

+0

Tôi chắc chắn đây chính là cách mã thông báo Microsoft AntiForgery được viết cho MVC rằng nó sử dụng trường ẩn trên trang. Nếu tôi đang sử dụng MVC, tôi sẽ sử dụng chức năng của họ bất kể nhưng không có trong các biểu mẫu web. –

+0

Tôi sẽ phải đi với một DV về điều này vì bạn không thêm bất kỳ thông tin hoặc cung cấp một giải pháp đã tồn tại để sao lưu quy tắc đầu tiên của bạn. –

0

Trước hết, tôi cho rằng tôi nên hỏi ... làm những gì bạn thực sự có ý nghĩa bởi "AntiForgery"? Bạn đang lo lắng về việc bị giả mạo? Phần còn lại của những gì sau đây chỉ là một số thông tin chung mà chúng tôi lưu ý ...

Một điều tôi sẽ thay đổi là không sử dụng Guid.NewGuid. Có cuộc tranh luận về việc liệu nó là ngẫu nhiên hay không và do đó không thích hợp cho mục đích an ninh. Điều đó nói rằng, tôi nghĩ rằng nó sẽ là một cuộc tấn công rất khó khăn để kéo ra.

Xem RNGCryptoServiceProvider cho phương thức GetBytes để biết điều gì đó sẽ tốt hơn để tạo ra một mã thông báo ngẫu nhiên. Ngoài sự ngẫu nhiên tốt hơn, một ưu điểm khác là bạn có thể làm cho nó bất kể kích thước bạn muốn.

Bạn có thực hiện điều này qua mặc dù ssl không? Đầu tiên, ssl là dòng phòng thủ số một cho người đàn ông trong các cuộc tấn công ở giữa. Nó có thể không đủ an toàn (và những người khác có thể tranh luận về điều đó) cho mọi nhu cầu, nhưng nếu bạn lo lắng về những điều như vậy, đó là điểm khởi đầu nếu không có gì khác. Nếu không, làm thế nào để bạn đảm bảo rằng bạn đang nhận được một phản ứng từ đúng máy và không phải là một người đàn ông-trong-the-trung người trả lời đầu tiên?Nếu không có SSL hoặc tương đương, mã thông báo của bạn cũng dễ bị đánh cắp như bất kỳ thứ gì khác bạn làm.

Một điều bổ sung cần lưu ý là việc thêm thẻ của bạn chỉ tốt cho một chuyến đi và bạn tạo một thẻ mới cho khách hàng trong chuyến đi tiếp theo. Cố gắng sử dụng lại nó không thành công.

Tôi sẽ không hãy thử thay thế SSL bằng thứ gì đó khác của chính bạn nếu đó là điều bạn đang nghĩ. Nếu bạn lo lắng về việc phát lại, một thế hệ mã thông báo thời gian là một cách để ngăn chặn nó. Nếu bạn lo lắng về việc người dùng gửi cùng một dữ liệu biểu mẫu hai lần, đây là một việc cần làm. Tôi cũng sẽ xem xét thiết kế ứng dụng tổng thể của bạn nếu bạn lo lắng về điều đó. Nhiều kịch bản phát lại và tương tự có thể bị đánh bại bởi thiết kế âm thanh của logic nghiệp vụ của bạn như không tin tưởng khách hàng gửi cho bạn thông tin nhạy cảm như giá của một mặt hàng trong giỏ hàng.

Cũng vui lòng xem hướng dẫn khác về microsoft về bảo mật ASP.NET và IIS (nghĩa là trang web bảo mật của Google ASP.NET hoặc IIS: microsoft.com) làm điểm bắt đầu. Rất nhiều người thông minh đã giải quyết được nhiều vấn đề cho chúng tôi.

+0

Có mã thông báo này sẽ nằm trên đầu trang của SSL để ngăn chặn thêm phát lại/người đàn ông trong các cuộc tấn công ở giữa. Tôi đã không xem xét mã thông báo sử dụng duy nhất sẽ cung cấp sự mạnh mẽ hơn cả trong bảo mật thực tế và chỉ dừng idiots từ cách nhấp vào công cụ trước khi postback cuối cùng thậm chí đã hoàn thành cho đến khi bạn đưa điều này lên. –

+0

Điều duy nhất tôi bắt đầu nghĩ đến với mã thông báo sử dụng là cách hiệu quả để theo dõi mã thông báo hợp lệ vì người dùng có thể mở nhiều cửa sổ để giữ danh sách tất cả mã thông báo trong phiên và sau đó gửi hết hạn các mã thông báo bằng cách loại bỏ nó khỏi danh sách để bất kỳ nỗ lực tiếp theo để gửi cùng một hình thức sẽ thất bại cho đến khi trang kết thúc nó vòng chuyến đi và có một mã thông báo mới được lưu trữ trong ViewState? –

0

tất cả điều này có hợp lệ để triển khai AntiForgery không?

Theo như tôi có thể nói, có vẻ như bạn đang chèn GUID vào một trang và sau đó tìm kiếm GUID tương tự khi trang trở lại.

Tôi không biết yêu cầu của bạn là gì, vì vậy tôi không thể nói nếu lược đồ thực sự "hợp lệ". Tuy nhiên, tôi có thể chỉ ra một vài điều:

  1. Nếu GUID chỉ sống trên trang, điều gì sẽ ngăn người dùng đọc trang trên một máy và gửi biểu mẫu từ một máy khác? Nó sẽ là tốt để liên kết nó với một cookie hoặc một phiên (mà còn sử dụng một cookie), nếu bạn chưa có.
  2. Nếu GUID được viết vào trang dưới dạng trường tĩnh ẩn <input>, thì biểu mẫu có thể được đọc và gửi bởi bot. Bạn có thể giải quyết vấn đề này bằng cách yêu cầu tập lệnh trên trang xử lý mã thông báo, trước khi gửi.
  3. Bạn đang sử dụng ViewState? Nếu vậy, bạn có thể xem xét chỉ cần đặt ViewStateUserKey thành một số giá trị có thể lặp lại duy nhất cho mỗi khách hàng; nó thực hiện một chức năng tương tự với những gì bạn đã mô tả ở đây.
+0

"Tôi có StructureMap xử lý lưu trữ các mã thông báo bên trong phiên để nó tồn tại cho mỗi phiên người dùng" –

0

Như NICK đã nói, đối với tôi quá mã mà bạn đã đưa ra, có vẻ như bạn đang chèn một GUID vào một trang, và sau đó tìm kiếm cùng một GUID khi trang trở lại. Thats tốt ý tưởng quá khi ur bằng cách sử dụng một bản đồ cấu trúc lưu trữ vào phiên.

Nhưng có một số phương pháp sẵn có sẵn có cho khái niệm AntiForgery này.

Vui lòng tham khảo liên kết bên dưới đầu tiên và hiểu

http://blog.maartenballiauw.be/post/2008/09/01/ASPNET-MVC-preview-5s-AntiForgeryToken-helper-method-and-attribute.aspx

Bây giờ,

Kiểm tra liên kết dưới đây để biết các mô tả chi tiết và phương pháp tiếp cận.

http://msdn.microsoft.com/en-us/library/system.web.mvc.htmlhelper_methods.aspx

http://blog.codeville.net/2008/09/01/prevent-cross-site-request-forgery-csrf-using-%20aspnet-mvcs-antiforgerytoken-helper/

Cảm ơn bạn !!

-1

Thay vì sử dụng mã thông báo chống giả mạo như vậy, tôi sẽ xác thực rằng người dùng được xác thực thực sự có các quyền cần thiết để thực hiện các sửa đổi được yêu cầu.

Ví dụ: là trang web "tạo trang người dùng", tôi sẽ kiểm tra xem người dùng được xác thực có ủy quyền tạo người dùng mới hay không. Là trang "chỉnh sửa trang X của người dùng", tôi sẽ kiểm tra xem người dùng được xác thực có ủy quyền sửa đổi người dùng X. Có thể vì chính anh ta là người dùng X hoặc người dùng quản trị.

Điều đó nói rằng việc sử dụng GUID không an toàn lắm. Các hướng dẫn được tạo dựa trên một thuật toán được viết cho tính độc đáo, không phải ngẫu nhiên. AFAIK có ba thuật toán hợp lệ, dựa trên tên, dựa trên thời gian và ngẫu nhiên. Nếu thuật toán Guid được hệ thống sử dụng (có thể được thay đổi bởi phiên bản .NET tương lai) dựa trên thời gian, thì việc đoán các Guids hợp lệ không phải là rất khó.

+0

DV vì câu hỏi của tôi không có gì về ủy quyền/quyền truy cập của người dùng –

+0

Pete, vui lòng truy cập http://blog.codeville.net/2008/09/01/prevent-cross-site-request-forgery-csrf-using-aspnet -mvcs-antiforgerytoken-helper/để hiểu tại sao/làm thế nào của các thẻ chống giả mạo. CSRF sẽ gửi cookie phiên người dùng và do đó trông giống như một người dùng được xác thực miễn là cuộc tấn công xảy ra trong phạm vi của một phiên hoạt động. Mã thông báo chống giả mạo được thiết kế như mã thông báo sử dụng một lần và do đó cửa sổ khai thác được giảm đáng kể. – Neal

+0

@Neal - cảm ơn vì liên kết đó, đó không phải là một nhận thức về lỗ hổng cụ thể đó. – Pete

0

Điều đó có vẻ như tôi đang tạo ra một con chim canary với mọi yêu cầu. Điều gì xảy ra nếu người dùng mở nhiều tab? :)

Vấn đề với cách tiếp cận của bạn (và triển khai ASP.NET MVC) là nó dựa vào các nhà phát triển để triển khai nó. Bảo mật như thế này nên chọn không tham gia, không chọn tham gia. Khi tôi viết AntiCSRF module, tôi đã sử dụng vòng đời trang ASP.NET thay vào đó, điều này có nghĩa là không có thay đổi đối với mã cơ bản, trừ khi nhà phát triển muốn chọn không tham gia kiểm tra CSRF. Bạn sẽ lưu ý rằng nó sử dụng một mã thông báo duy nhất kéo dài suốt đời của phiên trình duyệt của người dùng đó - không cần phải thay đổi mã thông báo với mọi yêu cầu.

Bây giờ tôi đã viết các module chủ yếu như là một cách để minh họa một số khái niệm cho cuốn sách ra đến tôi (chèn quảng cáo ở đây nụ cười), bạn có thể sử dụng tất nhiên các ViewStateUserKey, nhưng một lần nữa đây là opt-in, chứ không phải là từ chối -ngoài.

+0

Tôi nghĩ rằng bạn cũng bỏ lỡ nơi tôi nói các thẻ sẽ được lưu trữ trong phiên bởi StructureMap. Và mã được đăng ở đây là vì lợi ích ngắn gọn như tôi đã giải thích, tôi tin rằng @Neal, tôi có gói đóng gói/xác thực tốt hơn nhiều nên nó không thực sự được triển khai trên mỗi trang (vì vậy nó tuân thủ DRY), nó không liên quan gì đến tôi câu hỏi. –

+0

Quan điểm của tôi là bạn vẫn dựa vào các nhà phát triển kế thừa từ lớp trang cơ sở của bạn. Nếu bạn nối vào sự kiện page_prerender thông qua một mô-đun HTTP thì bạn không phải lo lắng về các nhà phát triển kế thừa từ lớp bên phải. Nó không quan trọng nơi bạn lưu trữ các mã thông báo bạn kiểm tra chống lại (mặc dù StructureMap làm việc trong một trang trại dễ dàng?) – blowdart

+0

Tôi đã nhìn vào mô-đun của bạn có vẻ thực sự tốt, tôi phải đã được tìm kiếm với các từ khóa sai trên google mà tôi không thể tìm thấy điều này trước đây! –

2

Biểu mẫu web ASP.NET ngăn chặn tấn công CSRF ra khỏi hộp theo mặc định nếu bạn đang sử dụng trạng thái xem. Trừ khi nếu bạn đã vô hiệu hóa trạng thái xem có hiệu quả trong ứng dụng của mình, bạn sẽ thêm mã để giải quyết vấn đề mà bạn không có.

Xem Nhà nước ngăn chặn cuộc tấn công CSRF
.Net CSRF Guard - OWASP

Các vấn đề liên quan