为啥恶意站点在攻击前无法通过 GET 获取 CSRF 令牌?
Posted
技术标签:
【中文标题】为啥恶意站点在攻击前无法通过 GET 获取 CSRF 令牌?【英文标题】:Why can't a malicious site obtain a CSRF token via GET before attacking?为什么恶意站点在攻击前无法通过 GET 获取 CSRF 令牌? 【发布时间】:2017-04-12 00:01:58 【问题描述】:如果我理解正确,在 CSRF 攻击中,恶意网站 A 会告诉我的浏览器向网站 B 发送请求。我的浏览器会自动在该请求中包含我的 B cookie。虽然 A 看不到这些 cookie,但如果我已经在 B 中进行了身份验证,则请求看起来是合法的,并且所要求的任何操作都将成功执行。为了避免这种情况,每次我访问包含表单的 B 页面时,我都会收到一个 CSRF 令牌。此令牌与我的会话相关联,因此如果我向 B 发帖,我必须包含此类令牌;否则 B 拒绝我的请求。这种方案的好处是 A 将无法访问该令牌。
我有两个问题:
以上描述正确吗? 如果是这样,为什么站点 A 不能先告诉我的浏览器向 B 发送 GET,从响应中获取 CSRF 令牌,然后使用令牌现在向 B 发送 POST 吗?请注意,令牌将有效并与我的会话相关联,因为 GET 还包含我的所有 B cookie。谢谢!
【问题讨论】:
同源策略阻止站点 B 以用户身份读取站点 A 上的内容 【参考方案1】:你的描述是正确的。
如果站点 A 告诉您的浏览器转到 B 并获取令牌,那很好,但由于它是跨域请求,A 将无法访问 javascript 中的令牌(这是浏览器功能)。因此,当 A 告诉您的浏览器返回 B 并实际执行某些操作时,它仍然无法在请求中包含令牌。
也就是说,除非 B 将令牌设置为 cookie。显然,这将是有缺陷的,因为令牌 cookie 也会被发送,从而否定任何保护。因此,在这种情况下,令牌必须作为表单值或请求标头(或其他不会自动发送的东西,如 cookie)发送。
这也意味着如果 B 易受跨站脚本攻击,它也易受 CSRF 攻击,因为令牌可以被盗,但 CSRF 是一个较小的问题。 :)
【讨论】:
感谢您的回答。我还不太明白的是这个“浏览器功能”(我想你指的是 CORS)。因为执行跨域请求的站点有很多,而且他们实际上可以查看响应的内容。我能想到的最简单的例子是包含一个 src 指向不同域的图像。我没有得到的是服务器是否会为图像发送与页面不同的 Access-Control-Allow-Origin 标头,或者浏览器是否正在处理此问题。再次感谢。 其实这个特性叫做SOP,同源策略。 Javascript 只能访问从页面本身的来源下载的内容,除非其他站点发送 CORS(跨域资源共享)标头以允许请求者访问。 Javascript 也无法访问跨域图像,但它们会显示给用户。同样,可以在 iframe 中加载和显示另一个来源(除非发送 x-frame-options,但这是另一回事),但外部页面将无法访问 iframe 内容。 这是一个浏览器功能。攻击者是否可以使用其他东西,例如 curl 并向 siteB 发送请求并获取 csrf 令牌? @v1h5 是的,当然是为了他自己。但这有意义吗?不,无论如何他都会在浏览器中找到它。在 CSRF 中,攻击者利用有效用户(受害者)的现有会话,因为例如会话 cookie 是自动发送的。在 curl 他不会有一个有效的用户。 @GaborLengyel 哦,是的!这就说得通了。为蹩脚的问题道歉。尽我所能了解所有基础知识。【参考方案2】:正确。
由于浏览器的CORS 策略,站点 A 无法获取站点 B 的 csrf 令牌。
我们需要验证请求的referer
(可以伪造)。
https://en.wikipedia.org/wiki/HTTP_referer
在 url(AKA 查询字符串)中验证 crsf 令牌也是一个好习惯。
仅供参考,Laravel
,一个流行的 web 框架,在表单中使用隐藏的 CSRF 令牌字段来防止 csrf 攻击。
【讨论】:
我知道隐藏的 CSRF 令牌,这正是我在问题中所指的。所以,如果我理解正确的话,我提到的攻击是通过告诉服务器不允许向其他引用者的请求发送包含 CSRF 令牌的响应来防止的(浏览器应该确保是正确的,对吗?)。 @Mugarte Bingo.以上是关于为啥恶意站点在攻击前无法通过 GET 获取 CSRF 令牌?的主要内容,如果未能解决你的问题,请参考以下文章