当前位置:首页 > 知识

跨站请求伪造漏洞修复方式包括

跨站请求伪造(CSRF)的跨站修复,核心就一句话:让服务器能分辨“这个请求是请求用户主动发的”还是“恶意网站偷偷替用户发的”。听起来简单,伪造但实际落地时坑不少。漏洞我见过太多团队只加了个Token就以为万事大吉,修复结果被绕过——下面直接说能用的包括修复方式。

第一招:同步器令牌(Synchronizer Token)。跨站这是请求最基础也最常用的。服务器在渲染表单时生成一个随机且不可预测的伪造token,存在session里,漏洞同时放进页面隐藏字段。修复用户提交表单时,包括服务器比对提交的跨站token和session里的值。不匹配就拒绝。请求关键细节:token必须每次会话都重新生成,伪造不能复用;而且不要用GET请求传token——浏览器历史、代理日志、referer都会泄露它。我见过有人把token塞进URL里,那是给攻击者递刀子。

第二招:双重提交Cookie(Double Submit Cookie)。这招不需要服务端存session,适合无状态API。做法是:服务器生成token,写入cookie(比如叫csrf_token),同时要求前端在请求头(比如X-CSRF-Token)里也带上同样的值。服务器只比对cookie里的值和请求头的值是否一致。为什么有效?因为跨站请求时,浏览器会自动带上cookie,但攻击者无法读取cookie的值,所以没法在请求头里伪造出相同的token。但注意:如果你的站点存在子域劫持或XSS,这招就废了。另外,cookie必须设置SameSite=Lax或Strict,否则默认Lax在某些场景下还是会被发送。

说到SameSite,这是第三招,也是最省事的。直接给cookie加上SameSite=Strict属性,浏览器就不会在跨站请求时携带该cookie。现代浏览器(Chrome 80+、Firefox、Safari)基本都支持。但有个坑:Strict模式会导致用户从外部链接跳转到你的站点时,首次请求不带cookie,比如用户从邮件点链接进入登录页,session可能失效,体验变差。Lax模式则允许顶级导航的GET请求带cookie,但POST、PUT、DELETE等跨站请求不带——这对大多数业务够用了。我建议能用Lax就用Lax,别追求Strict,除非你的站点对安全性要求极端高。

第四招,检查Origin和Referer头。服务器校验请求的Origin头(或Referer)是否来自自己的域名。这招能防住大部分CSRF,但有两个漏洞:一是某些老浏览器不发Origin头,你得降级到Referer;二是Referer可能被隐私插件或浏览器策略去掉。所以这招只能作为辅助,不能单独用。实际案例:某电商平台只靠Referer校验,结果攻击者用meta name="referrer" content="no-referrer"标签就能让请求不带Referer,直接绕过——后来他们加了Token才补上。

最后提一个容易被忽略的:自定义请求头。比如强制要求所有敏感操作的AJAX请求带上X-Requested-With: XMLHttpRequest。因为跨站表单提交没法自定义请求头(除非用CORS配合,但CORS会预检拦截),所以这招对纯表单CSRF有效。但如果你有JSONP接口或者允许跨域资源共享,那就别用了。

别把所有鸡蛋放一个篮子里。实际修复时,我建议组合使用:SameSite=Lax + 双重提交Cookie,或者同步器Token + Origin检查。别忘了,如果你的站点有XSS漏洞,以上所有招数都是白搭——攻击者直接通过脚本读取token或cookie。先修XSS,再谈CSRF。

还有个细节:登录和注销接口也要防护。很多人只保护业务接口,忘了登录接口。攻击者可以用你的登录接口做“登录CSRF”,强制用户登录攻击者的账号,然后诱导用户在其账号里操作(比如绑定攻击者的手机号)。修复方式一样,登录表单加上token或SameSite。

最后说个反直觉的案例:某金融App,后端是Java Spring Security,默认带CSRF保护,但前端是Angular,开发者嫌麻烦把CSRF过滤器关了,只保留了JWT认证。结果攻击者构造了一个恶意图片链接,用户浏览器发了个GET请求去转账(因为该App把转账参数放在URL里),直接中招。别以为用了JWT就安全,JWT只解决身份认证,不解决请求来源验证。CSRF修复的本质是“验证请求意图”,跟认证方式无关。

分享到: