1、CSRF是什么

CSRF(Cross Site Request Forgery),中文是跨站点请求伪造。CSRF攻击者在用户已经登录目标网站之后,诱使用户访问一个攻击页面,利用目标网站对用户的信任,以用户身份在攻击页面对目标网站发起伪造用户操作的请求,达到攻击目的。

【20200129】SpringBoot   CSRF - 图1 836049-20160322214747901-1548153978.jpg

2、CSRF攻击的本质原因

CSRF攻击是源于Web的隐式身份验证机制!Web的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的。CSRF攻击的一般是由服务端解决。

3、CSRF工具的防御手段
  1. 尽量使用POST,限制GET
    GET接口太容易被拿来做CSRF攻击,看第一个示例就知道,只要构造一个img标签,而img标签又是不能过滤的数据。接口最好限制为POST使用,GET则无效,降低攻击风险。
    当然POST并不是万无一失,攻击者只要构造一个form就可以,但需要在第三方页面做,这样就增加暴露的可能性。
  2. 浏览器Cookie策略
    IE6、7、8、Safari会默认拦截第三方本地Cookie(Third-party Cookie)的发送。但是Firefox2、3、Opera、Chrome、Android等不会拦截,所以通过浏览器Cookie策略来防御CSRF攻击不靠谱,只能说是降低了风险。
    PS:Cookie分为两种,Session Cookie(在浏览器关闭后,就会失效,保存到内存里),Third-party Cookie(即只有到了Exprie时间后才会失效的Cookie,这种Cookie会保存到本地)。
  3. 加验证码
    验证码,强制用户必须与应用进行交互,才能完成最终请求。在通常情况下,验证码能很好遏制CSRF攻击。但是出于用户体验考虑,网站不能给所有的操作都加上验证码。因此验证码只能作为一种辅助手段,不能作为主要解决方案。
  4. Referer Check
    Referer Check在Web最常见的应用就是“防止图片盗链”。同理,Referer Check也可以被用于检查请求是否来自合法的“源”(Referer值是否是指定页面,或者网站的域),如果都不是,那么就极可能是CSRF攻击。
    但是因为服务器并不是什么时候都能取到Referer,所以也无法作为CSRF防御的主要手段。但是用Referer Check来监控CSRF攻击的发生,倒是一种可行的方法。
  5. Anti CSRF Token
    现在业界对CSRF的防御,一致的做法是使用一个Token(Anti CSRF Token)。
    例子:
    用户访问某个表单页面。
    服务端生成一个Token,放在用户的Session中,或者浏览器的Cookie中。
    在页面表单附带上Token参数。
    用户提交请求后, 服务端验证表单中的Token是否与用户Session(或Cookies)中的Token一致,一致为合法请求,不是则非法请求。
    这个Token的值必须是随机的,不可预测的。由于Token的存在,攻击者无法再构造一个带有合法Token的请求实施CSRF攻击。另外使用Token时应注意Token的保密性,尽量把敏感操作由GET改为POST,以form或AJAX形式提交,避免Token泄露。
    4、在spring boot中使用spring security的filter防止CSRF攻击
  • 在pom中添加相关依赖
  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-freemarker</artifactId>
  5. </dependency>
  6. <!-- Security (used for CSRF protection only) -->
  7. <dependency>
  8. <groupId>org.springframework.security</groupId>
  9. <artifactId>spring-security-web</artifactId>
  10. </dependency>
  11. </dependencies>
  • 在app启动时,添加CsrfFilter
  1. @SpringBootApplication
  2. public class Application extends WebMvcConfigurerAdapter {
  3. @Bean
  4. public FilterRegistrationBean csrfFilter() {
  5. FilterRegistrationBean registration = new FilterRegistrationBean();
  6. registration.setFilter(new CsrfFilter(new HttpSessionCsrfTokenRepository()));
  7. registration.addUrlPatterns("/*");
  8. return registration;
  9. }
  10. public static void main(String[] args) {
  11. SpringApplication.run(Application.class, args);
  12. }
  13. }
  • form中添加CSRF的hidden字段
  1. <input name="${(_csrf.parameterName)!}" value="${(_csrf.token)!}" type="hidden">
  • ajax中添加CSRF的头
  1. xhr.setRequestHeader("${_csrf.headerName}", "${_csrf.token}");