DVWA靶场——Content Security Policy Bypass(CSP 内容安全策略)
CSPContent Security Policy是一种浏览器安全机制通过 HTTP 响应头告诉浏览器“这个页面只能加载哪些来源的资源脚本、样式、图片等其他的一律禁止。”主要是为了缓解潜在的跨站脚本问题(XSS)浏览器的扩展程序系统引入了内容安全策略这个概念。原来应对XSS攻时主要采用函数过滤转义输入中的特殊字符、标签、文本来规避攻击。CSP的实质就是白名单制度开发人员明确告诉客户端哪些外部资源可以加载和执行。开发者只需要提供配置实现和执行全部由浏览器完成。这对我们来说是一个全新的内容所以务必理解它的原理下面给出一个具体的场景带大家理解一下CSP 说来自 pastebin.com 的脚本是安全的 攻击者在 pastebin.com 上放恶意脚本 浏览器因为是 pastebin.com所以执行 结果CSP 被绕过这是浏览器配置CSP后的工作流程用户访问页面 ↓ 浏览器发起 Request请求页面 ↓ 服务器处理请求 ↓ 服务器返回 Response包含 HTML 响应头 ↓ 浏览器解析 Response Headers ↓ 发现 Content-Security-Policy ↓ 浏览器按照策略限制后续资源加载明白了它的原理这个漏洞最重要的点就在于找到那个它信任的来源Low源码分析?php $headerCSP Content-Security-Policy: script-src self https://pastebin.com hastebin.com example.com code.jquery.com https://ssl.google-analytics.com ;; // allows js from self, pastebin.com, hastebin.com, jquery and google analytics. header($headerCSP); # These might work if you cant create your own for some reason # https://pastebin.com/raw/R570EE00 # https://hastebin.com/raw/ohulaquzex ? ?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 ;后端完全信任用户输入没有做任何校验只依赖 CSP 来防御并且开发者给了我们两个URL示例https://pastebin.com/raw/R570EE00 https://hastebin.com/raw/ohulaquzex回到关卡中我们先抓个包放行在返回头里找找看有没有信息直接告诉了我们CSP 策略Content-Security-Policy: script-src self https://pastebin.com hastebin.com example.com code.jquery.com https://ssl.google-analytics.com ;我们来解读一下来源是否允许self同源允许https://pastebin.com允许hastebin.com允许注意没有 https:// 前缀example.com允许code.jquery.com允许https://ssl.google-analytics.com允许我们就试试https://pastebin.com这个网站它是一个快速文本分享网站构造弹框将URL复制进输入框include我的浏览器报错了了解了一下原因如下Pastebin 返回给浏览器的文件类型是纯文本text/plain但浏览器执行脚本需要JavaScript类型application/javascript类型不匹配所以拒绝执行。这是现代浏览器为提升安全性而采取的统一标准行为因此我们不用纠结是否弹框了解其原理即可。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 ;移除了所有第三方域名Pastebin、hastebin 等全部删除并且script-src 还可以设置一些特殊值unsafe-inline 允许执行页面内嵌的 script 标签和事件监听函数 引入了 nonce一次性随机数 机制CSP策略$headerCSP Content-Security-Policy: script-src self unsafe-inline nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA;;指令含义self允许同源脚本unsafe-inline允许内联脚本scriptalert(1)/scriptnonce-...允许带有指定 nonce 值的脚本标签Nonce 机制nonce Number used ONCE一次性数字服务器生成一个随机值同时放在 CSP 头里nonce-abc123放在合法的script标签里script nonceabc123浏览器只会执行nonce 值匹配的内联脚本。开发者给了我们提示能够直接拿到nonce通过内连注入script nonceTmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXAalert(1)/script成功弹窗了High源码分析vulnerabilities/csp/source/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 ;vulnerabilities/csp/source/high.jsfunction 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(); }); }1.在high.php中设置了csp头规定只允许从同源的脚本加载2.提交表单的时候如果存在POST形式的include参数3.游览器执行clickbutton,动态创建script元素将src属性设置为‘source/jsonp.php?callbacksolveSum’json .php是一个远程脚本的url4.加载远程脚本返回数据给solveSum展示到页面CSP策略$headerCSP Content-Security-Policy: script-src self;;self仅允许同源脚本无unsafe-inline内联脚本被禁止无第三方域名外部脚本被禁止我们打开开发者工具输入var s document.createElement(script); // 创建 script 标签 s.src source/jsonp.php?callbackalert(1)//; // 设置 src 属性 document.body.appendChild(s); // 把 script 添加到页面中其效果是在页面中动态插入了一个脚本标签script srcsource/jsonp.php?callbackalert(1)///script浏览器工作流程我们的 Console 代码 ↓ 创建 script srcsource/jsonp.php?callbackalert(1)// ↓ 浏览器请求该 URL ↓ jsonp.php 返回alert(1)//({answer: 15}) ↓ 浏览器执行这段 JavaScript ↓ alert(1) 被执行 → 弹窗因为source/jsonp.php是同源的都在http://192.168.158.130:5432下因此被成功执行impossible源码分析vulnerabilities/csp/source/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 ;vulnerabilities/csp/source/impossible.jsfunction 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(); }); }这个级别通过不接受用户输入和硬编码返回内容彻底封死了 JSONP callback 注入的攻击路径结合 CSP 的self限制使得该模块在当前环境下真正无法绕过攻击方式能否成功原因输入框注入内联脚本❌CSP 禁止unsafe-inline输入框注入外部脚本❌CSP 只允许self输入框注入同源脚本❌后端虽接收include但前端无输入框修改s.src参数❌JavaScript 代码已固定用户无法控制修改jsonp_impossible.php的响应❌需要服务器文件写入权限Console 执行s.src ...?callback...❌jsonp_impossible.php不接受 callback 参数