2012-02-14 31 views
9

Tôi đọc về cách bảo vệ trang web của mình khỏi các cuộc tấn công CSRF trong một ứng dụng web ASP.NET MVC. Họ nêu hai cách để làm như vậy, bằng cách:Tôi có nên sử dụng xác thực liên kết giới thiệu HTTP hoặc xác minh mã thông báo để ngăn chặn các cuộc tấn công CSRF không?

  1. sử dụng Mã xác nhận bằng cách sử dụng <@Html.AntiForgeryToken()>[ValidateAntiforgeryToken]

  2. sử dụng xác nhận HTTP giới thiệu như:

    public class IsPostedFromThisSiteAttribute : AuthorizeAttribute 
        { 
        public override void OnAuthorize(AuthorizationContext filterContext) 
         { 
         if (filterContext.HttpContext != null) 
          { 
          if (filterContext.HttpContext.Request.UrlReferrer == null) 
           throw new System.Web.HttpException("Invalid submission"); 
          if (filterContext.HttpContext.Request.UrlReferrer.Host != 
           "mysite.com") 
           throw new System.Web.HttpException 
            ("This form wasn't submitted from this site!"); 
          } 
         } 
        } 
    

    [IsPostedFromThisSite] 
    public ActionResult Register(…) 
    

Vì vậy, tôi đã nhầm lẫn về việc liệu tôi có nên sử dụng cả hai để bảo vệ trang web của tôi khỏi các cuộc tấn công CSRF hoặc liệu tôi có thể chọn một trong các phương pháp này không?

Trả lời

10

Kiểm tra liên kết giới thiệu có vấn đề. Trước hết, đặc tả HTTP đặc biệt cho phép khách hàng không gửi các chuỗi liên kết giới thiệu (vì nhiều lý do bảo mật khác nhau). Vì vậy, một số khách hàng của bạn có thể không bao gồm nó. Thứ hai, các chuỗi liên kết giới thiệu có thể bị giả mạo, nơi kẻ tấn công có đủ kỹ năng có thể khiến họ trông giống như những gì họ cần để thực hiện một cuộc tấn công CSRF thành công.

Sử dụng mã thông báo xác thực CSRF là một cách tiếp cận mạnh mẽ hơn và là phương pháp giảm thiểu ưu tiên chống lại các cuộc tấn công CSRF. Bạn có thể đọc về lý do tại sao trên OWASP CSRF Cheat Sheet.

Tôi cũng sẽ chỉ ra rằng không có lý do gì khiến bạn không thể làm cả hai. Một chiến lược Quốc phòng-Sâu (DiD) thường được mong muốn, để kẻ tấn công sẽ cần phải đánh bại nhiều, độc lập, phòng thủ để thực hiện một cuộc tấn công thành công. Bạn có thể thực hiện phương pháp kiểm tra liên kết giới thiệu yếu (NẾU một người giới thiệu được cung cấp bởi khách hàng, hãy đảm bảo rằng nó là trước khi hành động theo yêu cầu; nếu không có người giới thiệu, tiến hành như thể nó hiện diện và chính xác) cùng với mã thông báo xác thực CSRF. Bằng cách đó, bạn kiểm tra thông tin được giới thiệu nếu khách hàng cung cấp thông tin đó trong khi vẫn sử dụng phương thức mã thông báo xác thực mạnh hơn.

+1

+1: Cách tiếp cận thú vị. –

+1

nhưng đúng là cách tiếp cận mã thông báo chống giả mạo sẽ loại bỏ hầu hết các cuộc tấn công CSRFbased, nhưng nó sẽ không ngăn các bot ở đó tìm cách tự động đăng ký (và sau đó là spam) người dùng vào trang web của bạn. vì vậy làm thế nào tôi có thể chắc chắn 100% rằng trang web của tôi được bảo vệ. –

+4

@johnG: Đó không phải là một cuộc tấn công CSRF. Để ngăn chặn spambots, những gì bạn cần là tốt [CAPTCHA] (http://en.wikipedia.org/wiki/CAPTCHA). (Trên thực tế, [bảo mật thông qua tối nghĩa] (http://en.wikipedia.org/wiki/Security_through_obscurity) có thể hoạt động khá tốt, ít nhất là đối với các trang web nhỏ: nếu bạn tạo biểu mẫu đăng nhập của mình đủ khác với các trang khác, bot sẽ không thể hiểu nó. Một người gửi spam sẽ phải dành thời gian chỉnh sửa bot của họ chỉ cho trang web của bạn, điều này không hiệu quả về chi phí cho họ trừ khi trang web của bạn thực sự lớn và phổ biến.) –

2

Tiêu đề HTTP Referer (sic) is not reliable. Bạn không nên phụ thuộc vào nó cho bất cứ điều gì quan trọng. Để báo Wikipedia's CSRF article:.

"Kiểm tra HTTP Referer tiêu đề để xem nếu yêu cầu được đến từ một trang có thẩm quyền thường được sử dụng cho các thiết bị mạng nhúng bởi vì nó không làm tăng yêu cầu bộ nhớ Tuy nhiên một yêu cầu mà bỏ qua các Referer tiêu đề phải được coi là trái phép vì kẻ tấn công có thể chặn tiêu đề Referer bằng cách gửi yêu cầu từ các URL FTP hoặc HTTPS. Việc xác thực Referer nghiêm ngặt này có thể gây ra sự cố với trình duyệt hoặc proxy bỏ qua tiêu đề Referer vì lý do bảo mật. 9.0.18) cho phép Flash độc hại tạo ra các yêu cầu GET hoặc POST với các tiêu đề yêu cầu HTTP tùy ý bằng cách sử dụng CRLF Injection. lnerabilities trong một khách hàng có thể được sử dụng để giả mạo referrer của một yêu cầu HTTP. "

Kiểm tra liên kết giới thiệu cũng sẽ không giúp bạn chống lại một liên kết độc hại trực tiếp trên trang web của bạn. Cách đáng tin cậy duy nhất để bảo vệ chống lại các cuộc tấn công như vậy là sử dụng các thẻ chống giả mạo.

2

Mặc dù tôi chưa bao giờ sử dụng nó, cá nhân tôi muốn tránh căn cứ vào HTTP_REFERER. Tôi không nghĩ rằng nó phổ biến bây giờ, nhưng tôi nhớ một thời gian mà bộ bảo mật Internet (ví dụ như Norton Internet Security) sẽ chặn HTTP_REFERER được gửi đi. Điều đó có nghĩa là người dùng chính hãng có thể bị ngăn cản sử dụng trang web của bạn một cách hợp pháp.

Chỉnh sửa: Xem this question.

Tôi sẽ không dựa vào đó là đáng tin cậy.

1

Như được chỉ ra bởi các câu trả lời khác, việc sử dụng kiểm tra liên kết giới thiệu không đủ và bạn thực sự nên sử dụng mã thông báo chống giả mạo. Tuy nhiên, như @jeffsix đã chỉ ra, bạn có thể sử dụng kiểm tra liên kết giới thiệu như một chiến lược phòng thủ (DID), vì vậy kẻ tấn công sẽ phải đánh bại nhiều, độc lập, phòng thủ để thực hiện một cuộc tấn công thành công.

Thuộc tính ValidateReferrerAttribute bên dưới có thể được sử dụng cho các hành động MVP HttpPost của bạn. Nếu liên kết giới thiệu là null, nó không có gì. Nếu liên kết giới thiệu không phải là null thì nó sẽ kiểm tra xem nó có bằng tên máy chủ được chỉ định hay không. Bạn chỉ cần thêm nó bất cứ nơi nào bạn đang sử dụng ValidateAntiForgeryTokenAttribute đã có, do đó, nó sẽ rất dễ dàng để thêm.

/// <summary> 
/// For POST requests, checks that the requests referrer is the current site. This could be used along side the ValidateAntiForgeryToken 
/// Note that many clients do not send the referrer, so we do nothing in this case. 
/// This attribute can be used as part of a Defence-in-Depth (DID) strategy, so an 
/// attacker would need to defeat multiple, independent, defenses to execute a successful attack. 
/// </summary> 
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = false)] 
public class ValidateReferrerAttribute : FilterAttribute, IAuthorizationFilter 
{ 
    /// <summary> 
    /// Called when authorization is required. 
    /// </summary> 
    /// <param name="filterContext">The filter context.</param> 
    /// <exception cref="System.ArgumentNullException">filterContext</exception> 
    public void OnAuthorization(AuthorizationContext filterContext) 
    { 
     if (filterContext == null) 
     { 
      throw new ArgumentNullException("filterContext"); 
     } 

     if ((filterContext.HttpContext.Request.UrlReferrer != null) && 
      string.Equals(filterContext.HttpContext.Request.HttpMethod, "POST", StringComparison.OrdinalIgnoreCase) && 
      !string.Equals(filterContext.HttpContext.Request.UrlReferrer.Host, filterContext.HttpContext.Request.Url.Host, StringComparison.OrdinalIgnoreCase)) 
     { 
      this.HandleExternalPostRequest(filterContext); 
     } 
    } 

    /// <summary> 
    /// Handles post requests that are made from an external source. 
    /// By default a 403 Forbidden response is returned. 
    /// </summary> 
    /// <param name="filterContext">The filter context.</param> 
    /// <exception cref="System.Web.HttpException">Request not allowed.</exception> 
    protected virtual void HandleExternalPostRequest(AuthorizationContext filterContext) 
    { 
     throw new HttpException((int)HttpStatusCode.Forbidden, "Request not allowed."); 
    } 
} 
+1

Chỉ để cải thiện mã của bạn một chút (và để làm cho việc sử dụng lại dễ dàng hơn) bạn có thể đọc máy chủ lưu trữ hiện tại từ 'filterContext.HttpContext.Request.Url.Host' có nghĩa là bạn không cần phải có' "[HOST_NAME_HERE ] "' bit –

+0

Cảm ơn @MatthewSteeples. Đã cập nhật. –

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