为什么同源策略不足以阻止CSRF攻击?

gab*_*ssi 34 cookies csrf same-origin-policy cors jwt

首先,我假设一个后端控制输入以防止XSS漏洞.

这个答案中 @Les Hazlewood解释了如何在客户端保护JWT.

假设所有通信都有100%TLS - 在登录期间和登录后的所有时间 - 通过基本身份验证使用用户名/密码进行身份验证并在交换中接收JWT是一个有效的用例.这几乎就是OAuth 2的一个流程('密码授权')的工作方式.[...]

您只需设置Authorization标头:

Authorization: Bearer <JWT value here>
Run Code Online (Sandbox Code Playgroud)

但是,话虽如此,如果您的REST客户端是"不受信任的"(例如支持JavaScript的浏览器),我甚至不会这样做:HTTP响应中可通过JavaScript访问的任何值 - 基本上任何标头值或响应正文值 - 可以通过MITM XSS攻击嗅探和截获.

最好将JWT值存储在仅安全的纯http cookie中(cookie config:setSecure(true),setHttpOnly(true)).这可以保证浏览器:

  1. 只通过TLS连接传输cookie,
  2. 永远不要将cookie值用于JavaScript代码.

这种方法几乎是您为最佳实践安全所需要做的一切.最后一件事是确保您对每个HTTP请求都有CSRF保护,以确保启动对您站点的请求的外部域无法正常运行.

最简单的方法是使用随机值(例如UUID)设置仅安全(但不是仅限http)cookie.

我不明白为什么我们需要具有随机值的cookie来确保启动对您站点的请求的外部域无法运行.使用同源策略时,这不是免费的吗?

来自OWASP:

检查Origin Header

Origin HTTP Header标准是作为防御CSRF和其他跨域攻击的方法而引入的.与引用者不同,源将出现在源自HTTPS URL的HTTP请求中.

如果存在原始标头,则应检查其是否一致.

我知道OWASP本身的一般建议是同步器令牌模式,但我看不出剩下的漏洞是什么:

  • TLS + JWT在安全的httpOnly cookie +同源策略+没有XSS漏洞.

更新1: 同源策略仅适用于XMLHTTPRequest,因此恶意站点可以轻松地生成表单POST请求,这将破坏我的安全性.需要显式的原始标头检查.等式将是:

  • TLS + JWT在安全的httpOnly cookie + Origin Header检查 +没有XSS漏洞.

gab*_*ssi 16

摘要

我对@Bergi,@ Neil McGuigan和@SilverlightFox帮助我澄清的同源策略和CORS有一个误解的概念.

首先,@ Bergi说的是什么

SOP不会阻止发送请求.它确实阻止页面访问跨域请求的结果.

是一个重要的概念.我认为浏览器不会根据SOP限制向跨域提出请求,但这只适用于Monsur Hossain在这个优秀教程中称之为"不那么简单的请求"的情况.

跨域请求有两种形式:

  • 简单的要求
  • "不那么简单的请求"(我刚刚编写的一个术语)

简单请求是满足以下条件的请求:

  • HTTP方法匹配(区分大小写)以下之一:
    • 得到
    • POST
  • HTTP标头匹配(不区分大小写):
    • 接受
    • 接受语言
    • 内容语言
    • 最后,事件ID
    • Content-Type,但仅当值为以下值之一时:
      • 应用程序/ x-WWW窗体-urlencoded
      • 多部分/格式数据
      • 纯文本/

因此,具有内容类型application/x-www-form-urlencoded的POST将命中服务器(这意味着CSRF漏洞),但浏览器将无法访问该请求的结果.带有内容类型application/json的POST是一个"不那么简单的请求",因此浏览器会发出这样的预先请求

选项/端点HTTP/1.1
主机:https://server.com
连接:keep-alive
访问控制请求方法:POST
原点:https://evilsite.com
访问控制请求标题:内容类型
接受:*/*
Accept-Encoding:gzip,deflate,sdch
Accept-Language:es-ES,es; q = 0.8

如果服务器响应,例如:

Access-Control-Allow-Origin:http://trustedsite.com
Access-Control-Allow-Methods:GET,POST,PUT
Access-Control-Allow-Headers:content-type
Content-Type:text/html; 字符集= utf-8的

浏览器根本不会发出请求,因为

XMLHttpRequest无法加载http://server.com/endpoint.对预检请求的响应未通过访问控制检查:"Access-Control-Allow-Origin"标头包含无效值"trustedsite.com".因此,'evilsite.com'来源不允许访问.

所以我认为尼尔在谈到这一点时正在谈论这个:

同源策略仅适用于读取数据而不是写入数据.

但是,对于我向Bergi提出的原始标题显式控制,我认为就此问题而言已经足够了.

关于我对Neil的回答,我并不是说那个答案是我所有问题的答案,但它记得我关于SOP的另一个重要问题,那就是该政策仅适用于XMLHTTPRequest.

总之,我认为这个等式

  • TLS + JWT在安全的httpOnly cookie + Origin Header检查+没有XSS漏洞.

如果API在另一个域中,如SilverlightFox所说,是一个很好的选择.如果客户端位于同一个域中,那么客户端将遇到不包含Origin头的请求的麻烦.再次来自cors教程:

Origin头的存在并不一定意味着请求是跨源请求.虽然所有跨源请求都将包含Origin标头,但某些同源请求可能也包含一个.例如,Firefox在同源请求中不包含Origin标头.但Chrome和Safari在同源POST/PUT/DELETE请求中包含Origin标头(同源GET请求不具有Origin标头).

Silverlight指出了这一点.

剩下的唯一风险是客户端可以欺骗原始标头以匹配允许的来源,所以我正在寻找的答案实际上就是这个

更新:对于那些观看这篇文章的人,我怀疑使用JWT是否需要原始标题.

等式将是:

  • TLS + JWT存储在安全cookie + JWT请求标头中+没有XSS漏洞.

此外,前面的公式有httpOnly cookie但如果您在不同的域(如今许多SPA应用程序)中获得客户端和服务器,这将无法工作,因为cookie不会随每个请求一起发送到服务器.因此,您需要访问存储在cookie中的JWT令牌并将其发送到标头中.


Nei*_*gan 12

为什么同源策略不足以阻止CSRF攻击?

因为同源策略仅适用于读取数据而不是写入数据.

你想避免http://compromised.com这样的请求(来自用户的浏览器):

POST https://example.com/transfer-funds
fromAccountId:1
toAccountId:666
Run Code Online (Sandbox Code Playgroud)

合法的请求看起来像这样:

POST https://example.com/transfer-funds
fromAccountId: 1
toAccountId: 666
csrfToken: 249f3c20-649b-44de-9866-4ed72170d985
Run Code Online (Sandbox Code Playgroud)

您可以通过要求外部站点无法读取的值(CSRF令牌)来实现此目的,即在HTML表单值或响应头中.

关于Origin标头,旧浏览器不支持它,而Flash有一些漏洞让客户端更改它.基本上你会相信Adobe不会在将来搞砸任何东西......这听起来像个好主意吗?

确保您对每个HTTP请求都有CSRF保护

您只需要对具有副作用的请求进行CSRF保护,例如更改状态或发送消息

  • 并非同样的策略仅适用于读取数据而不适用于写入数据,而是如果[仅xmlhttprequest受相同策略限制,而表单POST不受限制](http://stackoverflow.com/ a / 9033631/3517383)。 (3认同)
  • @gabrielgiussi:您链接的答案特定于被提问题,不应作为该主题的一般答案.[SOP仅防止读取](http://security.stackexchange.com/a/81331/8340),而不是写入.在您链接的帖子中,可能没有从登录POST设置cookie,因为SOP将阻止cookie从登录设置后被读入浏览器.[查看此答案](http://security.stackexchange.com/a/91190/8340)关于使用`Origin`标题.简短的回答,如果您的API在另一个域上,那就没问题. (2认同)