首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >解码 CSRF 漏洞防护从原理到代码实践

解码 CSRF 漏洞防护从原理到代码实践

原创
作者头像
度假的小鱼
发布2025-09-01 16:38:41
发布2025-09-01 16:38:41
4980
举报
文章被收录于专栏:解码解码

在 Web 安全领域,跨站请求伪造(CSRF)漏洞如同隐藏在系统中的 “幽灵”,随时可能被攻击者利用,窃取用户权限、篡改数据甚至造成财产损失。本文将从 CSRF 漏洞的核心原理出发,结合实际应用场景分析风险,最终基于现有系统支撑框架,提供完整的防护方案与代码案例,帮助开发者快速落地安全防护措施。

测试过程 抓取数据包(放掉第一个校验原始密码的包),使用Generate CSRF PoC功能,如图

修改新密码为12345678,点击Regenerate按钮,再点击Test in browser按钮,复制其url至浏览器中访问,发现修改成功

使用密码12345678登录,发现登录成功 风险分析 攻击者通过伪造来自受信任用户的请求,伪造请求,进行篡改、转账、改密码、发邮件等非法操作。 加固建议 系统开发者可以在HTTP请求中以参数形式加入一个随机产生的token,并在服务器端建立一个拦截器验证这个token,如果请求中没有token或者token内容不正确,则认为可能是CSRF攻击而拒绝该请求。

1.读懂 CSRF:漏洞原理与真实风险

CSRF 漏洞的本质,是攻击者利用用户已建立的 “信任关系”,伪造用户身份发起非法请求。其攻击流程往往具备固定模式:首先,用户登录目标系统并生成认证 Cookie(如 SessionID);随后,用户在未退出登录的情况下,被诱导访问攻击者搭建的恶意页面;最后,恶意页面通过自动提交表单、发起 AJAX 请求等方式,向目标系统发送携带用户认证信息的伪造请求,而系统因无法区分请求来源的合法性,最终执行攻击者预设的操作。

从实际攻击场景来看,CSRF 的危害远超 “数据篡改” 的范畴。例如,在金融类系统中,攻击者可伪造转账请求,将用户账户资金转移至指定账户;在用户中心系统中,可篡改用户绑定的手机号、邮箱,甚至直接修改登录密码,导致账号被盗;在内容管理系统(CMS)中,还能伪造文章发布、评论删除等操作,破坏平台内容生态。更隐蔽的是,这类攻击往往不会留下明显痕迹,用户与开发者难以快速定位问题根源。

2.防护核心:Token 验证机制

抵御 CSRF 攻击的关键,在于打破 “攻击者可伪造合法请求” 的前提。而 Token 验证机制,正是通过在请求中加入 “随机且唯一的标识”,让服务器能够区分请求是否由用户主动发起。其核心逻辑可分为三步:

Token 生成:用户登录成功后,服务器生成一个随机字符串(即 CSRF Token),并将 Token 与用户 Session 绑定存储(如存入 Redis 或服务器内存);

Token 传递:服务器将 Token 通过页面渲染嵌入到表单隐藏字段、AJAX 请求头或 URL 参数中,确保用户后续发起的合法请求都携带该 Token;

Token 验证:服务器接收请求后,从请求中提取 Token,并与 Session 中存储的 Token 进行比对。若 Token 不存在、已过期或不一致,则判定为 CSRF 攻击,直接拒绝请求。

相较于 “Referer 验证”(通过判断请求来源域名是否合法)等方案,Token 验证机制具备更高的安全性与兼容性。一方面,Referer 字段可被浏览器插件或攻击者篡改,存在被绕过的风险;另一方面,Token 验证不受跨域场景、浏览器版本的限制,能适配复杂的 Web 应用架构。

3.基于系统支撑框架的防护方案

目前多数应用系统已内置 CSRF 漏洞防护框架,开发者无需从零搭建 Token 生成与验证逻辑,只需通过简单配置即可启用防护。以 “将防护 URI 加入 WEB-INF/xxxx-csrf.lst 文件” 的框架为例,完整落地步骤如下:

步骤 1:配置防护 URI 列表

首先,找到项目 WEB-INF 目录下的xxxx-csrf.lst文件(若不存在则手动创建),将需要防护的接口或页面 URI 按行写入。例如,若需防护用户密码修改、账户转账、个人信息更新接口,配置内容如下:

代码语言:javascript
复制
/user/password/update
/account/transfer
/user/info/edit

框架会自动对列表中的 URI 发起的请求进行 Token 验证,未在列表中的 URI 则不启用防护,避免不必要的性能消耗。

步骤 2:前端页面嵌入 Token

在需要发起防护请求的前端页面中,通过服务器渲染将 Token 嵌入表单或请求头。以 JSP 页面为例,可通过 EL 表达式从 Session 中获取 Token,并将其作为隐藏字段加入表单:

代码语言:javascript
复制
<!-- 密码修改表单 -->
<form action="${pageContext.request.contextPath}/user/password/update" method="post">
    <!-- CSRF Token隐藏字段 -->
    <input type="hidden" name="csrfToken" value="${sessionScope.csrfToken}">
    <div class="form-item">
        <label>原密码:</label>
        <input type="password" name="oldPassword" required>
    </div>
    <div class="form-item">
        <label>新密码:</label>
        <input type="password" name="newPassword" required>
    </div>
    <button type="submit">提交修改</button>
</form>

若使用 AJAX 发起请求(如 Vue、React 前端项目),则需将 Token 加入请求头。以 Axios 为例,可通过请求拦截器统一添加:

代码语言:javascript
复制
// Axios请求拦截器
axios.interceptors.request.use(config => {
    // 从本地存储(如localStorage)中获取Token
    const csrfToken = localStorage.getItem('csrfToken');
    if (csrfToken) {
        // 将Token加入请求头(需与服务器约定头字段名,此处为X-CSRF-Token)
        config.headers['X-CSRF-Token'] = csrfToken;
    }
    return config;
}, error => {
    return Promise.reject(error);
});

步骤 3:服务器端验证逻辑(框架内置,可自定义扩展)

系统防护框架会自动拦截xxxx-csrf.lst中配置的 URI 请求,并执行 Token 验证。若需了解底层逻辑或自定义验证规则,可参考以下核心代码(以 Java Spring Boot 框架为例):

代码语言:javascript
复制
/**
 * CSRF Token验证拦截器(框架内置,开发者可按需扩展)
 */
@Component
public class CsrfInterceptor implements HandlerInterceptor {
​
    // 从配置文件中加载需要防护的URI列表
    @Value("classpath:WEB-INF/xxxx-csrf.lst")
    private Resource csrfUriResource;
    private Set<String> protectedUris;
​
    // 初始化时加载防护URI列表
    @PostConstruct
    public void init() throws IOException {
        // 读取xxxx-csrf.lst文件内容
        List<String> uris = Files.readAllLines(csrfUriResource.getFile().toPath(), StandardCharsets.UTF_8);
        protectedUris = new HashSet<>(uris);
    }
​
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        // 1. 判断当前请求URI是否在防护列表中
        String requestUri = request.getRequestURI();
        if (!protectedUris.contains(requestUri)) {
            // 不在防护列表,直接放行
            return true;
        }
​
        // 2. 从请求中提取Token(支持表单参数、请求头两种方式)
        String requestToken = request.getParameter("csrfToken");
        if (requestToken == null) {
            requestToken = request.getHeader("X-CSRF-Token");
        }
​
        // 3. 从Session中获取服务器存储的Token
        HttpSession session = request.getSession();
        String serverToken = (String) session.getAttribute("csrfToken");
​
        // 4. Token验证逻辑
        if (requestToken == null || serverToken == null || !requestToken.equals(serverToken)) {
            // 验证失败,返回403 Forbidden
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            response.getWriter().write("CSRF Token验证失败,请求被拒绝");
            return false;
        }
​
        // 验证成功,放行请求
        return true;
    }
}

步骤 4:Token 生成与刷新

为确保 Token 的随机性与时效性,需在用户登录时生成 Token,并可根据需求定期刷新。以下为 Spring Boot 中 Token 生成的示例代码:

代码语言:javascript
复制
/**
 * 用户登录服务
 */
@Service
public class LoginService {
​
    // 生成CSRF Token(使用UUID保证随机性)
    private String generateCsrfToken() {
        return UUID.randomUUID().toString().replace("-", "");
    }
​
    /**
     * 用户登录成功后,生成Token并存入Session
     */
    public void afterLoginSuccess(HttpSession session) {
        String csrfToken = generateCsrfToken();
        // 将Token存入Session,有效期与Session一致
        session.setAttribute("csrfToken", csrfToken);
        // 若需前端存储Token(如localStorage),可将Token返回给前端
        // 例如:return csrfToken;
    }
}

4.防护效果验证与注意事项

配置完成后,可通过以下方式验证防护效果:

  1. 正常请求测试:用户登录后发起合法请求(如提交密码修改表单),观察请求是否成功执行,确保 Token 传递与验证正常;
  2. CSRF 攻击模拟:使用 Postman 等工具,不携带 Token 或携带伪造 Token 发起请求,验证服务器是否返回 403 错误,拒绝非法请求。

同时,需注意以下细节以避免防护失效:

  • Token 传输安全:确保 Token 通过 HTTPS 传输,避免在 HTTP 协议下被窃取;
  • Token 唯一性:每个用户 Session 对应唯一 Token,不可多个用户共享同一 Token;
  • Token 时效性:可根据业务需求设置 Token 过期时间(如 30 分钟),过期后重新生成,降低 Token 被复用的风险;
  • 排除静态资源:无需对 CSS、JS、图片等静态资源 URI 配置防护,避免增加服务器负担。

5.小结

CSRF 漏洞的防护并非复杂难题,基于现有系统支撑框架,只需通过 “配置防护 URI + 嵌入 Token + 验证 Token” 三步,即可构建可靠的防护体系。开发者需牢记:安全防护的核心在于 “最小权限原则” 与 “请求合法性校验”,除了启用 Token 验证,还需结合输入过滤、输出编码、HTTPS 加密等措施,构建多层级的 Web 安全防护屏障。希望本文的方案与代码案例,能帮助开发者快速解决 CSRF 漏洞问题,为用户数据安全保驾护航。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1.读懂 CSRF:漏洞原理与真实风险
  • 2.防护核心:Token 验证机制
  • 3.基于系统支撑框架的防护方案
    • 步骤 1:配置防护 URI 列表
    • 步骤 2:前端页面嵌入 Token
    • 步骤 3:服务器端验证逻辑(框架内置,可自定义扩展)
    • 步骤 4:Token 生成与刷新
  • 4.防护效果验证与注意事项
  • 5.小结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档