CSRF(Cross-site request forgery)跨站请求伪造,也被称为"One Click Attack"(一键攻击)或者"Session Riding"(会话控制),是一种对网站的恶意利用。与传统的XSS攻击(跨站脚本攻击)相比,CSRF攻击更加难以防范,被认为更具危险性。CSRF攻击可以在用户不知情的情况下,以用户的名义伪造请求发送给攻击页面,从而在用户未授权的情况下执行受到权限保护的操作。
场景讲解
例如,一个用户Andy登录银行站点服务器准备进行转账操作。在Andy的用户信息有效期内,Andy被诱导查看了一个黑客恶意网站。该网站获取了Andy登录后的浏览器与银行网站之间尚未过期的Session信息。由于Andy浏览器的cookie中含有Andy银行账户的认证信息,黑客可以以Andy的合法身份伪装访问Andy的银行账户,并进行非法操作。
CSRF攻击的防御策略
验证HTTP Referer字段:验证请求来源页面的Referer字段,确保请求来自同一站点,但该方法并不可靠,因为Referer字段可能被伪造或者被浏览器禁用。
在请求地址中添加Token并验证:在每个页面中嵌入一个随机生成的Token,并将其添加到请求地址的参数中,后端服务器在接收到请求时验证Token的有效性。
在HTTP头中自定义属性并验证:在每个请求中添加自定义的HTTP头属性,例如"X-Requested-With"或"X-CSRF-Token",后端服务器在接收到请求时验证该属性的值。
以Spring Security安全框架中的CSRF防御功能来讲解:
-
disable()
: 关闭Spring Security默认开启的CSRF防御功能。 -
csrfTokenRepository(CsrfTokenRepository csrfTokenRepository)
: 指定要使用的CsrfTokenRepository(Token令牌持久化仓库)。默认是由LazyCsrfTokenRepository包装的HttpSessionCsrfTokenRepository。 -
requireCsrfProtectionMatcher(RequestMatcher requireCsrfProtectionMatcher)
: 指定针对什么类型的请求应用CSRF防护功能。默认设置是忽略GET、HEAD、TRACE和OPTIONS请求,而处理并防御其他所有请求。
- CSRF防护功能关闭的配置,但直接关闭CSRF防御的方式简单粗暴,不太推荐使用,如果强行关闭后网站可能会面临CSRF攻击的危险,适合在开发过程中测试使用。
@Override
protected void configure(HttpSecurity http
) throws Exception {
http
.csrf()
.disable()
// ...其他配置
}
Spring Boot整合Spring Security进行CSRF防御的示例
- 针对Form表单数据修改请求的CSRF Token配置:
在表单中添加携带CSRF Token信息的隐藏域:
<form method="post">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
<!-- 其他表单字段 -->
<input type="submit" value="Submit" />
</form>
- 针对Ajax数据修改请求的CSRF Token配置:
在页面的<head>
标签中添加<meta>
标签设置CSRF Token信息,并在具体的Ajax请求中获取相应的Token值,并将其添加到请求的HTTP header中进行验证。
<head>
<meta name="_csrf" th:content="${_csrf.token}"/>
<meta name="_csrf_header" th:content="${_csrf.headerName}"/>
<!-- 其他头信息 -->
</head>
<body>
<!-- 具体页面内容 -->
<script type="text/javascript">
$(document).ajaxSend(function(e, xhr, options) {
xhr.setRequestHeader($("meta[name='_csrf_header']").attr("content"), $("meta[name='_csrf']").attr("content"));
});
// 其他Ajax请求
</script>
</body>
希望通过以上的讲解,能让大家更深入的了解CSRF(跨站请求伪造)攻击及防御策略。