相关文章推荐
坚强的梨子  ·  Python Selenium 无法点击 ...·  2 年前    · 
  • 用户无需注销即可访问恶意网站。 此恶意网站包含以下 HTML 格式:

    <h1>You Are a Winner!</h1>
      <form action="http://example.com/api/account" method="post">
        <input type="hidden" name="Transaction" value="withdraw" />
        <input type="hidden" name="Amount" value="1000000" />
      <input type="submit" value="Click Me"/>
    </form>
    

    请注意,表单操作发布到易受攻击的网站,而不是恶意站点。 这是 CSRF 的“跨网站”部分。

  • 用户单击“提交”按钮。 浏览器包含包含请求的身份验证 Cookie。

  • 请求使用用户的身份验证上下文在服务器上运行,并且可以执行经过身份验证的用户允许执行的任何操作。

    尽管此示例要求用户单击窗体按钮,但恶意页面可能同样轻松地运行自动提交表单的脚本。 此外,使用 SSL 不会阻止 CSRF 攻击,因为恶意站点可以发送“https://”请求。

    通常,CSRF 攻击可能会针对使用 Cookie 进行身份验证的网站,因为浏览器会将所有相关 Cookie 发送到目标网站。 但是,CSRF 攻击并不局限于利用 Cookie。 例如,基本身份验证和摘要式身份验证也容易受到攻击。 用户使用基本身份验证或摘要式身份验证登录后。 浏览器会自动发送凭据,直到会话结束。

    为了帮助防止 CSRF 攻击,ASP.NET MVC 使用反伪造令牌,也称为 请求验证令牌

  • 客户端请求包含窗体的 HTML 页面。
  • 服务器在响应中包含两个令牌。 一个令牌作为 Cookie 发送。 另一个放置在隐藏的窗体字段中。 令牌是随机生成的,以便对手无法猜测这些值。
  • 当客户端提交表单时,它必须将这两个令牌发送回服务器。 客户端将 Cookie 令牌作为 Cookie 发送,并在表单数据中发送表单令牌。 (当用户提交 form.) 时,浏览器客户端会自动执行此操作
  • 如果请求不包含这两个令牌,服务器将禁止请求。
  • 下面是包含隐藏窗体标记的 HTML 窗体的示例:

    <form action="/Home/Test" method="post">
        <input name="__RequestVerificationToken" type="hidden"   
               value="6fGBtLZmVBZ59oUad1Fr33BuPxANKY9q3Srr5y[...]" />    
        <input type="submit" value="Submit" />
    </form>
    

    由于恶意页面由于同源策略而无法读取用户的令牌,因此防伪令牌有效。 (同源策略 阻止两个不同站点上托管的文档访问彼此的内容。因此,在前面的示例中,恶意页面可以将请求发送到 example.com,但它无法读取 response.)

    若要防止 CSRF 攻击,请使用任何身份验证协议的防伪令牌,浏览器会在用户登录后以无提示方式发送凭据。 这包括基于 Cookie 的身份验证协议,例如表单身份验证,以及基本身份验证和摘要式身份验证等协议。

    对于 POST、PUT、DELETE) 的任何非安全 (方法,应要求使用防伪令牌。 此外,请确保安全方法 (GET,HEAD) 没有任何副作用。 此外,如果启用跨域支持(如 CORS 或 JSONP),则甚至 GET 等安全方法可能容易受到 CSRF 攻击的影响,从而允许攻击者读取潜在的敏感数据。

    ASP.NET MVC 中的防伪令牌

    若要将反伪造令牌添加到 Razor 页面,请使用 HtmlHelper.AntiForgeryToken 帮助程序方法:

    @using (Html.BeginForm("Manage", "Account")) {
        @Html.AntiForgeryToken()
    

    此方法添加隐藏的窗体字段,并设置 Cookie 令牌。

    反 CSRF 和 AJAX

    表单令牌可能是 AJAX 请求的问题,因为 AJAX 请求可能会发送 JSON 数据,而不是 HTML 表单数据。 一种解决方法是在自定义 HTTP 标头中发送令牌。 以下代码使用 Razor 语法生成令牌,然后将令牌添加到 AJAX 请求。 令牌通过调用 AntiForgery.GetTokens 在服务器上生成。

    <script>
        @functions{
            public string TokenHeaderValue()
                string cookieToken, formToken;
                AntiForgery.GetTokens(null, out cookieToken, out formToken);
                return cookieToken + ":" + formToken;                
        $.ajax("api/values", {
            type: "post",
            contentType: "application/json",
            data: {  }, // JSON data goes here
            dataType: "json",
            headers: {
                'RequestVerificationToken': '@TokenHeaderValue()'
    </script>
    

    处理请求时,请从请求标头中提取令牌。 然后调用 AntiForgery.Validate 方法来验证令牌。 如果令牌无效, Validate 方法将引发异常。

    void ValidateRequestHeader(HttpRequestMessage request)
        string cookieToken = "";
        string formToken = "";
        IEnumerable<string> tokenHeaders;
        if (request.Headers.TryGetValues("RequestVerificationToken", out tokenHeaders))
            string[] tokens = tokenHeaders.First().Split(':');
            if (tokens.Length == 2)
                cookieToken = tokens[0].Trim();
                formToken = tokens[1].Trim();
        AntiForgery.Validate(cookieToken, formToken);
    
  •