识别表单未做防重放校验的关键是:后端未对每次提交生成并校验一次性令牌;若用Burp Suite重复发送同一请求仍成功处理(如创建多条订单),即存在漏洞,常见漏点包括token缺失、未绑定session、未及时失效或仅存于前端。

怎么识别表单提交没做防重放校验
防重放(replay protection)不是靠前端按钮禁用或 JS 标志位实现的,而是看后端是否对每次提交生成并校验一次性令牌。如果表单提交后,你用 Burp Suite 或浏览器开发者工具重复发同一个请求,服务器仍成功处理(比如创建了两条订单、扣了两次款),就说明缺失防重放机制。
常见漏点包括:submit_token 字段缺失、token 未绑定 session 或时间戳、token 被重复消费后未及时失效、token 仅存在前端 localStorage 中而未由后端签发和验证。
检查 submit_token 是否真正生效
打开表单页面源码或响应 HTML,搜索 submit_token、csrf_token、form_nonce 等字段名。关键不是它“是否存在”,而是它是否满足以下条件:
- 值是服务端生成的(非客户端随机拼接),且含签名或加密信息
- 在表单提交时作为隐藏字段随请求发出,并被后端完整接收
- 后端收到后执行校验:验证签名有效性、检查是否过期(如 TTL ≤ 5 分钟)、确认未被标记为已使用
- 校验通过后立即标记该 token 为“已消费”,后续相同 token 提交返回
400 Bad Request或409 Conflict
若 token 是静态字符串(如固定写死的 "abc123")、或只校验存在性不校验时效与唯一性,等同于没有防重放。
立即学习“前端免费学习笔记(深入)”;
为什么 PRG 模式不能替代防重放
PRG(Post-Redirect-Get)能防止用户刷新导致重复提交,但它解决的是浏览器行为问题,不是网络层重放。攻击者绕过浏览器,用脚本直接 POST 多次,PRG 完全无效。
典型误判场景:
- 表单提交后跳转到 success 页面,但后端依然接受原始 POST 请求
- success 页面里带“再提交一次”按钮,且复用了旧 token 或无 token
- API 接口被设计为纯 POST,无 redirect,但又没做 token 校验
只要接口允许相同参数+相同 token 的多次请求被成功处理,PRG 就不构成防重放保障。
Burp Suite 实操检测步骤
用 Burp Proxy 拦截一次正常表单提交,然后做三件事:
- 右键请求 → “Send to Repeater”,在 Repeater 中连续点击
Go3–5 次,观察响应状态码和业务结果(如数据库记录数、余额变化) - 修改其中一次请求的
submit_token值为上一次的旧值,看是否仍被接受 - 把请求中的时间戳参数(如
ts=1756185780)减去 300 秒再发,测试是否校验过期
任意一项成功触发业务逻辑变更,即确认存在防重放漏洞。注意:某些系统会返回 200 但内部静默丢弃,务必查数据库或日志确认实际执行效果。
真正的防重放必须依赖服务端生成、绑定上下文、一次性的 token,前端任何禁用按钮、loading 状态、AbortController 都只是辅助体验,无法阻止重放本身。



















