美文网首页
DVWA 总结系列之 CSP 篇

DVWA 总结系列之 CSP 篇

作者: JackoQm | 来源:发表于2018-12-20 22:36 被阅读0次

    前前言

    本人的个人博客网址:www.QmSharing.space,所有的文章都可以在里面找到,欢迎各位大佬前来参观并留下宝贵的建议,大家一起学习一起成长 :-)

    本题目标

    本题好像是 v1.10 版本新加入的, 因此网上的分析文章并不是很多.

    CSP(Content Security Policy) 是一种用来防止 XSS 攻击的手段, 通过在头部添加 Content-Security-Policy 的相关参数, 来限制未知(不信任)来源的 javascript 的执行从而防止 XSS 攻击. 本题并不是要介绍这种技术有什么漏洞, 而且本题所导致的 XSS 攻击都是因为开发者的不正当配置所致. 所以本题仅仅让你能成功执行一个弹框的 XSS 注入即可.

    Low

    因为 CSP 主要是客户端进行防御, 所以服务端的核心代码应该是没有变的(除了 CSP 头):

    # 主要就是设置 HTTP 头部信息, 后面就不粘代码了, 直接分析头部即可
    $headerCSP = "Content-Security-Policy: script-src 'self' https://pastebin.com  example.com code.jquery.com https://ssl.google-analytics.com ;"; // allows js from self, pastebin.com, jquery and google analytics.
    
    header($headerCSP);
    

    这个头部信息的具体含义可以参考这个 参考文档, 这里直接理解就是能从 https://pastebin.com 等网站加载 javascript, 你可以试试从自己的搭建的服务器中加载 javascript, 结果如下:

    加载结果

    可以明显的看到, 这个 javascript 的加载被 blocked 了(估计 Firefox 的插件 No-script 也是基于这个的). 既然不能从未指定的源加载 javascript, 那我可以从它信任的源, 比如 https://pastebin.com 中来加载. 可能有人不知道这个网站是什么, 我开始也不知道的, 但你打开就会发现这就是个共享粘贴板, 允许你粘贴任何文本内容.

    那我们就可以在这个粘贴板网站中写入一段恶意 javascript, 比如 alert("hacked"), 然后, 通过该网站的 raw 形式(原生)来显示, 我当时生成的网址是这个 恶意 javascript, 然后你就可以在 URL 栏中输入这个网址, 让浏览器将这个远程加载文本当作 javascript 来执行. Boom! 成功注入, 结果你们自己去试哈.

    Medium

    通过浏览器抓包可以看到:

    script-src 'self' 'unsafe-inline' 'nonce-TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=';
    

    这次使用了两个新的参数(self 不算哈). 其中 'unsafe-inline' 代表可以执行诸如 onclick 等事件或 script 标签内的内容这类 javascript, 而后者就是指如果你要使用 script 标签加载 javascript, 你需要指明其 nonce 值, 比如 <script nonce="TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA=">alert('hacked')</script>这个就能正常加载, 从而造成 XSS 注入.

    但需要注意的是, 如果你测试 <img src=hacked onerror=alert('hacked')> 这类在标签内执行的 javascript, 会得到如下结果:

    加载标签 js

    错误提示告诉我们, 因为头部指定了 nonce 值, 所以自动忽略了 'unsafe-inline' 这个参数. 因此可以判断这两个参数是不能共存的, 而且如果共存, 后者是会覆盖前者的.

    这里还有个有意思的地方, 你看那个 nonce 的值很明显是个 base64 编码, 我就无聊去解码了一下, 嗯... 原文"TmV2ZXIgZ29pbmcgdG8gZ2l2ZSB5b3UgdXA="转换后是 "Never going to give you up", 还是给出题者 666. 不过呢, 正确的防御方式下的 nonce 值不应该是个固定值, 而是应该是个随机生成的值, 这样才能真正达到防止 XSS 的目的.

    High

    这个级别已经没有输入框了, 不过题目已经给了足够多的提示. 首先先看一下 CSP 头, 发现只有 script-src 'self';, 看来只允许本界面加载的 javascript 执行. 然后研究了一下这个点击显示答案的逻辑(逻辑在 source/high.js里), 大致如下: 点击按钮 -> js 生成一个 script 标签(src 指向 source/jsonp.php?callback=solveNum), 并把它加入到 DOM 中 -> js 中定义了一个 solveNum 的函数 -> 因此 script 标签会把远程加载的 solveSum({"answer":"15"}) 当作 js 代码执行, 而这个形式正好就是调用了 solveSum 函数, 然后这个函数就会在界面适当的位置写入答案.

    本来嘛, 应该是没办法修改在服务器的 jsonp.php 文件的(除非结合别的漏洞, 拿 shell 后修改). 然而, 我后来在查看服务端源码的时候发现了这个:

    if (isset ($_POST['include'])) {
    $page[ 'body' ] .= "
        " . $_POST['include'] . "
    ";
    }
    # 剩余的显示代码
    

    666, 竟然还偷偷接收 include 参数(不清楚是不是作者复用了之前 Medium 的代码). 总之, 这肯定能作为一个注入点, 我开始打算用简单粗暴的 <script>alert('hacked')</script> 来搞定的, 谁知道, 这种是属于 'unsafe-inline' 形式的, 所以被限制执行了. 嗯... 既然如此的话, 那我就利用 src 吧.

    if (array_key_exists ("callback", $_GET)) {
        $callback = $_GET['callback'];
    } else {
        return "";
    }
    
    $outp = array ("answer" => "15");
    # 这个 callback 可以被控制的
    echo $callback . "(".json_encode($outp).")";
    

    这个即使你不看源码, 你做几个测试也会发现, 那个 callback 参数可以被操控以生成任何你想要得到的结果, 比如 alert, 因此可以构造 Payload: <script src="source/jsonp.php?callback=alert('hacked');"></script>, 并把这个当做 include 参数传给界面就 Boom! 注入成功!

    Impossible

    该级别主要还是修复了 callback 参数可被控制问题(毕竟这是问题根源):

    $outp = array ("answer" => "15");
    # 写死的话, 就没办法被控制了
    echo "solveSum (".json_encode($outp).")";
    

    参考链接

    相关文章

      网友评论

          本文标题:DVWA 总结系列之 CSP 篇

          本文链接:https://www.haomeiwen.com/subject/iqfpkqtx.html