html注入与csrf组合攻击成功:通过逆向aes加密和md5加盐签名绕过waf,利用换行符构造payload实现存储型xss,并结合get登出接口完成点击即登出的csrf攻击。

HTML 本身没有“防作弊”能力——它只是静态标记语言,所有前端代码都可被用户查看、修改、绕过。所谓“防作弊”,实际是防止非授权操作、数据篡改、界面伪造或爬虫恶意抓取,但必须明确:一切逻辑和校验放在前端都是形同虚设。
真正有效的策略,是把关键判断下沉到服务端,并用前端做体验层辅助。下面几个点,是日常开发中高频踩坑、又容易被误以为“很安全”的地方。
别信 disabled 或 readonly 能阻止提交
用户禁用按钮、隐藏表单字段、加 disabled 属性,这些只影响 UI 行为,不阻断请求本身。
- 浏览器开发者工具里直接删掉
disabled属性,表单立刻可提交 -
readonly对input[type="text"]有效,但对select、textarea外的其他控件无效,且照样能通过 JS 修改value - 更隐蔽的是:有人会绕过页面,直接构造
fetch或curl请求发到接口
正确做法:服务端必须校验字段是否允许修改、当前用户是否有权限、值是否在合法范围内。前端只做提示和体验优化。
data- 属性不是保密容器
很多人把临时状态、ID、token 甚至加密片段塞进 data-id、data-token 等自定义属性,以为“藏在 DOM 里就安全”。
-
data-属性完全暴露在 HTML 源码和 DevTools 的 Elements 面板中 - 任何脚本(包括用户写的 Bookmarklet 或控制台命令)都能读取:
document.querySelector('[data-id]').dataset.id - 如果用来存敏感信息(比如未过期的短期 token),等于白送
替代方案:敏感上下文应由后端下发并绑定 session;前端如需临时标识,优先用内存变量(const tempId = 'xxx'),而非挂载到 DOM。
隐藏链接/黑链检测不能只靠 CSS
检查页面是否被植入隐藏链接时,光看 display: none 或 color: #fff 是远远不够的。
- 攻击者常用
position: absolute; left: -9999px、font-size: 0、opacity: 0、clip-path等多种方式隐藏内容 - 部分恶意代码用
document.write或innerHTML动态注入,源码里根本看不到 - 更难缠的是通过第三方 SDK(如统计、广告脚本)异步加载后插入的链接,需结合 Network 面板追踪资源来源
建议:上线前用 Puppeteer 或 Playwright 启动无头浏览器,遍历所有 a[href] 元素,检查其 getComputedStyle 是否满足可见性条件(visibility !== 'hidden' 且 display !== 'none' 且 offsetWidth > 0),再比对域名白名单。
注释里别留线索
<!-- TODO: 这里要加权限校验 --> 这类注释看似无害,实则可能泄露业务逻辑弱点。
- 攻击者扫到
<!-- DEBUG: user_role=admin -->,立刻知道该接口可能绕过角色判断 - 注释中暴露路径、参数名、内部 API 地址(如
<!-- internal api: /v1/internal/batch_delete -->)会极大降低渗透门槛 - 构建流程若未移除注释(尤其 SSR 模板或预渲染 HTML),生产环境照常输出
上线前务必启用构建工具的注释清除插件(如 Webpack 的 HtmlWebpackPlugin 配合 minify.removeComments,或 Vite 的 build.minify 默认行为)。开发阶段也应避免在注释中写具体实现细节。
前端能做的,只是提高攻击成本、增加探测难度、及时发现异常行为。真正的防线永远在服务端——校验、鉴权、审计、限流,缺一不可。最容易被忽略的,其实是日志里没记录关键字段变更、没留存用户操作上下文、没对高频异常请求做聚合分析。这些事不在 HTML 里写,但决定系统是否真的“防得住”。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











