多维绕过RCE

发布时间 2023-09-18 21:33:55作者: Eddie_Murphy

来自:

[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$,也一样。