小议 CSRF 攻击
CSRF(Cross-site request forgery),即跨站请求伪造,本质就是攻击者伪造你的身份发送请求。
攻击流程
在 Google 上找了一张流程图:
- 用户访正常登录访问 mybank.com 网站,登录成功后,mybank 服务端会产生 Cookie 信息给浏览器;
- 在用户不登出 mybank.com 的情况下访问攻击网站 attacker.com 的攻击链接,此链接会直接访问 mybank.com,此时会携带着 mybank 的 Cookie,从而执行恶意脚本;
首先这里不能只局限于 Cookie,比如 Token,也是可以通过抓包分析获取的。也就是说 CSRF 的本质就是攻击者伪造你的身份发送请求,那么身份用什么体现呢,就是 Cookie 或者 Token。
示例
先看一个简单的模拟例子:
用户登录页面:
<form action="/login" method="post" enctype="multipart/form-data">
<p> 用户名:<input type="text" name="username">
<p> 密码:<input type="text" name="password">
<input type="submit" value="提交">
</form>
后台代码:
@RequestMapping("login")
public Object login(@RequestParam("username")String username, @RequestParam("password")String password, HttpServletResponse response){
Cookie cookie = new Cookie("8080Cookie", "123456");
cookie.setPath("/");
response.addCookie(cookie);
return "OK";
}
用户登录成功后这里会生成一个 Cookie:
攻击页面:
<h2>attack</h2>
<form action="http://localhost:8080/pay" method="post" enctype="multipart/form-data">
<input type="text" name="money" value = "1000" style="visibility: hidden;">
<input type="submit" value="恭喜你中奖了">
</form>
这里可以做成比如超链接等,如果用户点击了这个按钮,那么实际会携带着用户的 Cookie 信息去访问之前的系统,即“伪造你的身份发送请求”:
后端代码:
@RequestMapping("pay")
public Object pay(@RequestParam("money")Integer money, HttpServletRequest request){
System.out.printf("获取了 Cookie:%s",
Stream.of(request.getCookies()).collect(Collectors.toMap(Cookie::getName, Cookie::getValue)).get("8080Cookie"));
return String.format("扣掉了 %d 元钱",money);
}
这样会出现跨站请求成功:
如果无法获取 Cookie 的话,后端代码会抛出 NPE 异常。
防御方式
总得来说没有绝对的防御方式,其实将**过程设置的越复杂,也算是一种成功的防御。
通过 HTTP 请求头中的 Referer 和 Origin 属性
这两种方式其实并不算可靠,这里借用一篇博客中的描述(相关链接在文末):
- referer属性
记录了该http请求的来源地址,但有些场景不适合将来源URL暴露给服务器,所以可以设置不用上传,并且referer属性是可以修改的,所以在服务器端校验referer属性并没有那么可靠
- origin属性
通过XMLHttpRequest、Fetch发起的跨站请求或者Post方法发送请求时,都会带上origin,所以服务器可以优先判断Origin属性,再根据实际情况判断是否使用referer判断。
CSRF Token
这种应该是常用的一种方式,就是浏览器向服务器发送请求后,服务器端生成一个随机的 Token,然请求的时候就携带这个 Token,服务器端再进行校验,关于这个可以参看这两篇博客:
- https://blog.csdn.net/Dongguabai/article/details/81150989
- https://blog.csdn.net/Dongguabai/article/details/81151035
设置 SameSite 属性
Chrome 51 开始,浏览器的 Cookie 新增加了一个 SameSite
属性,用来防止 CSRF 攻击和用户追踪。
关于 SameSite 属性,可以参看:
- http://www.ruanyifeng.com/blog/2019/09/cookie-samesite.html
但是在动静分离的情况下,这时候静态资源会单独部署,这时候 SameSite 属性限制比较大。所以最常见的还是基于 Token 的方式去处理。
References
下一篇: centos Linux内核 升级