图形验证码被会话重放绕过,表单防垃圾是不是还要加一层
验证码模块公告说已提交过的表单可被重放绕过,表单防垃圾要不要再加一层?要,但加的那一层不是再放一个图形验证码,而是补上「一次性」和「成本」这两件事。Drupal 那条公告的口径是模块没有把已解开的验证会话完全作废,也就是说同一份验证结果可以被再次使用;这类问题不是识别率不够,而是验证状态没有被及时清理。
重放绕过的是哪一环
正常链路里,用户先解一次验证码,服务端记下「这次会话已经通过」,随后提交表单时直接引用这个状态。绕过发生在引用那一步:状态没有被一次性消费,重复携带同一个已通过的状态,就能在不解新题的情况下再次提交。
| 环节 | 作用 | 重放时是否被复用 |
|---|---|---|
| 出题与作答 | 判断请求方是不是人 | 被跳过 |
| 通过状态记录 | 记住这次已通过 | 被反复使用 |
| 表单提交校验 | 检查字段与频率 | 需要自己承担拦截 |
| 落库与审核 | 决定内容是否公开 | 垃圾已经进入 |
这段链路里能通过状态是关键节点。一个可用的判断方法:提交成功后再手工重放同一份请求,观察服务端是否要求重新验证。若仍然接受,说明通过状态的作用范围过大。
只有一层验证时的失效面
单层验证的失效面不只在重放。脚本提交会绕开前端渲染,图形验证如果被做成纯前端校验,等于没有校验;第三方验证服务受网络与配额影响,超时时的放行策略也需要明确,默认放行会让服务异常变成垃圾涌入的窗口。
另一类是低成本自动化:人工打码服务把验证环节变成开销很小的重复动作,此时拦截要依赖提交频率、字段一致性与内容质量,而不是验证本身。
蜜罐字段与校验服务各自挡什么
蜜罐字段是在表单里放一个对人类不可见、对脚本却会被填写的输入项,一旦有值就判定为机器人。它的成本几乎为零,也不影响真人体验,能挡住大批不看样式的简单脚本;挡不住的是专门识别隐藏字段并跳过的提交器。
校验服务(例如表单接入 reCAPTCHA 这类人机验证)承担的是另一段:判断请求方的行为特征,配合提交频率限制对同一来源短时间内的重复提交设上限。两者叠加的分工是蜜罐负责筛掉大批廉价脚本,校验与频控负责抬高剩余请求的成本,服务端再把验证通过状态改成一次性消费。
上线后怎么验收拦截效果
验收要从提交端做,而不是只看配置项。建议留三组对照:真人在正常浏览器提交一次、隐藏字段被填值的提交、以及同一来源短时间内的重复提交。三组都要在后台留言或垃圾记录里留下结果,能看到拦截发生在哪一层。
内容侧还要有兜底。AnQiCMS 的表单可以把 reCAPTCHA 验证码作为验证项接入,留言进入后台列表便于逐条复核;内容安全设置里的敏感词过滤与关键词替换负责在落库前后拦掉明显违规的文本,需要人工判断的部分走内容审核,避免把拦截完全押在验证环节上。三层结果分开看,才能判断该补哪一层。
常见问题
升级验证模块之后还需要加别的一层吗? 升级解决的是状态没有作废这一个成因。蜜罐与频控的作用是在验证之外提供不依赖验证结果的判断,避免单点再次出问题。
加了蜜罐字段会不会误伤真人? 蜜罐只对填写了隐藏字段的请求判拒,真人正常操作不会触发。要留意的是辅助技术与自动填充工具可能填值,出现误拦时先查该字段是否被自动填充。
验证服务超时应该放行还是拦截? 两种都要有明确策略。对留言、注册这类可重试的表单,超时后提示稍后重试比默认放行更稳;默认放行会把服务异常变成垃圾涌入的窗口。