目录
在 Web 应用安全领域,CSRF(Cross - Site Request Forgery)攻击是一种常见且具有潜在危害的安全威胁。它往往涉及个人隐私泄露以及财产安全问题。本文将详细介绍 CSRF 的原理、场景、业务易受攻击性以及相应的防御措施,并提供前端 Vue 和后端 Java 的代码示例。
一、CSRF 的原理
由于浏览器的特性,会自动携带同一域名下的 Cookie 到服务器。服务器端的某些功能在验证了 Cookie 有效性后,就会执行相应功能。这就使得攻击者有可能利用用户的身份,在用户不知情的情况下,以用户的名义发送恶意请求。
二、CSRF 的场景和易受攻击的业务
- 场景分类
- 包括修改个人数据(横向越权),例如攻击者可能会修改用户的个人信息,如联系方式、收货地址等;添加用户(纵向越权)等情况。
- 易受攻击的业务类型
- CSRF 一般用于操作用户的资源,或者使用用户的权限进行操作,或者窃取用户的相关信息。常见的如电商业务中的订单操作、社交网络中的信息发布(如发微博)、用户账号授权相关的操作(如二维码登陆、绑定第三方账号等)。
三、CSRF 与 XSS 的危险性比较
对于 CSRF 是否比 XSS 更具危险性,存在不同观点。有人认为 CSRF 不比 XSS 更有危险性,因为 CSRF 能完成的事,XSS 更能够完成;而 XSS 能完成的事,CSRF 不一定能做到。
四、CSRF 的最佳利用方式
CSRF 可用于多种敏感操作,例如给电商用户新增默认收货地址、发微博、添加管理员等等。所有的敏感操作都可能成为攻击目标,因此都需要进行 CSRF 的防护。
五、防御措施
(一)后端 Java 代码示例
- 使用 Token 验证
- 在 Java 后端,可以为每个用户会话生成一个唯一的 Token,并在敏感操作的请求中包含该 Token。服务器端验证请求中的 Token 是否与用户会话中的 Token 一致。以下是一个简单的示例:
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.UUID;
public class CSRFTokenUtil {
public static String generateToken() {
return UUID.randomUUID().toString();
}
public static void setTokenCookie(HttpServletResponse response) {
String token = generateToken();
Cookie cookie = new Cookie("csrf_token", token);
cookie.setPath("/");
response.addCookie(cookie);
}
public static boolean validateToken(HttpServletRequest request) {
Cookie[] cookies = request.getCookies();
if (cookies!= null) {
for (Cookie cookie : cookies) {
if ("csrf_token".equals(cookie.getName())) {
String requestToken = request.getParameter("csrf_token");
return cookie.getValue().equals(requestToken);
}
}
}
return false;
}
}
在上述代码中,generateToken方法用于生成一个随机的 Token,setTokenCookie方法用于将 Token 设置为一个 Cookie 发送给客户端,validateToken方法用于验证请求中的 Token 是否有效。
- Referer 限制
- 可以对请求的 Referer 进行校验。但要注意严格校验 host,而不是简单的使用一个字符包含的检查。以下是一个简单的示例,用于检查 Referer 是否来自合法的域名:
import javax.servlet.http.HttpServletRequest;
public class RefererValidator {
public static boolean validateReferer(HttpServletRequest request) {
String referer = request.getHeader("Referer");
if (referer!= null) {
// 假设合法域名是example.com
return referer.contains("example.com");
}
return false;
}
}
- 日志系统
- 建立严格的日志系统也是一种重要的防护手段。通过记录请求信息,可以在事后甄别一定的 CSRF 攻击。例如,可以使用 Java 的日志框架(如 Log4j)来记录请求的相关信息:
import org.apache.log4j.Logger;
public class CSRFLogger {
private static final Logger logger = Logger.getLogger(CSRFLogger.class);
public static void logRequest(HttpServletRequest request) {
logger.info("Request URL: " + request.getRequestURL());
logger.info("Referer: " + request.getHeader("Referer"));
logger.info("Parameters: " + request.getParameterMap());
}
}
(二)前端 Vue 代码示例
- 使用 Token 验证(结合后端)
- 在 Vue 前端,可以在发送敏感请求时,从 Cookie 中获取 Token 并添加到请求参数中。以下是一个简单的示例:
<template>
<div>
<button @click="sendSensitiveRequest">发送敏感请求</button>
</div>
</template>
<script>
export default {
methods: {
sendSensitiveRequest() {
const csrfToken = document.cookie.match(/csrf_token=(.*?);/)[1];
// 假设这里是一个axios请求,用于发送敏感请求
axios.post('/sensitive-api', { csrf_token: csrfToken })
.then(response => {
console.log(response);
})
.catch(error => {
console.log(error);
});
}
}
};
</script>
在上述代码中,当点击按钮时,会从 Cookie 中获取csrf_token并添加到 POST 请求的参数中,发送到后端的/sensitive-api接口。
- 校验 X - Requested - With 头(针对 Ajax 请求)
- 如果请求仅仅是 Ajax 请求,那么可以校验
X - Requested - With头。以下是一个简单的示例,用于在 Vue 中发送 Ajax 请求并校验该请求头:
- 如果请求仅仅是 Ajax 请求,那么可以校验
<template>
<div>
<button @click="sendAjaxRequest">发送Ajax请求</button>
</div>
</template>
<script>
export default {
methods: {
sendAjaxRequest() {
const xhr = new XMLHttpRequest();
xhr.open('POST', '/ajax-api');
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest');
xhr.onreadystatechange = function () {
if (xhr.readyState === 4 && xhr.status === 200) {
console.log(xhr.responseText);
}
};
xhr.send();
}
}
};
</script>
在上述代码中,在发送 Ajax 请求时,设置了X - Requested - With头为XMLHttpRequest,并且在服务器端可以校验该请求头,以防止 CSRF 攻击。
希望通过对 CSRF 攻击与防御的这些介绍,能让开发人员和用户更加重视 CSRF 问题,采取有效的措施来保障 Web 应用的安全。

583

被折叠的 条评论
为什么被折叠?



