利用 PHP7 的 OPcache 执行 PHP 代码
字数 1529 2025-08-29 08:31:41

PHP7 OPcache 代码执行漏洞分析与利用

0x00 OPcache 简介

OPcache 是 PHP 7.0 内置的缓存引擎,通过将 PHP 脚本编译为字节码并存储在内存中来提升性能。关键特性:

  • 缓存文件存储在文件系统中,路径由 opcache.file_cache 配置指定
  • 缓存目录结构镜像 Web 目录结构
  • 缓存文件名格式为 原文件名.bin
  • 每个缓存文件包含 system_id 头信息,用于版本兼容性校验

0x01 漏洞利用原理

基本利用条件

  1. 目标服务器使用 PHP7 并启用 OPcache
  2. 存在文件上传漏洞
  3. Web 目录不可写但 OPcache 缓存目录可写
  4. OPcache 配置满足以下至少一项:
    • opcache.validate_timestamp = 0(PHP7 默认值为1)
    • opcache.file_cache_only = 1(PHP7 默认值为0)

攻击步骤

  1. 收集信息

    • 通过 phpinfo() 获取:
      • OPcache 缓存目录路径
      • Web 目录路径
      • 计算 system_id 所需的 PHP 和 Zend 版本信息
  2. 生成恶意缓存文件

    <?php system($_GET['cmd']); ?>
    
    • 在本地配置相同 PHP 环境
    • 访问该文件生成缓存文件(如 index.php.bin)
    • 修改文件头中的 system_id 为目标系统的值
  3. 上传覆盖

    • 将恶意缓存文件上传至目标缓存目录
    • 路径格式:/tmp/opcache/[system_id]/var/www/index.php.bin
  4. 触发执行

    • 访问对应的 PHP 文件(如 /var/www/index.php)
    • 恶意代码将被执行

0x02 高级绕过技术

绕过内存缓存(file_cache_only = 0)

当内存缓存优先时,需要:

  1. 等待服务器重启使内存缓存失效
  2. 或寻找框架中不常用的旧文件(如 WordPress 的 registration-functions.php)
    • 这些文件不会被主动加载,无内存缓存
    • 上传对应的恶意缓存文件后直接访问可触发

绕过时间戳校验(validate_timestamps = 1)

  1. 针对框架中长时间未修改的文件(如 WordPress 某些 2012 年后未更新的文件)
  2. 获取目标文件的准确时间戳
  3. 修改恶意缓存文件中的时间戳(偏移量 34 字节处)与源文件匹配

0x03 防御措施

  1. PHP 配置

    • 保持 opcache.validate_timestamp = 1(默认值)
    • 设置 opcache.file_cache_only = 0(默认值)
    • 限制 OPcache 缓存目录权限
  2. 代码审计

    • 严格检查文件上传功能
    • 移除不必要的旧文件
  3. 系统加固

    • 确保 Web 目录和缓存目录的适当权限
    • 定期更新 PHP 版本

0x04 技术细节补充

system_id 计算

system_id 是以下信息的 MD5 哈希:

  • PHP 版本号
  • Zend 扩展版本号
  • 各数据类型大小

可通过 phpinfo() 获取必要信息后计算得出。

缓存文件结构

  1. 文件头部包含签名和 system_id
  2. 时间戳位于偏移量 34 字节处
  3. 文件内容为编译后的字节码

环境要求

  • PHP 7.0 及以上版本
  • OPcache 扩展启用
  • 缓存目录可写(通常 www-data 用户有权限)

总结

OPcache 的代码执行漏洞展示了即使在没有 Web 目录写权限的情况下,攻击者仍可能通过缓存机制实现代码执行。这种攻击方式特别针对 PHP7 环境,强调了安全配置和权限控制的重要性。防御的关键在于合理的 OPcache 配置、严格的权限管理和及时清理不必要的旧文件。

PHP7 OPcache 代码执行漏洞分析与利用 0x00 OPcache 简介 OPcache 是 PHP 7.0 内置的缓存引擎,通过将 PHP 脚本编译为字节码并存储在内存中来提升性能。关键特性: 缓存文件存储在文件系统中,路径由 opcache.file_cache 配置指定 缓存目录结构镜像 Web 目录结构 缓存文件名格式为 原文件名.bin 每个缓存文件包含 system_id 头信息,用于版本兼容性校验 0x01 漏洞利用原理 基本利用条件 目标服务器使用 PHP7 并启用 OPcache 存在文件上传漏洞 Web 目录不可写但 OPcache 缓存目录可写 OPcache 配置满足以下至少一项: opcache.validate_timestamp = 0 (PHP7 默认值为1) opcache.file_cache_only = 1 (PHP7 默认值为0) 攻击步骤 收集信息 : 通过 phpinfo() 获取: OPcache 缓存目录路径 Web 目录路径 计算 system_ id 所需的 PHP 和 Zend 版本信息 生成恶意缓存文件 : 在本地配置相同 PHP 环境 访问该文件生成缓存文件(如 index.php.bin) 修改文件头中的 system_ id 为目标系统的值 上传覆盖 : 将恶意缓存文件上传至目标缓存目录 路径格式: /tmp/opcache/[system_id]/var/www/index.php.bin 触发执行 : 访问对应的 PHP 文件(如 /var/www/index.php) 恶意代码将被执行 0x02 高级绕过技术 绕过内存缓存(file_ cache_ only = 0) 当内存缓存优先时,需要: 等待服务器重启使内存缓存失效 或寻找框架中不常用的旧文件(如 WordPress 的 registration-functions.php) 这些文件不会被主动加载,无内存缓存 上传对应的恶意缓存文件后直接访问可触发 绕过时间戳校验(validate_ timestamps = 1) 针对框架中长时间未修改的文件(如 WordPress 某些 2012 年后未更新的文件) 获取目标文件的准确时间戳 修改恶意缓存文件中的时间戳(偏移量 34 字节处)与源文件匹配 0x03 防御措施 PHP 配置 : 保持 opcache.validate_timestamp = 1 (默认值) 设置 opcache.file_cache_only = 0 (默认值) 限制 OPcache 缓存目录权限 代码审计 : 严格检查文件上传功能 移除不必要的旧文件 系统加固 : 确保 Web 目录和缓存目录的适当权限 定期更新 PHP 版本 0x04 技术细节补充 system_ id 计算 system_ id 是以下信息的 MD5 哈希: PHP 版本号 Zend 扩展版本号 各数据类型大小 可通过 phpinfo() 获取必要信息后计算得出。 缓存文件结构 文件头部包含签名和 system_ id 时间戳位于偏移量 34 字节处 文件内容为编译后的字节码 环境要求 PHP 7.0 及以上版本 OPcache 扩展启用 缓存目录可写(通常 www-data 用户有权限) 总结 OPcache 的代码执行漏洞展示了即使在没有 Web 目录写权限的情况下,攻击者仍可能通过缓存机制实现代码执行。这种攻击方式特别针对 PHP7 环境,强调了安全配置和权限控制的重要性。防御的关键在于合理的 OPcache 配置、严格的权限管理和及时清理不必要的旧文件。