**针对 PHP-Proxy 的已知明文攻击:从破碎的加密到 FastCGI 远程代码执行(RCE)**

30 阅读2分钟

官网:http://securitytech.cc/

针对 PHP-Proxy 的已知明文攻击:从破碎的加密到 FastCGI 远程代码执行(RCE)

一次凯撒密码的错误实现,如何通过已知明文攻击与 FastCGI 协议利用,将 URL 加密彻底演变为整台服务器被攻陷


引言(Introduction)

在研究 Web 代理实现时,我发现了 PHP-Proxy 这个项目。它引起我注意的原因在于:尽管该项目早已被开发者弃用,但仍然有大量实例在生产环境中运行

原本只是一次常规的安全评估,却逐渐演变成了一次关于单点密码学缺陷如何瓦解整个应用安全模型的深入分析。

按 Enter 键或点击图片查看大图

这就是我如何从弱加密一路追踪到整台服务器被完全攻陷的全过程。


初识 PHP-Proxy(First Encounter with PHP-Proxy)

我首先检查了 PHP-Proxy 是如何处理用户输入的。

当用户通过表单提交一个 URL 时,会发生一件有趣的事情: 应用并不会直接使用该 URL,而是先对其进行加密,然后重定向到:

/?q=<ENCRYPTED_URL>

这个 q 参数中存放的是 Base64 编码后的密文 URL

按 Enter 键或点击图片查看大图

初步 SSRF 尝试失败

我的第一反应是测试 SSRF,于是提交了:

file:///etc/passwd

但应用有一个防护机制:add_http 函数会自动给不以 http://https:// 开头的 URL 添加 http:// 前缀,起到了协议强制校验的作用。

结果是:

file:///etc/passwd
↓
http://file:///etc/passwd

cURL 会将其视为一个非法 HTTP URL,而不是 file:// 协议请求。 SSRF 攻击在入口处直接失败。

我需要换一种思路。


请求流程分析

我继续梳理应用内部逻辑。

proxify_url 函数负责构造重定向 URL,并在此过程中完成加密。

按 Enter 键或点击图片查看大图

表单提交完成后,应用进入核心逻辑阶段 —— 拉取远程资源。 此时 URL 已经从 q 参数中完成解密

按 Enter 键或点击图片查看大图

我发现 Proxy 类中的 forward 方法内部直接使用了 cURL:

  • 使用 curl_exec()
    • CURLOPT_URL 设置为用户提供的 URL

按 Enter 键或点击图片查看大图

关键发现

整个请求链路中,没有任何 URL 校验:

  • 不校验协议(scheme)
    • 不校验主机名
    • 不校验端口

而 cURL 默认支持多种协议:

  • file:// —— 本地文件
    • gopher:// —— 原始 TCP 数据
    • dict:// —— 字典协议
    • ftp:// —— 文件传输

只要能绕过 add_http,这些危险协议就能被直接利用。

按 Enter 键或点击图片查看大图

PHP-Proxy 中存在两条请求路径:

表单提交路径(受保护) vs 直接访问加密参数(绕过协议校验)

结论很明确: