Java CSRF案例

wen java案例 4

Java防CSRF攻击实战案例与漏洞修复全解析

📖 文章导读

  • 什么是CSRF?它为何危险?
  • 真实的Java CSRF攻击案例剖析
  • 为什么你的Java Web应用可能“裸奔”?
  • 从零搭建:一个带漏洞的Spring Boot案例
  • 3种主流防御方案及代码实现
  • QA:开发者最常问的5个CSRF问题
  • 构建零信任的Java安全防线

什么是CSRF?它为何危险?

CSRF(Cross-Site Request Forgery,跨站请求伪造) 是一种利用用户已登录身份,在用户不知情下发起恶意请求的攻击方式,攻击者通过构造一个看似合法的请求(如转账、改密码、发帖),诱导用户点击或访问,从而以用户的名义执行操作。

Java CSRF案例

核心危险在于:

  • 无需窃取用户密码或SessionID
  • 利用浏览器自动携带Cookie的机制
  • 用户难以察觉,且攻击可批量自动化

根据OWASP统计,CSRF目前仍是企业级Java应用中最常见的高危漏洞之一。


真实的Java CSRF攻击案例剖析

案例:某银行金融系统的“一秒转账”漏洞

某银行Java Web应用采用Spring MVC框架,后台用户管理功能通过/user/transfer?toAccount=XXX&amount=1000实现转账,未添加任何CSRF防护。

攻击过程:

  1. 用户在银行后台登录,获得有效Session。
  2. 攻击者在论坛发布帖子,内嵌一个隐藏图片标签:
    <img src="http://bank.example.com/user/transfer?toAccount=attacker&amount=5000" width="0" height="0" />
  3. 用户(仍为登录状态)打开帖子时,浏览器自动加载该图片,发起GET请求。
  4. 银行服务器验证Session有效,执行转账操作——钱被转走!

关键失败点:

  • 未校验请求来源(Origin/Referer)
  • 未使用Token验证
  • 未区分GET/POST语义(转账不应使用GET)

为什么你的Java Web应用可能“裸奔”?

很多Java开发者存在以下误区:

  • ❌ “我的API加了JWT/Token,不需要CSRF防护”
  • ❌ “用POST请求就安全了”
  • ❌ “只有表单才需要防CSRF”

事实是:

  • JWT存储在LocalStorage,但Cookie仍可能被用于身份验证
  • 攻击者可构造POST表单(如通过隐藏<form>+onload提交)
  • 所有能改变状态的接口(POST/PUT/DELETE)都可能被利用

从零搭建:一个带漏洞的Spring Boot案例

@RestController  
public class UserController {  
    @PostMapping("/updatePassword")  
    public String updatePassword(@RequestParam String newPwd) {  
        // 直接更新密码,无任何校验  
        userService.updatePassword(currentUser(), newPwd);  
        return "success";  
    }  
}

攻击构造(恶意HTML页面):

<form action="http://victim.com/updatePassword" method="POST">  
    <input type="hidden" name="newPwd" value="hacked123">  
</form>  
<script>document.forms[0].submit();</script>  

用户只要打开此页面,密码即被篡改。


3种主流防御方案及代码实现

✅ 方案一:CSRF Token(最推荐,兼容性好)

原理: 服务器生成随机Token,嵌入表单/请求头,服务端校验。

Spring Security集成:

@EnableWebSecurity  
public class SecurityConfig {  
    @Bean  
    public SecurityFilterChain filterChain(HttpSecurity http) {  
        http.csrf(csrf -> csrf  
            .csrfTokenRepository(CookieCsrfTokenRepository.withHttpOnlyFalse())  
        );  
        return http.build();  
    }  
}

前端需在请求头添加X-CSRF-TOKEN,后端自动校验。

✅ 方案二:SameSite Cookie属性

原理: 浏览器限制Cookie跨站发送。

@Configuration  
public class CookieConfig {  
    @Bean  
    public WebServerFactoryCustomizer<TomcatServletWebServerFactory> cookieCustomizer() {  
        return factory -> factory.addContextCustomizers(context -> {  
            context.setSessionCookieName("JSESSIONID");  
            context.setUseHttpOnly(false);  
            // 设置SameSite为Strict或Lax  
            context.setSessionCookieDomain(null);  
        });  
    }  
}

注意: 需配合Spring Boot 2.6+或使用SameSite过滤器。

✅ 方案三:双重提交Cookie + 自定义请求头(适用于前后端分离)

原理: 在Cookie和自定义请求头中同时携带同一随机值,后端比较是否一致。

// 后端过滤器示例  
String cookieValue = extractCookie(request, "X-Session-Id");  
String headerValue = request.getHeader("X-Session-Id");  
if (!cookieValue.equals(headerValue)) {  
    throw new CsrfException("CSRF验证失败");  
}

❓ QA:开发者最常问的5个CSRF问题

Q1:RESTful API需要防CSRF吗?
A:需要!只要API使用Cookie/Session认证,就必须防护,JWT若放在LocalStorage则无需,但放在Cookie仍需。

Q2:用HTTPS能防CSRF吗?
A:不能,HTTPS仅保证传输加密,不验证请求来源,攻击者仍可发起跨站请求。

Q3:CSRF Token如何保证唯一性?
A:建议使用java.security.SecureRandom生成,或Spring Security自动生成的Token,每次请求后可选刷新。

Q4:多域名场景如何部署CSRF?
A:使用Origin + Referer校验,或采用CORS白名单配合自定义Token,注意不要暴露Token给第三方域名。

Q5:前端Vue/React如何配合CSRF Token?
A:从Cookie读取Token(如XSRF-TOKEN),然后在每次请求时通过拦截器自动附加到请求头。


构建零信任的Java安全防线

CSRF攻击看似“老派”,但在实践中高频出现。防御思路应从“信任来源”转向“验证请求意图”

  • 必须使用的:CSRF Token(Spring Security原生支持)
  • 建议配合的:SameSite=Lax(保护GET请求)
  • 务必避免的:仅依赖Referer、允许GET请求改变状态、省略Token校验开关

每次代码上线前运行OWASP ZAP或Burp Suite扫描,可自动检测CSRF漏洞。安全无小事,防微杜渐,从每一行代码开始。


📌 本文综述了Java环境下CSRF的攻击原理、实战案例与3种核心防护方案,适用于Spring Boot传统架构与前后端分离架构,下一期将详解“Java文件上传漏洞防护”,敬请关注。

抱歉,评论功能暂时关闭!