php2shell:三条链 测试版
同一份公告,三种不同的攻击。目标条件不同,能证明的东西也不同。
结果属于产出它的那条链。单说“php2shell 可用”没有意义。
| 链 | 需要 | 证明 |
|---|---|---|
| A — 应用自身的 sink | include 参数、可写会话目录 | 以 Web 用户身份在应用内执行代码 |
| B — CVE 引擎链 | mod_php prefork、单 worker、display_errors、未修补 | 在主机上执行命令(无需 sink) |
| C — FPM 可用性 | FPM 池、请求体大于 memory_limit | 仅致不可用,绝不代表拿到权限 |
链 A — 应用自身的 sink
上传进度写入文件,应用把它包含进来。没有内存破坏,没有偏移量。
- 应用本来就有的 include / LFI 参数——是探测到的,不是假设的
- 可写的会话目录
- 请求体大于 memory_limit
- 在已修补的 PHP 上同样可用——它不是 2026 年的那个 CVE
php2shell lfi https://site/ --attempt --upload / --lfi "https://site/?page={page}"
上传的标记以 Web 用户身份执行。结论属于应用,修复也属于应用。
把它叫作“php2shell RCE”是错的:PHP 补丁挡不住它。
链 B — CVE 引擎链
内存耗尽叠加过期的请求状态,破坏已释放的内存;伪造 HashTable 让 pDestructor = system() 执行命令。
- Apache prefork 下的 mod_php,不是 FPM
- 两个请求必须由同一个子进程处理:单个 worker 或固定 worker;多个 worker 也没问题
- display_errors 开,memory_limit 相对请求体很小,session.upload_progress 开,use_strict_mode 关
- 未修补的 8.3 / 8.4 / 8.5,且偏移量匹配该构建
php2shell-chain https://site/index.php --attempt -c "id>p.txt" --fetch /p.txt
PROOF: uid=33(www-data)——命令输出,前面是泄漏的 chunk 与 libphp 基址。
它前面有两步小结果:4096 字节 Set-Cookie 泄漏与 libphp 泄漏。只有泄漏没有 PROOF,说明布局不对,不是站点安全。
已在 8.3 / 8.4 / 8.5 官方构建上验证;构建由表内遍历自动发现。
链 C — FPM 上的可用性
超大的表单字段抽干进程池;FPM 以代码 70 结束每个 worker 并补上新的。
- PHP-FPM,任何池大小
- memory_limit 低于请求体,边缘不限制请求体
- N 个请求抽干 N 个进程的池
php-dos https://site/ --attempt --workers 20 --mb 12
请求失败与延迟。永远拿不到 shell,我们也从不把它报告为访问权。
当链 B 不适用时,这是诚实的答案:可以让它下线,不能执行代码。
运行会选哪一条?
由计划按顺序决定:
- 目标已记录 sink → 先用 A:几秒,无需偏移量,修补过的 PHP 也能用
- 无 sink、mod_php prefork、未修补 → B
- 无 sink、FPM → C,只报告可用性
- 一条链绝不继承另一条链的结果
未验证或不可及:PHP 5.4–8.2 的泄漏布局、display_errors=Off、Windows。没有 PROOF 行就是未证明,绝不是“安全”。