Java代码审计漏洞-CSRF跨站请求伪造
Java代码审计漏洞-CSRF跨站请求伪造
若要通过代码审计去挖掘 CSRF 漏洞,一般需要首先了解该开源程序的框架。CSRF 漏洞一般会在框架中存在防护方案,所以在审计CSRF漏洞时,首先要熟悉框架对CSRF的防护方案,若没有防护方案,则以该框架编写的所有Web程序都可能存在CSRF漏洞。若有防护方案,则可以首先去查看增删改请求中是否有token、formtoken、csrf-token等关键字,若有则可以进一步去通读该Web 程序对CSRF的防护源码,来判断其是否存在替换token值为自定义值并重复请求漏洞、重复使用 token 等漏洞。此外还要关注源程序是否对请求的Referer进行校验等。
框架Spring Security+Thymeleaf 中默认自动防御 csrf, 防御的原理就是生成 csrfToken 保存在 HttpSession 或者 Cookie 中。请求到来时,从请求中提取出来 csrfToken,和保存的 csrfToken 做比较,进而判断出当前请求是否合法。
Spring Security
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated()
.and()
.formLogin()
.and()
.csrf()
.disable();
}
}
Thymeleaf
<body>
<form action="/hello" method="post">
<input type="hidden" th:value="${_csrf.token}" th:name="${_csrf.parameterName}">
<input type="submit" value="hello">
</form>
</body>
Model
@GetMapping("/hello")
public String hello2() {
return "hello";
}
如果是前后端分离项目,Spring Security 也提供了解决方案。放在 Cookie 中返回前端
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated()
.and()
.formLogin()
.and()
.csrf().csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
}
}
框架没有自动防护,手写防护方案情况如下
Referer 过滤不严
1.从用户的请求头中取得 Referer 值
2.判断其是否为空。若为空,则跳转至首页;
3.若不为空,则进行下一步判断。
判断Referer是否以 www.testdomain.com 开头,若不是,则跳转至首页;
若是,则执行该操作请求。可以看到,这里逻辑判断的关键点在于第二步。
该判断仅仅判断请求 Referer 字段是否以www.testdomain.com开头,若我们构建一个二级域名为www.testdomain.com.hacker.com 的地址,则可能成功绕过该判断,从而进行 CSRF攻击。
token 可重用
判断 token 是否可用的核心代码
1.首先通过 generateToken() 方法生成一个属于该用户的 token,然后将其保存在服务端,并且将其镶嵌到 HTML页面中的<input>标签内。
2.当用户提交操作的时候,程序会比对该标签的 token 值是否等于服务端的 token 值,如果相等,则判断该操作是用户本人操作,而不是受到了CSRF 攻击。
其实这段源程序对于 CSRF 的防御机制是存在问题的。该段源程序在用户成功登录后,生成了唯一的令牌,直至该用户注销前,该 token 都是有效的。这就可能导致一个问题,如果这个 token 被盗用或者泄露,那么就可能导致CSRF 漏洞的发生。
漏洞防御
1)STP(Synchronizer Token Pattern,令牌同步模式),这种防御机制是当用户发送请求时,服务器端应用将token 嵌入HTML表格中,并发送给客户端。客户端提交HTML表格,会将令牌发送到服务端,令牌的验证是由服务端实行的。令牌可以通过任何方式生成,只要确保其随机性和唯一性。这样就能够确保攻击者发送请求的时候,由于没有该令牌而无法通过验证。
2)检查Referer字段。HTTP 头中有一个 Referer 字段,这个字段用以标明请求来源于哪个地址。在处理敏感数据请求时,一般情况下,Referer 字段应该与请求地址位于同一域名下。而如果是 CSRF 攻击传递来的请求,Referer 字段会是包含恶意攻击载荷的地址,通过这种判断能够识别出 CSRF 攻击。这种防御手段的关键点在于如何建立合适的校验机制。
3)添加校验token。CSRF 的本质是攻击者通过欺骗用户去访问自己设置的地址,所以如果在所有用户进行敏感操作时,要求用户浏览器提供未保存在Cookie中且攻击者无法伪造的数据作为校验,那么攻击者就无法再进行 CSRF 攻击。这种方式通常是在请求时增加一个加密的字符串token,当客户端提交请求时,这个字符串token也被一并提交上去以供校验。当用户进行正常的访问时,客户端的浏览器能够正确得到并传回这个字符串token
还有很多其他方式,比如验证码机制、自定义http请求头方式、Origin字段等,但是这些方法都存在各自的问题,如友好度差、存在机制绕过的可能等,因而只是作为辅助防御方式使用。
参考文章
java代码审计入门篇
本文来自博客园,作者:九天揽月丶,转载请注明原文链接:https://www.cnblogs.com/-meditation-/articles/16223797.html