一、转义规则概述
核心目标:防止用户输入被浏览器解析为可执行代码,确保输入始终被视为数据而非代码。
关键策略:根据数据嵌入的上下文环境(HTML、JavaScript、CSS 等),对特殊字符进行转义或编码。
二、不同上下文的转义规则
1. HTML 正文(标签之间)
场景:用户输入直接插入到 HTML 标签内部。
<div>用户输入内容</div>
转义规则:
字符 | 转义后的实体 | 防御目的 |
---|---|---|
< |
< |
防止插入新标签(如 <script> ) |
> |
> |
防止闭合已有标签 |
& |
& |
防止 HTML 实体被解析 |
示例:
攻击输入:
<img src=x onerror=alert(1)>
转义后:
<img src=x onerror=alert(1)>
结果:显示为文本,无法执行。
2. HTML 属性值
场景:用户输入插入到 HTML 属性值中(非事件属性)。
<input value="用户输入内容">
转义规则:
字符 | 转义后的实体 | 防御目的 |
---|---|---|
" |
" |
防止闭合属性,注入新属性或事件 |
' |
' |
同上(适用于单引号属性) |
& |
& |
防止 URL 伪协议(如 javascript: ) |
示例:
攻击输入:
" onclick="alert(1)
转义后:
" onclick="alert(1)
结果:无法闭合属性,事件注入失败。
3. JavaScript 上下文
场景:用户输入插入到 JavaScript 代码或事件属性中。
<script>var username = "用户输入内容";</script> <button οnclick="用户输入内容">点击</button>
转义规则:
字符 | 转义方式 | 防御目的 |
---|---|---|
" |
\" |
防止闭合字符串 |
' |
\' |
同上(单引号字符串) |
\ |
\\ |
防止转义后续字符 |
</script> |
<\/script> |
防止提前结束脚本块 |
示例:
攻击输入:
";alert(1);//
转义后:
\";alert(1);//
结果:
var username = "\";alert(1);//";
→ 语法错误。
4. URL 上下文
场景:用户输入插入到 URL 属性中。
<a href="用户输入内容">链接</a>
转义规则:
防御措施 | 说明 |
---|---|
协议白名单校验 | 只允许 http:// 、https:// 等安全协议 |
URL 编码保留字符 | 使用 encodeURIComponent() 转义特殊符号(如 空格→%20 ) |
禁止 javascript: 伪协议 |
直接拦截或替换 |
示例:
攻击输入:
javascript:alert(1)
防御后:
javascript%3Aalert(1)
或直接拦截。
5. CSS 上下文
场景:用户输入插入到 CSS 属性中。
<div style="color:用户输入内容">文本</div>
转义规则:
字符 | 转义方式 | 防御目的 |
---|---|---|
" |
\22 (十六进制) |
防止闭合 CSS 字符串 |
' |
\27 (十六进制) |
同上 |
() |
转义或删除 | 防止调用危险函数(如 expression ) |
示例:
攻击输入:
red;);expression(alert(1))
转义后:
red;\);expression\(alert\(1\)\)
→ 无法执行。
三、通用防御原则
上下文感知:根据数据最终嵌入的位置(HTML/JS/CSS)选择转义方式。
编码优先:始终对用户输入进行编码,而非依赖黑名单过滤。
使用安全 API:
避免
innerHTML
,优先使用textContent
。使用框架(React/Vue)的自动转义机制。
启用 CSP:通过内容安全策略限制脚本来源。
Content-Security-Policy: default-src 'self'
四、常用转义工具
场景 | 工具 | 作用 |
---|---|---|
HTML 转义 | Lodash _.escape |
转义 < > & " ' |
JS 转义 | JSON.stringify() |
自动处理字符串中的特殊字符 |
富文本过滤 | DOMPurify | 清理危险标签,保留安全 HTML |
URL 编码 | encodeURIComponent() |
转义 URL 保留字符 |
五、总结
攻击场景 | 防御要点 | 类比 |
---|---|---|
HTML 标签 | 转义 < > & |
拆解乐高积木的拼接卡扣 |
HTML 属性 | 转义 " ' |
封死信封的封口处 |
JavaScript | 转义 " ' \ |
粘牢代码字符串的胶水 |
URL | 校验协议 + 编码保留字符 | 检查快递地址的安全性 |
核心思想:通过转义让浏览器始终将用户输入视为数据,而非代码。多层防御(转义 + CSP + 安全 API)是抵御 XSS 的关键!