游客发表
一个CSRF漏洞能有多致命?漏洞2019年,某知名社交平台因为忘记校验请求来源,挖掘攻击者只需诱导用户点击一张图片,漏洞就能让用户自动关注恶意账号、挖掘甚至修改绑定邮箱。漏洞整个过程用户毫无感知,挖掘浏览器带着用户身份悄悄把请求发出去了。漏洞这种攻击不靠暴力破解,挖掘不靠代码注入,漏洞纯粹利用的挖掘是“服务器信任了浏览器自动携带的凭证”这一特性。
挖掘CSRF有个笨办法,漏洞但特别有效——抓包改方法。挖掘登录目标站点,漏洞打开Burp Suite,挖掘找到修改个人资料或转账的漏洞请求,把POST改成GET,如果服务器还正常处理,那漏洞基本就坐实了。别笑,真有站点这么干过。我测试过一个后台管理系统,删除用户的功能点用的是POST,但服务器端没校验方法类型,改成GET后,攻击者把链接伪装成图片地址发给管理员,只要管理员浏览器还开着后台,点一下就删一个账号。
更隐蔽的是JSON CSRF。现在很多接口用application/json传数据,传统表单无法直接触发跨站请求,很多人就觉得安全了。但老式浏览器或某些插件环境里,用表单的enctype="text/plain"就能绕过Content-Type限制,照样把JSON数据发出去。我曾在某电商平台发现,它的修改收货地址接口接收JSON,但没校验Content-Type,用form表单加text/plain就能篡改地址。攻击者构造一个自动提交的form,用户访问恶意页面,收货地址就被改了,后续订单全寄到攻击者指定地点。
Token验证不是万能解药。有些系统把CSRF Token放在Cookie里,然后又在请求参数里回传,但校验时只比对两者是否一致。这种设计等于把钥匙和锁一起挂在门上——攻击者通过XSS或子域名劫持拿到Cookie里的Token,就能任意伪造请求。更蠢的是有些系统把Token写死在页面源码里,但页面被CDN缓存了,所有用户拿到的Token都一样,那这Token还不如没有。
挖CSRF最快的方式是盯住“状态变更”接口。GET请求改数据是重灾区,但POST也不保险。重点看三件事:请求头里有没有自定义字段(比如X-Requested-With)、请求体里有没有随机Token、服务端有没有校验Origin或Referer。三个都没有,直接报漏洞。有Token但Token是静态的或可预测的,也能报。有校验但校验逻辑有缺陷——比如只检查Referer是否包含域名,攻击者可以在自己的恶意页面里用meta标签伪造Referer,照样打穿。
讲个真实案例。某政务网站有个“修改密码”功能,旧密码、新密码都通过POST提交。服务器校验了Referer,但校验逻辑是“包含目标域名即可”。攻击者把恶意页面挂在目标域名的子域上——子域可能是个被遗忘的测试站,或者用户可控的评论功能里插入链接。只要Referer里带着主域名,请求就合法。最后攻击者诱导用户访问子域上的恶意页面,密码被改成攻击者预设的值,账号直接沦陷。这种问题根源在于,开发者以为校验了Referer就安全,却没想过Referer可以来自同域的其他不可信位置。
挖洞时别忽略浏览器插件的影响。某些安全插件会统一给所有请求加自定义Header,比如X-Requested-With: XMLHttpRequest。如果服务器只校验这个Header存在就放行,那插件反而帮攻击者省了事。更极端的,有些浏览器扩展会修改页面里的表单,自动填充Token,这类环境下的CSRF测试结果可能误导你——你以为Token校验有效,实际是插件在帮你兜底。
最后说点反直觉的。CSRF不一定非要跨站。同站内的CSRF——比如论坛的私信功能里,用户A给用户B发送包含恶意请求的图片链接,B点击后请求带着B的凭证发出,但来源是站内,Referer校验完全失效。这种“同站CSRF”更难防御,因为服务器无法通过来源区分是用户主动操作还是被诱导。挖掘时多注意那些用户能提交富文本或链接的模块,配合CSRF能让存储型XSS的杀伤力翻倍。
防御CSRF最靠谱的还是同步器Token模式——服务端生成随机Token,存在Session里,表单提交时带上,服务端比对。但Token一定要每次请求都刷新,且不能出现在URL里。至于那些说“用SameSite Cookie就能防CSRF”的,别全信——SameSite=Lax在跨站GET请求时仍会带Cookie,而某些浏览器对SameSite的支持存在版本差异,老版本Chrome甚至默认不拦截。安全方案没有银弹,挖洞的人永远比修洞的人多想一步。
友情链接