反射型XSS的核心漏洞点是服务端将用户输入(如URL参数、POST数据)未经转义直接拼入HTML响应;必须根据输出上下文对<、>、&、"、'等字符做精准转义,或使用DOMPurify等经验证的安全库。

反射型 XSS 的核心漏洞点,是服务端把用户输入(比如 URL 参数、POST body)未经转义就直接拼进 HTML 响应里。只要在输出前对这 5 个字符做严格转义:、<code>>、&、"、',就能拦住绝大多数反射型攻击。
哪些地方必须转义?看输出上下文
不是所有地方都用同一套规则。关键看用户数据最终插在哪种 HTML 上下文中:
- 插入到 HTML 标签体中(比如
<div>{userInput}</div>):必须转义、<code>>、&;"和'在这里不危险,但统一处理更稳妥 - 插入到双引号属性值中(比如
<input value="{userInput}">):必须转义"和&;、<code>>、'不会提前闭合属性,但保留转义无害 - 插入到单引号属性值中(比如
<div data-id='{userInput}'>):必须转义'和& - 插入到 URL 属性(如
href、src):不能只靠 HTML 转义,得先用encodeURIComponent()编码,再放进引号里
服务端模板里怎么写才安全?
别手动拼字符串,用框架或语言内置的自动转义机制:
- PHP:用
htmlspecialchars($input, ENT_QUOTES, 'UTF-8'),ENT_QUOTES确保单双引号都被处理 - Java(JSP/JSTL):用
<c:out value="${param.q}" />或 EL 表达式自带的${fn:escapeXml(param.q)} - Python(Jinja2):默认
{{ value }}就是 HTML 转义的;如果关了 autoescape,必须显式写{{ value|e }} - Node.js(EJS):用
<%= value %>(带等号)自动转义;<%- value %>不转义,慎用
错误示范:res.send('<h2>Search result for ' + req.query.q + '</h2>') —— 这等于把 <script></script> 直接送进浏览器。
文章转信息图。将文章/笔记转化为手机可读的 HTML 信息图,自动匹配视觉风格。触发场景:文章转图、笔记转图、信息图、转小红书图、做张图、可视化这篇文章、文生图。
立即学习“前端免费学习笔记(深入)”;
前端 JS 动态渲染时为什么不能用 innerHTML?
哪怕你服务端已转义,前端再用 element.innerHTML = userInput,就等于重开一扇门。浏览器会重新解析那段字符串,转义实体又还原成原始字符,<script> 就复活了。
- 纯文本展示:一律用
element.textContent = userInput - 必须渲染富文本(比如评论含链接、加粗):先过
DOMPurify.sanitize(userHtml),它默认剥离on*事件和javascript:协议 - React/Vue/Angular 等框架:它们的插值语法(如
{userInput})默认转义,但像 React 的dangerouslySetInnerHTML或 Vue 的v-html是例外,用之前必须确认内容已由后端或 DOMPurify 处理过
为什么正则替换 <script> 没用?
反射型 XSS 的绕过方式太多,比如:
-
<img src=1 onerror=alert(1)>—— 不含<script>,但能执行 JS -
<a href="javascript:alert(1)">click</a>——javascript:协议触发 - Unicode 变体、注释混淆、大小写混用(
<ScRiPt>)都能绕过简单正则
真正可靠的防线只有两个:服务端输出时按上下文做标准 HTML 转义,或者用 DOMPurify 这类经过大量 XSS 测试验证的库。自己写的“过滤器”基本等于摆设。


















