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:
- It accepts the request from a trusted worker
- It deserializes the data into Python objects
- 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:
- Attacker compromises a worker node
- Crafts a malicious payload
- Sends it via internal cluster communication (DAPI)
- Manager deserializes the payload
- 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.