此仓库包含一个本地 Docker 实验室,用于重现和验证 CVE-2026-10795,这是一个未认证的身份认证绕过漏洞,影响通过其 UpdraftCentral 远程通信层的 UpdraftPlus WordPress 插件。
易受攻击的行为存在于 UpdraftCentral RPC 消息处理流程中。在易受攻击的版本中,伪造的 format=1 RPC 消息可以绕过签名验证,触发失败的 RSA 解密路径,并仍然以可预测的 null key/null IV 行为到达对称解密。这允许精心构造的加密 RPC 消息被接受并作为 UpdraftCentral 命令进行调度。
此实验室比较两个 UpdraftPlus 版本:
| 服务 | UpdraftPlus 版本 | 目的 | URL |
|---|---|---|---|
vuln | 1.26.4 | 易受攻击的比较目标 | http://127.0.0.1:8081 |
patched | 1.26.5 | 已修补的比较目标 | http://127.0.0.1:8082 |
演示的链条是:```text Unauthenticated attacker → forged UpdraftCentral RPC request → format=1 signature verification bypass → failed RSA decrypt not rejected in vulnerable version → predictable zero-key/zero-IV decrypt path → forged JSON RPC command accepted → privileged UpdraftCentral command dispatch → plugin.upload_plugin → install and activate marker plugin → hard-coded /usr/bin/id proof endpoint
主要漏洞是认证绕过。该实验室表明,当存在特权 UpdraftCentral 密钥状态时,此绕过可与 RCE 式影响链式结合,因为 UpdraftCentral 暴露了合法的插件管理命令,这些命令可以安装和激活 WordPress 插件。
这不是直接的命令注入漏洞。代码执行证明来自在绕过 RPC 认证边界后滥用经过身份验证的插件安装功能。
本实验室仅设计用于受控的本地研究、源代码级理解和作品集演示。
## 已验证的事实
| 声明 | 证据 | 如何在本实验室中验证 |
| ---------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------ |
| UpdraftPlus 1.26.4 在本实验室中存在漏洞。 | 易受攻击的服务接受伪造的 `format=1` RPC 消息并调度 `plugin.upload_plugin`。 | 运行 `python3 poc/poc.py --url http://127.0.0.1:8081`。 |
| UpdraftPlus 1.26.5 在本实验室中阻止了伪造的消息。 | 修补后的服务不返回 RPC 响应体,也不调度伪造的命令。 | 运行 `python3 poc/poc.py --url http://127.0.0.1:8082`。 |
| 该问题是 UpdraftCentral RPC 层中的认证绕过。 | 在易受攻击的版本中,伪造的未经身份验证的 RPC 请求可以到达命令调度。 | 比较端口 `8081` 和 `8082` 的 `--ping` 行为。 |
| 实验室没有预安装标记插件。 | 设置仅安装 WordPress、UpdraftPlus 和本地 UpdraftCentral 密钥状态。 | 在运行 PoC 之前检查 `/wp-json/cve-lab/v1/id`。 |
| PoC 通过伪造的 RPC 安装标记插件。 | PoC 在 RPC 数据字段中发送带有 ZIP 插件负载的 `plugin.upload_plugin`。 | 运行 PoC,然后请求 `/wp-json/cve-lab/v1/id`。 |
| 易受攻击的目标达到 RCE 式影响。 | 标记插件暴露了一个硬编码的端点,返回 `/usr/bin/id` 的输出。 | 易受攻击的目标返回 `uid=33(www-data) gid=33(www-data)`。 |
| 修补后的目标不会安装标记插件。 | 在修补后的服务上,标记端点返回 `404 rest_no_route`。 | 对 `http://127.0.0.1:8082` 运行 PoC。 |
| 实验室需要 UpdraftCentral 密钥状态。 | UpdraftCentral 调度依赖于本地密钥条目和相关元数据。 | 查看 `scripts/setup-wordpress.sh`。 |
## 假设与未知因素
本实验室有意植入本地 UpdraftCentral 密钥状态,以重现已配置远程控制的站点条件。
植入的密钥状态是实验室的先决条件,而非漏洞本身。它使实验室能够一致地利用易受攻击的 RPC 解析和解密路径。
实验室并不声称每个 UpdraftPlus 安装都立即可以被利用。所演示的链取决于是否存在与特权 WordPress 用户关联的本地 UpdraftCentral 密钥条目。
本实验室通过安装一个暴露硬编码 `/usr/bin/id` 证明端点的标记插件,演示了受控的 RCE 式影响。它不提供通用 Web shell、任意命令执行参数、反向 shell、持久化机制、凭证窃取或外部回调。
PoC 仅针对本地目标,默认拒绝非本地主机名。
## 根本原因总结
根本原因是易受攻击的 UpdraftPlus 版本中对 UpdraftCentral RPC 消息的验证不恰当。
易受攻击的 RPC 流程接受 `format=1` 消息。`format=1` 路径不需要像较新消息格式那样的相同签名验证。
高级别问题是:```text
format=1 message
→ signature verification is bypassed
→ RSA decrypt of the symmetric key can fail
→ failed decrypt result is not rejected
→ false is passed into the symmetric cipher as a key
→ phpseclib normalizes this into a predictable null key path
→ attacker-controlled encrypted JSON can decrypt successfully
→ command is dispatched
在易受攻击的行为中,RSA 解密可能返回:```text false
Instead of rejecting that failed decrypt result, the vulnerable flow continues and passes the value into the symmetric decryption layer.
The effective vulnerable pattern is:```php
$sym_key = $rsa->decrypt($sym_key);
$rij->setKey($sym_key);
$decrypted = $rij->decrypt($ciphertext);
问题在于 $sym_key 在使用前未经过验证。
当 $sym_key 为 false 时,密码设置会遵循可预测的空密钥/空初始向量行为。这使得可以使用已知的零密钥和零初始向量来构造加密的 RPC 负载。
修补后的版本在对称密钥使用前添加了一个防护检查:```php if (false === $sym_key || !is_string($sym_key) || strlen($sym_key) < 16) { return false; }
这改变了信任边界。
在补丁之前:```text
failed RSA decrypt result could still reach symmetric decrypt
补丁之后:```text failed RSA decrypt result is rejected before command dispatch
这就是为什么存在漏洞的服务会分发伪造的 RPC 命令,而修补后的服务则不会。
## 为什么身份验证绕过可能导致代码执行
CVE-2026-10795 最好被描述为身份验证绕过,因为根本缺陷在于 RPC 身份验证和消息验证层。
然而,在绕过该身份验证边界后,攻击者控制的 RPC 消息可以到达特权级 UpdraftCentral 命令。
其中一个重要的命令路径是:```text
plugin.upload_plugin
该命令是 UpdraftCentral 插件管理功能的一部分。它接收插件 ZIP 负载,将其写入临时位置,安装插件,并根据请求激活插件。
因此影响链为:```text Authentication bypass → forged privileged RPC command → plugin upload through legitimate UpdraftCentral functionality → plugin installation → plugin activation → WordPress plugin code execution
这不是命令注入。
该实验室通过安装一个公开单个端点的标记插件来演示代码执行:```text
/wp-json/cve-lab/v1/id
标记插件不接受命令参数。它只运行:```text /usr/bin/id
这使得证明过程可控,并避免将实验室变成通用型的网页外壳。
## 补丁源码摘要
相关的补丁行为是,修补后的版本在尝试解密RPC消息体之前,会拒绝无效的对称密钥。
重要的验证是:```php
if (false === $sym_key || !is_string($sym_key) || strlen($sym_key) < 16) {
return false;
}
这防止了易受攻击的回退行为,即失败的RSA解密结果可能变成可预测的对称密钥路径。实际结果是:```text UpdraftPlus 1.26.4 → forged format=1 RPC message reaches command dispatch
UpdraftPlus 1.26.5 → failed symmetric key validation stops the forged message → command dispatch is not reached
该实验还通过针对真实的 UpdraftCentral 插件上传命令路径来验证下游影响。
相关命令行为是:```text
plugin.upload_plugin
→ base64 decode ZIP data
→ write temporary ZIP file
→ UpdraftCentral_Plugin_Upgrader->install()
→ activate_plugin()
The patched version blocks the forged message before this command path is reached.
This section explains the vulnerable path at source-code level and maps each PoC step to the relevant UpdraftPlus / UpdraftCentral behavior.
The lab does not rely on a fake vulnerable application route. The vulnerable behavior is reached through the real UpdraftCentral RPC listener and the real UpdraftCentral plugin-management command path.
The important source areas are:```text vendor/team-updraft/common-libs/src/updraft-rpc/class-udrpc2.php central/bootstrap.php central/listener.php central/commands.php central/modules/plugin.php
### 监听器创建
当WordPress接收到包含以下内容的POST请求时,存在漏洞的RPC路径启动:```text
udrpc_message
format
key_name
RPC 库会在存在这些 POST 字段时,在 WordPress 的 wp_loaded 上注册一个监听器。
从概念上讲,流程如下:```php if (!empty($_POST['udrpc_message']) && !empty($_POST['format'])) { add_action('wp_loaded', array($this, 'wp_loaded')); add_action('wp_loaded', array($this, 'wp_loaded_final'), 10000); }
这意味着攻击者无需知道特定的REST端点或管理员URL。伪造的RPC请求会作为普通的POST请求发送到WordPress网站根目录。
PoC发送:```text
POST /
format=1
key_name=0.central.updraftplus.com
udrpc_message=<crafted encrypted message>
请求到达与合法的UpdraftCentral远程通信相同的监听器路径。
UpdraftCentral将本地远程控制键存储在WordPress选项中。在本实验中,设置脚本为易受攻击的靶机和已修补的靶机分别植入了受控的键状态。
相关的键名是:```text 0.central.updraftplus.com
此格式由UpdraftCentral关键指标逻辑生成:```php
private function indicator_name_from_index($index) {
return $index.'.central.updraftplus.com';
}
监听器只有在未加密的 POST 字段与预期的密钥指示符匹配时才会继续执行:```php if (empty($_POST['key_name']) || $_POST['key_name'] != $this->key_name_indicator) { return; }
因此,PoC 设置:```python
KEY_NAME = "0.central.updraftplus.com"
这不是漏洞。这是一个实验室前提条件,允许测试以可重复的方式执行易受攻击的RPC解析和解密路径。
UpdraftCentral 支持消息格式。重要的区别是:```text format=1 legacy path format=2 signed message path
在易受攻击的代码路径中,只有当格式大于或等于2时才进行签名验证。```php
if ($format >= 2) {
if (empty($_POST['signature'])) {
die;
}