CVE-2025-24016 - How Unsafe Deserialization in Wazuh Leads to Remote Code Execution (RCE)

Wazuh is a widely deployed, open-source platform for threat prevention, detection, and response. It’s used by organizations big and small to monitor endpoints, collect security events, and automate response. However, between versions 4.4. and 4.9.1, a critical vulnerability (CVE-2025-24016) has been found that lets anyone with API access execute arbitrary Python code on a Wazuh server—including in some cases, compromised agents. This post breaks down how the bug works, where the danger is, and what you need to do to protect your infrastructure.

What's the Issue?

The problem lies in how Wazuh's Distributed API (DAPI) handles incoming JSON data. DAPI serializes request and response data as JSON. On the server side, this JSON is deserialized using a helper called as_wazuh_object, found in framework/wazuh/core/cluster/common.py.

In vulnerable versions, there was not enough sanitization during this deserialization. This opened up a scenario where an attacker could craft a malicious dictionary in a DAPI request, which takes advantage of undocumented Python features to cause arbitrary code execution.

Why Does This Matter?

If an attacker is able to inject a malicious payload into a DAPI message, and if the server deserializes it without proper checks, the attacker can fully compromise the server. All they need is some way to send requests to the API—through either a stolen access token, a compromised dashboard, another vulnerable server in the Wazuh cluster, or (in some setups) even a rogue agent.

The Root Cause: as_wazuh_object and Magic Method Abuse

The critical function here is as_wazuh_object. This function reconstructs Python objects from the serialized JSON. Unfortunately, in vulnerable versions, this process allowed for construction of objects that include magic attributes, like __unhandled_exc__. For those familiar with Python, including special attributes like this can cause parts of the interpreter or error handling system to run code you (the defender) did not write or approve.

By crafting a JSON payload that injects a dictionary containing a __unhandled_exc__, an attacker can trick Python into evaluating arbitrary code during exception handling!

Example Exploit Step-by-Step

Let’s look at how an attacker might pull this off.

Suppose you have API access (for example, you’ve compromised a Wazuh dashboard user). The attacker crafts a DAPI message with a payload like:

# Malicious dictionary payload for injection
payload = {
    "__unhandled_exc__": {
        "exception": "__import__('os').system('touch /tmp/wazuh_hacked')"
    }
}

When this gets deserialized by the vulnerable as_wazuh_object function, it will eventually trigger the construction and evaluation of the payload as a Python object—causing the code inside system(...) to run on the server.

Note: The actual JSON sent will look like this

{
  "request": {
    "__unhandled_exc__": {
      "exception": "__import__('os').system('touch /tmp/wazuh_hacked')"
    }
  }
}

Here’s a simplified look at the vulnerable process

import json

# Wrong: deserializing directly and trusting all keys!
def as_wazuh_object(payload):
    # payload is a dict loaded from user-supplied JSON
    obj = SomeBaseClass()
    for key, value in payload.items():
        setattr(obj, key, value)
    return obj

# Attacker injects malicious attribute:
dangerous_dict = {
    "__unhandled_exc__": {
        "exception": "__import__('os').system('id')"
    }
}
# This will eventually get evaluated!

Anyone with Wazuh API or dashboard access.

- Any other server in the cluster (if the attacker controls/compromises one).

In some configurations, by a rogue agent connecting to the manager.

Given Wazuh’s goal—being the security nerve center of your organization—that’s a very dangerous place to have a remote code execution vulnerability.

Is My Server Vulnerable?

Check your Wazuh version. Vulnerable versions are 4.4. up to, but not including, 4.9.1.

or

cat /var/ossec/etc/ossec.conf | grep wazuh_version

If it’s below 4.9.1 and not 4.9.1 or newer, you are at risk.

Patch Now: Upgrade to 4.9.1+

The Wazuh team released version 4.9.1 to fix this issue. If you can, upgrade all your Wazuh servers and clusters immediately. This closes the deserialization hole in DAPI.

Other Defenses

- Restrict API access: Limit dashboard/API traffic with firewall rules, network-level access controls, and host-based protections.
- Audit agent enrollments: Ensure only legitimate, known hosts join your cluster or connect as agents.
- Review logs: Look for strange errors or failed requests in Wazuh logs that might indicate failed exploit attempts.

References

- Wazuh Security Advisory CVE-2025-24016

*(Replace with actual advisory URL once public.)*

- Official Wazuh Releases
- CVE Details Entry for CVE-2025-24016
- Generic background: About Unsafe Deserialization

Summary

CVE-2025-24016 is a critical bug in Wazuh, letting attackers run code as root (or whatever user runs Wazuh) by passing crafted JSON data to the server's Distributed API interface. If you run Wazuh between 4.4. and 4.9.1, patch *now* and confirm your upgrade. Failing to do so can result in a full environment takeover by attackers, undoing all your security monitoring work.

Stay safe, patch quickly, and never trust user-supplied data!

*This write-up was made to provide clear, actionable information for defenders and security operators. If you have any other questions about this vulnerability or upgrading Wazuh safely, post in the comments or see the links above.*

Timeline

Published on: 02/10/2025 20:15:42 UTC