对PHP-FPM RCE漏洞(CVE-2019-11043)的调试和分析
字数 1519 2025-08-26 22:11:28

PHP-FPM RCE漏洞(CVE-2019-11043)深入分析与调试指南

0x00 漏洞概述

CVE-2019-11043是一个影响PHP-FPM的远程代码执行漏洞,当Nginx与PHP-FPM配合使用时,通过精心构造的恶意请求可以导致远程代码执行。该漏洞的核心在于Nginx处理URL时的正则表达式匹配问题与PHP-FPM内存操作的结合利用。

0x01 漏洞成因

根本原因:Nginx处理URL的正则表达式存在缺陷,在特定情况下会将path_info置空。

关键点

  • Nginx使用libpcre.so库处理正则表达式
  • 当URL中包含换行符(%0A)时,正则匹配行为异常
  • 这种异常导致PHP-FPM接收到的PATH_INFO环境变量为空

0x02 环境准备

编译调试版PHP-FPM

./configure --prefix=/root/php7.3.10 \
            --enable-phpdbg-debug \
            --enable-debug \
            --enable-fpm \
            CFLAGS="-g3 -gdwarf-4"

Nginx配置示例

location ~ [^/]\.php(/|$) {
    fastcgi_split_path_info ^(.+?\.php)(/.*)$;
    include fastcgi_params;

    fastcgi_param PATH_INFO       $fastcgi_path_info;
    fastcgi_index index.php;
    fastcgi_param  REDIRECT_STATUS    200;
    fastcgi_param  SCRIPT_FILENAME /opt/nginx-src/nginx-branches-stable-1.10/html$fastcgi_script_name;
    fastcgi_param  DOCUMENT_ROOT /opt/nginx-src/nginx-branches-stable-1.10/html;
    fastcgi_pass 127.0.0.1:9000;
}

0x03 漏洞利用原理

关键数据结构

  1. fcgi_hash_bucket:哈希表结构,保存请求的环境变量键值对
  2. fcgi_hash_seg:存储键值对的实际数据结构,包含:
    • pos:指向下一个要插入变量的位置
    • end:当前数据块的终点
    • next:指向下一个fcgi_hash_seg
    • data:连续的键值对存储区域

漏洞触发流程

  1. 初始状态

    • env_path_info指针为空
    • pilen(路径信息长度)为0
  2. 内存操作异常

    • path_info被赋值为env_path_info指针向上偏移slen的值
    • 通过精心构造的请求,使path_info指针减去特定长度后,恰好指向fcgi_hash_segpos指针最低位
  3. 内存覆盖

    • pos指针的最低位清零
    • 通过FCGI_PUTENV函数向被修改的pos指针位置写入恶意数据
  4. 哈希碰撞利用

    • 需要将PHP_VALUE覆盖到与它哈希值相同的变量上(如HTTP_EBUT
    • 通过长度控制和哈希碰撞,确保PHP-FPM会读取被覆盖的变量

0x04 调试过程详解

关键断点

init_request_info函数设置断点,观察以下关键变量:

  1. env_path_info的值和指针地址
  2. path_info的赋值过程
  3. fcgi_hash_seg结构的内存布局

内存操作观察点

  1. pos指针修改前

    • 记录pos指针的原始值
    • 确认其指向的内存区域
  2. pos指针修改后

    • 观察最低位被清零的效果
    • 确认指针偏移后的新位置
  3. 变量写入过程

    • 跟踪FCGI_PUTENV函数的执行
    • 观察fcgi_hash_set函数如何向被修改的pos位置写入数据

对齐调整

由于请求路径前有/index.php/(11字节),需要:

  1. 计算正确的偏移量
  2. 通过添加HTTP头确保h->data->pos正确对齐

0x05 利用示例

最简单的利用方式是设置auto_prepend_file

  1. 在web目录创建恶意文件a
  2. 构造请求使PHP-FPM加载该文件作为前置文件

0x06 防御措施

  1. 升级PHP版本:官方已发布修复补丁
  2. Nginx配置检查:确保正确处理PATH_INFO
  3. 输入过滤:过滤包含换行符的请求
  4. 权限控制:限制PHP-FPM进程权限

0x07 参考资源

  1. PCRE正则表达式库分析
  2. 90sec社区分析
  3. Seebug Paper分析
  4. 官方PoC代码

0x08 总结

该漏洞利用涉及多个组件的交互异常,包括:

  • Nginx的正则处理
  • PHP-FPM的内存管理
  • 环境变量的哈希存储机制

成功利用需要精确控制内存布局和指针操作,展示了系统组件间交互可能引入的复杂安全问题。

PHP-FPM RCE漏洞(CVE-2019-11043)深入分析与调试指南 0x00 漏洞概述 CVE-2019-11043是一个影响PHP-FPM的远程代码执行漏洞,当Nginx与PHP-FPM配合使用时,通过精心构造的恶意请求可以导致远程代码执行。该漏洞的核心在于Nginx处理URL时的正则表达式匹配问题与PHP-FPM内存操作的结合利用。 0x01 漏洞成因 根本原因 :Nginx处理URL的正则表达式存在缺陷,在特定情况下会将 path_info 置空。 关键点 : Nginx使用 libpcre.so 库处理正则表达式 当URL中包含换行符( %0A )时,正则匹配行为异常 这种异常导致PHP-FPM接收到的 PATH_INFO 环境变量为空 0x02 环境准备 编译调试版PHP-FPM Nginx配置示例 0x03 漏洞利用原理 关键数据结构 fcgi_ hash_ bucket :哈希表结构,保存请求的环境变量键值对 fcgi_ hash_ seg :存储键值对的实际数据结构,包含: pos :指向下一个要插入变量的位置 end :当前数据块的终点 next :指向下一个fcgi_ hash_ seg data :连续的键值对存储区域 漏洞触发流程 初始状态 : env_path_info 指针为空 pilen (路径信息长度)为0 内存操作异常 : path_info 被赋值为 env_path_info 指针向上偏移 slen 的值 通过精心构造的请求,使 path_info 指针减去特定长度后,恰好指向 fcgi_hash_seg 的 pos 指针最低位 内存覆盖 : 将 pos 指针的最低位清零 通过 FCGI_PUTENV 函数向被修改的 pos 指针位置写入恶意数据 哈希碰撞利用 : 需要将 PHP_VALUE 覆盖到与它哈希值相同的变量上(如 HTTP_EBUT ) 通过长度控制和哈希碰撞,确保PHP-FPM会读取被覆盖的变量 0x04 调试过程详解 关键断点 在 init_request_info 函数设置断点,观察以下关键变量: env_path_info 的值和指针地址 path_info 的赋值过程 fcgi_hash_seg 结构的内存布局 内存操作观察点 pos指针修改前 : 记录 pos 指针的原始值 确认其指向的内存区域 pos指针修改后 : 观察最低位被清零的效果 确认指针偏移后的新位置 变量写入过程 : 跟踪 FCGI_PUTENV 函数的执行 观察 fcgi_hash_set 函数如何向被修改的 pos 位置写入数据 对齐调整 由于请求路径前有 /index.php/ (11字节),需要: 计算正确的偏移量 通过添加HTTP头确保 h->data->pos 正确对齐 0x05 利用示例 最简单的利用方式是设置 auto_prepend_file : 在web目录创建恶意文件 a 构造请求使PHP-FPM加载该文件作为前置文件 0x06 防御措施 升级PHP版本 :官方已发布修复补丁 Nginx配置检查 :确保正确处理PATH_ INFO 输入过滤 :过滤包含换行符的请求 权限控制 :限制PHP-FPM进程权限 0x07 参考资源 PCRE正则表达式库分析 90sec社区分析 Seebug Paper分析 官方PoC代码 0x08 总结 该漏洞利用涉及多个组件的交互异常,包括: Nginx的正则处理 PHP-FPM的内存管理 环境变量的哈希存储机制 成功利用需要精确控制内存布局和指针操作,展示了系统组件间交互可能引入的复杂安全问题。