`

spring-security(二十四)CSRF

阅读更多
1.什么是CSRF攻击
下面我们以一个具体的例子来说明这种常见的攻击模式
1.1 假定某个银行的网站提供让当前登录用户给其他账号转账的功能,转账请求的格式如下
POST /transfer HTTP/1.1
Host: bank.example.com
Cookie: JSESSIONID=randomid; Domain=bank.example.com; Secure; HttpOnly
Content-Type: application/x-www-form-urlencoded
amount=100.00&routingNumber=1234&account=9876

1.2 现在有一个用户登录到了这个银行的网站并且进行了认证,在未logout的情况下访问了一个恶意网站,恶意网站包含如下html代码段
<form action="https://bank.example.com/transfer" method="post">
   <input type="hidden"name="amount" value="100.00"/> 
   <input type="hidden"name="routingNumber" value="evilsRoutingNumber"/> 
   <input type="hidden" name="account" value="evilsAccountNumber"/>
   <input type="submit" value="领取奖品"/> 
</form>

这时如果用户点击了【领取奖品】按钮,你将给那个恶意攻击者的账户转入100元,这是因为虽然恶意网站不能获取到用户cookie信息,但是当点击【领取奖品】按钮访问银行网站时,cookie信息还是会一起发送。更糟糕的是,借助于javascript,上面的过程可以自动执行,不需要等待用户点击【领取奖品】按钮,只要你打开了这个页面,你的钱就被偷走了,这也是我们常见的钓鱼网站的做法。

像这样虽然用户访问的是另一个网站,但是这个网站却伪装成当前认证用户访问用户正在访问的网站以实现攻击的方式称为CSRF。

2.同步token模式
2.1 从上面的例子可以看出,无论转账请求是从银行自己的网站发出,还是从恶意网站发出,对于银行的服务端来说内容是一样的,所以单纯从服务端来讲我们没法过滤掉那些恶意的请求。如果我们能采取一种措施让银行的正常页面发请求时给服务器提供一个凭证,并且这个凭证是恶意网站所不能提供的,这样服务器端就可以很容器拒绝掉那些非法的请求了。
同步token就是这样的一种方式,他要求在客户端发起请求时,除了cookie信息外,还需要提供一个随机的token值作为参数。当服务器收到一个请求后,会先解析出这个token值,再和期望的值进行比较,如果不匹配则拒绝提供服务。
2.2 在实际项目中,我们可以放宽上面的规则,只要求那些会修改信息的请求才提供token值,因为根据同源策略,那些恶意网站是不能获取到我们正常请求的响应结果的。追加完token后,我们的请求示例如下:
POST /transfer HTTP/1.1
Host: bank.example.com
Cookie: JSESSIONID=randomid; Domain=bank.example.com; Secure; HttpOnly
Content-Type: application/x-www-form-urlencoded
amount=100.00&routingNumber=1234&account=9876&_csrf=<secure-random>

这样,因为恶意网站不能狗提供_csrf对应的随机值,伪造的请求将不会被服务器接受。
3.如何利用spring security防止csrf攻击
3.1 采用正确的http动词
动词 作用 类比数据库操作
GET从服务器获取信息select
POST在服务器上新创建一个资源insert
PUT更新服务器上的一个资源,本次请求包含完整的信息 update
PATCH更新服务器上的一个资源,包含部分信息 update
DELETE删除服务器上的一个资源 delete
HEAD向服务器索要与GET请求相一致的响应,只不过只有头部信息,响应体将不会被返回。  无
TRACE回显服务器收到的请求,主要用于测试或诊断  无
OPTIONS返回服务器针对特定资源所支持的HTTP请求方法  无

确保对信息进行修改的请求其动词一定是post、put、patch、delete中的一种。
3.2配置CSRF
对于spring security4.0+无论是xml配置形式还是Java config形式,csrf默认都是开启的,可以通过如下方式关闭
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  @Override
  protected void configure(HttpSecurity http) throws Exception { 
  http
   .csrf().disable();
  }
}

默认情况下,如果csrf检查失败,spring security会返回客户端一个403码,可以通过http.csrf()方法返回的CsrfConfigurer类来定制AccessDeniedHandler,实现自己的逻辑。
3.3界面包含CSRF相关设定
我们要确保在所有执行post、put、patch、delete的请求中包含CSRF token值,最直接的方式是使jstl表达式从request中获取到_csrf对应的值,如下
 <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>

另外spring 也为我们提供了两个方便的jsptag。具体例子参考csrf jsptag
另外如果我们采用thymeleaf模版引擎,也会自动的为form表单追加对应的csrf属性。
具体例子参考[url url=https://github.com/fengyilin/spring-security-sample/tree/master/security-samples-javaconfig-csrf-thymeleaf]csrf-thymeleaf[/url]
3.4 CookieCsrfTokenRepository
在某些场合下,我们可能会需要将csrf token值存储在cookie中,此时可以用CookieCsrfTokenRepository来实现这个功能,默认情况下,写入到cookie中的key是XSRF-TOKEN,读取时从request header的X-XSRF-TOKEN中或者parameter的_csrf中读取。可以用如下代码段配置
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	@Override
	protected void configure(HttpSecurity http) throws Exception { 
	http
   		.csrf()
    	.csrfTokenRepository(new CookieCsrfTokenRepository());
	} 
}

默认情况下设置到cookie中的信息不能够通过js读取,如果需要js访问的话需要明确设定
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	@Override
	protected void configure(HttpSecurity http) throws Exception { 
		http
  		 .csrf()
   		 .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse());
	}
}

4 使用csrf的一些注意点
4.1 Timeouts
默认情况下,csrf token存储在httpsession中,当session过期时AccessDeniedHandler会收到一个InvalidCsrfTokenException,如果我们使用的是spring security默认的AccessDeniedHandler,客户端将会收到一个简单的403错误(因为 CSRF_FILTER在认证filter的后面),对于这个问题,我们可以采用下面几种方式处理
  • 在页面里面追加js,当session快过期时通知用户,可以通过用户点击按钮的方式刷新session
  • 自定义AccessDeniedHandle,自己处理InvalidCsrfTokenException
  • 也可以将csrf token存入CsrfTokenRepository中(如CookieCsrfTokenRepository),这样就不会有过期问题,虽然存入token中有安全隐患,不过大多数情况下都不会有问题

4.2 登录问题
如果在登录页面也启用csrf token保护,就需要在登录前生成CsrfToken时创建HttpSession,这时就需要考虑如果用户在登录页面长时间停留,会引起session过期问题,当登录时直接返回403(没权限登录--),现在通用的解决方法是采用JavaScript在点击登录时,先获取token值,接着在提交登录请求,这样session在登录时才创建,用户就可以在登录界面停留任意时间了,利用CsrfTokenArgumentResolver我们很容易实现这样的功能
@RestController
public class CsrfController {
 	@RequestMapping("/csrf")
	public CsrfToken csrf(CsrfToken token) { 
	return token;
	} 
}

此时需要注意,为了安全不能把cors功能应用到这个endpoint上。
4.3 Logout
默认情况下,启用csrf token后,LogoutFilter只接收Post请求,并且logout时还需要提供csrf token值
@SuppressWarnings("unchecked")
private RequestMatcher getLogoutRequestMatcher(H http) {
	if (logoutRequestMatcher != null) {
		return logoutRequestMatcher;
	}
	if (http.getConfigurer(CsrfConfigurer.class) != null) {
		this.logoutRequestMatcher = new AntPathRequestMatcher(this.logoutUrl, "POST");
	}
	else {
		this.logoutRequestMatcher = new OrRequestMatcher(
			new AntPathRequestMatcher(this.logoutUrl, "GET"),
			new AntPathRequestMatcher(this.logoutUrl, "POST"),
			new AntPathRequestMatcher(this.logoutUrl, "PUT"),
			new AntPathRequestMatcher(this.logoutUrl, "DELETE")
		);
	}
	return this.logoutRequestMatcher;
}

如果Logout操作安全性没有那么高,实现时不想这么复杂,可以通过下面代码段配置
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
	@Override
	protected void configure(HttpSecurity http) throws Exception {
	 http
		.logout()
		.logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
	} 
}

这时可以用任意的HTTP method执行logout操作
4.4 文件上传
可通过以下两种方式解决
  • 将MultipartFilter放到spring security 相关filter前面
  • public class SecurityApplicationInitializer extends AbstractSecurityWebApplicationInitializer {
    	@Override
    	protected void beforeSpringSecurityFilterChain(ServletContext servletContext) { 
    	insertFilters(servletContext, new MultipartFilter());
    	} 
    }
  • 在上传文件对应的action中追加token值
  •    <form action="./upload?${_csrf.parameterName}=${_csrf.token}" method="post" enctype="multipart/form- data">
       
    分享到:
    评论

    相关推荐

      spring-security Jar包

      Spring Security 是一个强大的且高度可定制的身份验证和访问控制框架,用于保护基于Java的应用程序。这个框架被广泛应用于Web应用程序,提供了一套全面的安全解决方案,包括用户认证、授权、会话管理以及防止常见...

      spring-boot spring-security-oauth2 完整demo

      Spring Security是Spring生态下的一个安全模块,它提供了全面的安全管理解决方案,包括身份验证、授权、CSRF防护等。Spring Security的配置灵活性高,能够适应各种安全需求,而且与Spring Boot结合使用时,可以无缝...

      spring-security3.1.4 完整的jar包

      2. **spring-security-web-3.1.4.RELEASE.jar**:这个模块主要处理Web应用程序中的安全性问题,包括HTTP安全头设置、登录页面处理、CSRF(跨站请求伪造)防护等。它也提供了FilterChainProxy,用于管理安全过滤器链...

      spring security 4.0.0所需jar包

      如果涉及到复杂的Web安全问题,如CSRF防护,则可能需要`spring-security-web`。 总的来说,Spring Security 4.0.0的这些jar包是构建安全、健壮的Java Web应用不可或缺的组件,它们提供了一套灵活且强大的工具,可以...

      spring-security源代码

      默认情况下,Spring Security开启CSRF防护,通过生成并验证CSRF令牌,防止跨站请求伪造攻击。 6. **Web表达式访问控制**: 使用Spring Expression Language (SpEL)进行细粒度的URL访问控制,如`@PreAuthorize`和`...

      spring-boot-security

      7. **状态保持(CSRF)**:默认情况下,Spring Security开启CSRF(跨站请求伪造)保护。若不需要,可以通过`http.csrf().disable()`关闭。 通过以上介绍,我们可以看出Spring Boot Security提供了丰富的功能,能够...

      spring-security-jwt-csrf:使用Spring Security,Spring Boot和Vue js进行无状态JWT身份验证的演示

      基于令牌(Spring Security, 和CSRF) 客户端构建工具 ,Webpack,npm 服务器构建工具 Gradle Безопасность( Security ) JWT令牌 ДлягенерацииипроверкиJWT以及 。 JJWT -...

      spring-security-oauth2与spring-security-web 3.1.2 源码

      4. **CSRF Protection**: 为了防止跨站请求伪造(Cross-Site Request Forgery),`spring-security-web`包含了内置的CSRF防护机制,它要求每个修改状态的请求携带一个CSRF令牌。 接下来,`spring-security-oauth2`...

      spring-security-material-master.zip

      Spring Security 是一个强大的安全框架,主要用于Java web应用的安全管理。在Spring Boot中,Spring Security 提供了一种简单而有效的方式来保护应用程序,防止未经授权的访问。本资料“spring-security-material-...

      springsecurity所有jar包

      3. **spring-security-web**:此模块专注于Web安全,包括登录、注销、CSRF防护、会话管理等功能。它提供HTTP安全拦截过滤器链,如`DelegatingFilterProxy`,可以与Spring的DispatcherServlet集成。 4. **spring-...

      spring-security-3.1.4

      5. **CSRF保护**:为了防止跨站请求伪造攻击,Spring Security提供了内置的CSRF保护机制。 6. **Remember Me服务**:用户可以设置“记住我”选项,以便在下次访问时无需重新登录。 7. **国际化**:Spring Security...

      Teino1978-Corp-spring-security-csrf-token-interceptor-

      #spring-security-csrf令牌拦截器一... #安装### Via Bower $ bower install spring-security-csrf-token-interceptor###通过NPM $ npm install spring-security-csrf-token-interceptor#Usage将其作为对您的应用程序

      spring-security-core-2.0.5.RELEASE.src

      Spring Security提供了一整套解决方案,包括认证、授权、会话管理、CSRF防护等,以确保应用程序的安全性。它基于Spring框架构建,易于与其他Spring组件集成,如Spring MVC、Spring Boot等。`spring-security-core`是...

      spring-security-4.0.3.RELEASE-全包

      7. **CSRF Protection**:Spring Security 4.0.3包含内置的跨站请求伪造(CSRF)防护机制,以防止恶意攻击者利用用户的会话执行非预期的操作。 8. **Channel Security**:该框架可以强制某些URL只通过HTTPS连接访问...

      spring-security-2.0.5

      Spring Security内置了多种防御机制,如CSRF(跨站请求伪造)防护、XSS(跨站脚本攻击)过滤,以及Session Fixation防护等,增强了应用程序的安全性。开发者可以通过简单配置就能启用这些防护措施,无需编写额外的...

      spring-security-3.0.5.RELEASE

      5. **CSRF防护**:虽然3.0.5版本较旧,但Spring Security已经开始考虑跨站请求伪造(CSRF)攻击的防护,通过生成和验证CSRF令牌来防止这种攻击。 6. **集成其他Spring组件**:Spring Security能够无缝集成Spring ...

      Spring-Security-Demo-master.zip

      Spring Security 是一个强大的安全框架,常用于Java应用的安全管理,特别是在Spring Boot项目中。这个"Spring-Security-Demo-master.zip"压缩包包含了基于Spring Boot和Spring Security实现的前后端分离登录认证及...

      spring-security-4.2.4(全)资源包

      Spring Security 是一个强大的和高度可定制的身份验证和访问控制框架,用于Java应用程序。这个资源包是Spring Security 4.2.4的完整版本,发布于2018年2月24日,它专为Java Development Kit (JDK) 8设计。如果你的...

      springmvc4+spring4+mybatis3+spring-security3的环境搭建

      接下来,我们讨论Spring Security 3,它提供了全面的安全管理功能,包括认证、授权、CSRF防护等。在`pom.xml`中,添加Spring Security依赖: ```xml &lt;groupId&gt;org.springframework.security &lt;artifactId&gt;spring-...

      spring-security4.0.zip

      - `thymeleaf-extras-springsecurity4-3.0.0.RELEASE.jar`: 使得Thymeleaf模板引擎能够与Spring Security无缝协作,方便地在页面上展示权限相关的控制。 10. **消息安全** - `spring-security-messaging-4.0.0....

    Global site tag (gtag.js) - Google Analytics