前言
项目是java-sec-code:https://github.com/JoyChou93/java-sec-code
CSRF一般指跨站请求伪造(Cross-site request forgery),当某个接口没有设置CSRF验证,点击了别人恶意的链接,可能会造成对这个接口发送相应的数据,造成某个数据被更改。
看下具体实例。
GET类型的CSRF
利用十分简单,构造一个IMG标签,加载的时候即可发送一个恶意get请求
<img src=https://blog.mi-di.cn/csrf?xx=11 />
POST类型CSRF
构造一个表单自动提交,可以使用ajax触发事件去自动提交。
<form action=http://blog.mi-di.cn/csrf.php method=POST>
<input type="text" name="xx" value="11" />
</form>
<script> document.forms[0].submit(); </script>
打开该页面的时候,会自动提交该表单。
另类的CSRF
可以通过一些auth认证,比如ftp,路由器等。
<img src=http://admin:admin@192.168.1.1 />
接下来看下怎么防御。
从java代码出发
进入controller文件
/src/main/java/org/joychou/controller/CSRF.java
打开http://localhost:8080/csrf/ 看下源码
这个字段就是用来表单提交,POST请求验证的csrf_token,后端生成的,提交后会和后端校验。如果我们直接通过POSTMAN或者其他post请求,缺少了csrf的token是无法完成的。如图
我们看下这个csrf的token是怎么生成的
我们跟进模板页面
/src/main/resources/templates/form.html
我们发现Spring 3.2+和 Thymeleaf 2.1+可以通过这条语句自动生成一个csrf_token来验证
<input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
可能和flask中的csrf生成的原理不同,这个csrf_token和session相捆绑,在同一个session下每次提交的csrf_token值是相同的,而flask的那个生成csrf是每次都变的。
参考: