直接拼接用户输入到HTML会触发XSS,因浏览器将innerHTML、document.write等未转义内容解析为可执行代码,如fetch('/api/steal?c='+document.cookie)直接执行导致Cookie泄露。

为什么直接拼接用户输入到 HTML 就会触发 XSS?
因为浏览器会把 innerHTML、document.write 或未转义的模板变量当作可执行代码解析。比如用户提交了 ,你没做任何处理就塞进页面,这段脚本立刻执行——Cookie 就被发到攻击者服务器了。
常见错误现象:
• 后台用 res.send(` 直接返回 HTML
• 前端用 el.innerHTML = data.comment 渲染评论
• 模板引擎关闭了自动转义(如 EJS 的 而非 )
- 输出前必须转义:服务端用
html.escape()(Python)、htmlspecialchars()(PHP)或xss()(Node.js 库);前端优先用textContent替代innerHTML - 富文本场景必须用成熟净化库,比如
DOMPurify.sanitize(dirtyHtml),别自己写正则过滤—— 绕过方式太多 - HTTP 头加
Content-Security-Policy: default-src 'self'; script-src 'self',能拦住大部分 inline 脚本和外链 JS -
Set-Cookie必须带HttpOnly和Secure,否则 XSS 成功后 Cookie 一读一个准
CSRF Token 不生效?检查这三处硬伤
Token 验证失败不是因为逻辑错,而是部署细节漏了。典型表现是:本地开发一切正常,上线后表单总报“Invalid CSRF token”。
- Token 没随每次请求刷新:必须在每个新会话、登录后、或定时(如 2 小时)生成新 Token,不能复用长期不变的值
- Token 存储位置冲突:如果同时在 Cookie(
SameSite=Lax)和表单隐藏域里传同一个 Token,而前端又用fetch发送时没配credentials: 'include',后端就收不到 Cookie 中的 Token - 验证时机不对:必须在解析请求体(body-parser)之后、业务逻辑之前校验;若先查数据库再验 Token,攻击者可能靠时间差重放请求
更轻量的替代方案是直接设 SameSite=Strict 或 Lax(现代浏览器支持率已超 98%),但注意 Lax 对 GET 请求放行——敏感操作(如删除、转账)仍需 Token。
立即学习“Java免费学习笔记(深入)”;
为什么 Referer 检查不推荐作为主防御手段?
Referer 是浏览器自动加的请求头,但它的值不可信也不稳定:
- 隐私模式或某些安全插件会主动清空 Referer
- 从 HTTPS 页面跳转到 HTTP 页面时,浏览器按规范会丢弃 Referer
- 攻击者可通过
或fetch(..., {referrerPolicy: 'no-referrer'})干扰来源标识
所以它只能当辅助校验,比如日志里发现大量空 Referer 的 POST 请求,可能是扫描器在试探;但绝不能只靠它拦截 CSRF。
DOM XSS 和服务端 XSS 的防范重点有什么不同?
服务端 XSS 是后端没转义就吐 HTML;DOM XSS 是前端 JS 自己把 URL 参数、location.hash 或 localStorage 数据直接喂给 innerHTML、eval、setTimeout 等危险 API。
- DOM XSS 更隐蔽:不经过服务端,WAF 和服务端过滤完全无效
- 关键要审计所有“数据进 JS 执行环境”的入口:比如
location.search.match(/id=([^&]+)/)[1]拿到的值,千万别直接document.write(id) - URL 参数必须用
decodeURIComponent()+DOMPurify.sanitize()双重处理,不能只 decode - 避免用
eval、Function、setInterval('...', x)这类字符串执行 API,哪怕内容看起来“可控”
最常被忽略的是第三方 SDK:埋点、广告、客服组件如果动态加载 script 或修改 innerHTML,它们引入的漏洞一样会变成你的 XSS 攻击面。











