Hacker News 中文摘要

RSS订阅

跨站请求伪造 -- Cross-Site Request Forgery

文章摘要

跨站请求伪造(CSRF)是一种攻击方式,攻击者利用用户的cookie或网络位置,诱使浏览器向目标网站发送请求。所有使用cookie进行身份验证的应用程序都需要防范CSRF攻击,其核心在于识别来自不可信源的认证请求,而非防止攻击者发起任意请求。与跨域资源共享(CORS)不同,CSRF关注的是接受可能改变状态的请求。

文章总结

跨站请求伪造(CSRF)攻击及其防御措施

跨站请求伪造(CSRF)是一种攻击方式,攻击者利用用户的浏览器发送请求,借助用户的身份验证信息(如Cookie)来执行未经授权的操作。例如,攻击者可以通过在受害者的浏览器中嵌入一个隐藏的表单,诱导浏览器向目标网站发送POST请求,从而在用户不知情的情况下执行某些操作(如转账)。

几乎所有使用Cookie进行身份验证的应用程序都需要防范CSRF攻击。与跨域资源共享(CORS)不同,CSRF关注的是接受来自不可信源的请求,即使攻击者无法看到响应。浏览器之所以允许这些请求,主要是出于历史兼容性考虑,禁用第三方Cookie可能会破坏单点登录(SSO)流程。

同站与同源的区别

为了有效防御CSRF,首先需要明确什么是跨站或跨源请求。同站请求指的是来自同一顶级域名的请求,而同源请求则要求协议、域名和端口完全相同。例如,https://app.example.comhttp://app.example.com是同站但不同源的请求。由于HTTP请求容易受到中间人攻击,因此HTTPS和HTTP之间的信任差异尤为显著。

防御措施

  1. 双提交或同步令牌:经典的防御方法是使用CSRF令牌,即在请求中提交一个随机值,并与存储在Cookie或服务器端的值进行比对。双提交令牌容易受到同站Cookie设置的攻击,可以通过__Host-前缀或绑定用户会话的签名元数据来缓解。

  2. SameSite Cookie:通过将身份验证Cookie设置为SameSite=LaxStrict,可以防止这些Cookie在跨站请求中被发送。然而,SameSite Lax的默认设置在某些浏览器中并未有效实施,导致其防御效果有限。

  3. 非简单请求:虽然CORS并非设计用于防御CSRF,但非简单请求(如设置了自定义头部的请求)会触发预检请求(OPTIONS),从而增加攻击难度。

  4. Fetch元数据:浏览器引入了Fetch元数据,特别是Sec-Fetch-Site头,用于标识请求的来源(跨站、同站、同源或用户直接发起)。这是目前推荐的CSRF防御方法,但仅适用于HTTPS和localhost等可信源。

2025年的CSRF防御建议

为了有效防御CSRF,应用程序应拒绝来自跨源的非安全请求。最开发者友好的方法是使用Fetch元数据,无需额外的配置或工具。具体步骤如下:

  1. 允许所有GET、HEAD或OPTIONS请求,因为这些方法被认为是安全的。
  2. 如果Origin头匹配可信源列表,则允许请求。
  3. 如果存在Sec-Fetch-Site头,且其值为same-originnone,则允许请求,否则拒绝。
  4. 如果既没有Sec-Fetch-Site也没有Origin头,则允许请求,因为这些请求不来自现代浏览器。
  5. 如果Origin头的主机与Host头匹配,则允许请求,否则拒绝。

对于特殊情况(如SSO),应提供严格限制的绕过机制。

总结

CSRF攻击的防御需要结合多种技术手段,包括令牌、SameSite Cookie、Fetch元数据等。随着浏览器技术的进步,Fetch元数据已成为现代浏览器中防御CSRF的首选方法。开发者应确保应用程序能够有效识别和拒绝来自不可信源的请求,从而保护用户的安全。

评论总结

  1. 对Sec-Fetch的积极评价

    • 评论1的作者nchmy表示对Sec-Fetch的发现感到兴奋,认为它可以替代当前应用中使用的令牌,减少麻烦。
    • 引用:"Very excited to start using it in some applications where tokens are currently used - what a hassle to deal with those."
    • 中文翻译:"非常兴奋地开始在一些使用令牌的应用中使用它——处理这些令牌真是麻烦。"
  2. 对GET请求安全性的质疑

    • 评论2的作者MajesticHobo2对文章中关于GET、HEAD和OPTIONS请求是安全方法的观点表示不同意,指出许多应用允许GET请求改变状态。
    • 引用:"Plenty of apps violate this assumption and do allow GET requests to alter state."
    • 中文翻译:"许多应用违反了这个假设,确实允许GET请求改变状态。"
  3. 对SameSite cookie属性的疑问

    • 评论3的作者akersten对文章中SameSite cookie属性不能完全解决CSRF问题的解释表示不理解,认为SameSite=Secure的设计初衷就是解决CSRF。
    • 引用:"I thought that was the whole design intent of SameSite=Secure on an HTTPS cookie, was to fix CSRF."
    • 中文翻译:"我以为SameSite=Secure在HTTPS cookie中的设计初衷就是解决CSRF。"
  4. 对Origin header的认可

    • 评论4的作者AgentME对文章的及时性表示赞赏,认为Origin header的广泛支持使得传统的CSRF令牌变得不必要。
    • 引用:"I’ve gotten some odd looks for telling people that classic CSRF tokens are unnecessary work since the Origin header became widely supported."
    • 中文翻译:"自从Origin header被广泛支持后,我告诉人们传统的CSRF令牌是不必要的,这让我得到了一些奇怪的眼神。"
  5. 对CSRF保护普及性的疑问

    • 评论5的作者fabian2k询问是否不再需要CSRF令牌来完全防止CSRF攻击,并询问其他生态系统(如.NET/C#)是否也在实施类似的保护措施。
    • 引用:"So am I understanding it right that you don’t need any CSRF tokens anymore to fully protect against CSRF attacks?"
    • 中文翻译:"那么我的理解是否正确,即不再需要任何CSRF令牌来完全防止CSRF攻击?"