A practical breakdown of how unsafe deserialization and internal trust can lead to remote command execution in a real-world SIEM environment.

Modern security systems are built on trust.

But what happens when that trust is misplaced?

In this write-up, I explored a vulnerability in Wazuh that doesn't rely on external access , but instead abuses trusted internal communication between cluster nodes.

What is the Vulnerability?

Wazuh operates in a cluster model:

  • Manager (master server)
  • Worker nodes (agents / distributed systems)

These components communicate internally using authenticated channels.

The issue?

The manager implicitly trusts data coming from already authenticated worker nodes

Where things break

When the manager receives data:

  1. It accepts the request from a trusted worker
  2. It deserializes the data into Python objects
  3. That data is then processed — without strict validation of what it contains

Important distinction

  • Deserialization → converting data into usable Python objects
  • Decryption → decoding encrypted data

These are not the same.

How the attack works

The attack chain looks like this:

  1. Attacker compromises a worker node
  2. Crafts a malicious payload
  3. Sends it via internal cluster communication (DAPI)
  4. Manager deserializes the payload
  5. Malicious code is executed

Why subprocess matters

One part that initially confused me was the use of subprocess.

After digging deeper, I understood:

subprocess allows Python to execute system-level commands

This means:

  • attacker-controlled input
  • gets executed as system commands
  • potentially with high privileges

In simple terms:

If unsafe deserialization meets subprocess execution, it becomes a direct path to remote command execution.

Detection challenges (this is where it gets interesting)

At first glance, logs can be misleading.

Manager perspective

  • requests appear to come from a trusted worker
  • no obvious external attacker IP

You need to look deeper:

On the manager

  • unusual DAPI requests
  • unexpected command execution
  • abnormal process activity

On the worker node

  • connections to unknown external IPs
  • unusual inbound/outbound traffic
  • signs of compromise

Key insight:

The worker node may not be the attacker , but it becomes the attacker's proxy.

Mitigation

Wazuh addressed this by:

restricting what can be deserialized (allowlist approach)

Instead of blindly trusting data:

  • only approved internal objects/functions are allowed
  • arbitrary execution is prevented

What this taught me

This vulnerability isn't just about code.

It's about trust boundaries.

Key takeaways:

  • Internal systems are not automatically safe
  • Trust between components can be abused
  • Deserialization is dangerous when unchecked
  • Behavior matters more than source IP
  • Detection must go beyond surface-level logs

Final thought

This was one of those cases where:

  • everything looks normal
  • until you question why it looks normal

And that's where real analysis begins.