如何在java中安全地实现CSRF令牌

时间:2015-11-25 07:06:15

标签: java json security csrf-protection

问题背后的问题: 我试图在我的java Web应用程序中阻止csrf攻击,为了实现它,我尝试了X-CSRF-Token的实现,每当请求发出时,请求将通过这样的方式传输:

POST /sessions HTTP/1.1
Host: sample.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:42.0) Gecko/20100101 Firefox/42.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
X-CSRF-Token: Ma7g2c5tpeJGcenBa0S4rGtPaHLe2o+kO5AXz+Uk2WnpaTp1J9jdZMPcE1mMSLxZ/7BA1nCBxvLKiZwtepKdoA==
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: https://sample.com
Content-Length: 67

现在作为攻击者,我试图实现这一点,我截获了帖子请求,而不是攻击令牌,我试图攻击参数,例如见下面的请求:

POST /sessions HTTP/1.1
Host: sample.com
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:42.0) Gecko/20100101 Firefox/42.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
testX-CSRF-Token: Ma7g2c5tpeJGcenBa0S4rGtPaHLe2o+kO5AXz+Uk2WnpaTp1J9jdZMPcE1mMSLxZ/7BA1nCBxvLKiZwtepKdoA==
Content-Type: application/x-www-form-urlencoded; charset=UTF-8
X-Requested-With: XMLHttpRequest
Referer: https://sample.com
Content-Length: 67

当我尝试上述请求时,CSRF令牌实现失败,我能够成功绕过csrf注入,

缓解此类攻击的最佳方法是什么?是有效的csrf注入吗?如何优化我的java web应用以防止此类攻击?

我如何实现java代码:

在我的xml中:

<http>
    <!-- ... -->
    <csrf disabled="true"/>
</http>

在我的代码中:

@EnableWebSecurity
public class WebSecurityConfig extends
WebSecurityConfigurerAdapter {

@Override
protected void configure(HttpSecurity http) throws Exception {
    http
    .csrf().disable();
}
}

在提交表单时:

<c:url var="logoutUrl" value="/logout"/>
<form action="${logoutUrl}"
    method="post">
<input type="submit"
    value="Log out" />
<input type="hidden"
    name="${_csrf.parameterName}"
    value="${_csrf.token}"/>
</form>

我也遵循here提供的推荐方法 ,在上面的场景中,csrf失败了,可能是什么缓解措施?

1 个答案:

答案 0 :(得分:1)

根据spring的文档,您可以注入自定义RequestMatcher以验证CSRF令牌的HTTP请求。 Spring为您提供了覆盖默认值的功能。

参见第16.6节http://docs.spring.io/spring-security/site/docs/current/reference/html/csrf.html

class CSRFRequestMatcher implements RequestMatcher{
    public boolean matches (HttpServletRequest req){
        //Check if request contains valid header name & header value
    }
}