漏洞原理
CSRF(Cross-site request forgery),中文名称:跨站请求伪造。
CSRF漏洞是因为web应用程序在用户进行敏感操作时,如修改账号密码、添加账号、转账等,没有校验表单token或者http请求头中的referer值,从而导致恶意攻击者利用普通用户的身份(cookie)完成攻击行为
由于目标网站无token或referer限制,攻击者可以利用用户的身份,执行请求
跨站请求伪造,利用了网站允许攻击者预测特定操作所有细节这一特点。由于浏览器自动发送会话cookie等认证凭证,导致攻击者可以创建恶意的web页面来产生伪造请求。这些伪造的请求很难和合法的请求区分开
例如:
银行网站A,它以GET请求来完成银行转账的操作,如:
1 | http://www.mybank.com/Transfer.php?toBankId=11&money=1000 |
危险网站B,它里面有一段HTML的代码如下:
<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>
登陆银行网站A后,在同一个浏览器去访问B网站的一个上面的请求,这个时候会发现你的账户会少了1000块。
漏洞危害
攻击者可以让受害者用户修改任何允许修改的数据,执行任何用户允许的操作,例如修改密码,登录注销等
漏洞测试
1.GET类型的CSRF的检测
如果有token等验证参数,先去掉参数尝试能否正常请求。如果可以,即存在CSRF漏洞
2.POST类型的CSRF的检测
如果有token等验证参数,先去掉参数尝试能否正常请求。如果可以,再去掉referer参数的内容,如果仍然可以,说明存在CSRF漏洞,可以利用构造外部form表单的形式,实现攻击。如果直接去掉referer参数请求失败,这种还可以继续验证对referer的判断是否严格,是否可以绕过
漏洞修复
添加验证码:在一些特殊请求页面增加验证码,验证码强制用户必须与应用进行交互,才能完成最终请求
检测refer:检测refer值,来判断请求来源是否合法。
Token:在每个请求中设置Token是一种流行的方式来防御CSRF。CSRF攻击的原理:攻击者可以猜测到用户请求,现在在每个请求中加一个随机的Toekn值。
Token要足够随机————只有这样才算不可预测
Token是一次性的,即每次请求成功后要更新Token————这样可以增加攻击难度,增加预测难度
Token要注意保密性————敏感操作使用post,防止Token出现在URL中
代码示例
Token使用
说明:在重要操作的表单中增加会话生成的Token字段,一次一用,提交后在服务端校验该字段。
Java示例:用户登录后生成token:
1 | //获取用户的输入验证业务逻辑 |
页面(模板)渲染时输出token
输出到链接:
1 | <a href=logout.jsp?token=<%sessLogin.getAttribute("token")%>">logout</a> |
服务端逻辑检查中验证token是否正确:
1 | if (sessLogin.getAttribute("token").equals(request.getParameter("token"))) { |
二次验证
说明:在关键表单提交时,要求用户进行二次身份验证,如密码、图片验证码、短信验证码等。
Referer 验证
说明:检验用户请求中Referer字段是否存在跨域提交的情况。
Java示例:检查请求连接的referer是否合法
1 | String expectedRefererStartsWith = “https://xxx.test.com” |
Reference
https://sobug.com/article/detail/10
https://xz.aliyun.com/t/7450#toc-3
https://blog.csdn.net/weixin_45728976/article/details/104506544