解决cookie中无samesite的漏洞和无反CSRF设置的漏洞

本文最后更新于:2025年2月18日 下午

解决cookie中无samesite的漏洞和无反CSRF设置的漏洞

SpringBoot2.6.0之后可直接在配置文件中设置

1
2
3
4
5
6
7
8
server:
servlet:
session:
cookie:
same-site: LAX # 可以是 LAX、STRICT 或 NONE
# LAX:默认值,允许同站请求以及一些跨站请求(如 GET 表单提交)。
# STRICT:限制更加严格,Cookie 只会在同站请求中发送,不会在跨站请求中发送。
# NONE:允许跨站请求发送 Cookie,但需要将 Secure 属性设置为 true,即只通过 HTTPS 发送。

以下为2.6.0之前

服务器会默认自动生成一个cookie,其中属性为JSESSIONID,这个是没有指定samesite

解决方法是自己实现生成一个防止CSRF的cookie属性,并设置上samesite。这样自动生成的这个我们不用,也不做验证,就可以直接忽略掉了。

例如在网站入口处生成,以下以springboot的thymeleaf控制方法演示

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
@GetMapping("login")
public String toLogin(HttpSession session,HttpServletResponse response) {
String csrf_id = UUID.randomUUID().toString().replace("-", "");
// 将加密后的存入cookie返回给前端,加密方法随意,可以用MD5或者BCrypt
String s = PasswordUtil.hashPassword(csrf_id);
// 将csrf密文存入session
session.setAttribute("XSRF-TOKEN", s);
ResponseCookie cookie = ResponseCookie.from("XSRF-TOKEN", csrf_id)
.sameSite("Strict") // SameSite 属性
.maxAge(604800) // 7天
.path("/")
.httpOnly(true)
.secure(true)
.build();
response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString());
return "login";
}

在拦截器内进行验证

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
// 生成CSRF以防止跨站请求伪造
Cookie[] cookies = request.getCookies();
for (Cookie cookie : cookies) {
if (cookie.getName().equals("XSRF-TOKEN")) {
if (cookie.getValue() != null) {
// 获取 session
HttpSession session = request.getSession(false); // false 表示如果会话不存在则返回 null
if (session != null) {
String csrf = (String) session.getAttribute("XSRF-TOKEN");
if (csrf == null || csrf.isEmpty()) {
System.out.println("csrf为空");
return false;
}

// 执行 CSRF 验证 >> 将cookie内的值加密后与session中的值比对
boolean csrfValid = PasswordUtil.checkPassword(cookie.getValue(), csrf);
System.out.println("验证CSRF!");
if (!csrfValid) {
return false;
}
} else {
System.out.println("Session 不存在");
return false;
}
}
}
}

解决cookie中无samesite的漏洞和无反CSRF设置的漏洞
https://superlovelace.top/2024/11/06/cookie设置samesite/
作者
棱境
发布于
2024年11月6日
更新于
2025年2月18日
许可协议