The Zabbix agent (zabbix_agentd) listens on TCP 10050 and answers item-key requests from whoever can connect, normally the Zabbix server. Where the agent is configured to allow remote commands, it executes system.run[command] directly, so an attacker who can reach the agent runs commands on its host without going through the server or authenticating to the frontend at all. The gate is the agent's configuration: older agents enable this with EnableRemoteCommands=1, and newer agents require an explicit AllowKey=system.run[*] (it is denied by default in current versions). An agent with either setting, especially one exposed beyond the server's address, is direct code execution on that host.
# query the agent directly; if system.run is allowed, it runs the command
zabbix_get -s <agent-host> -p 10050 -k 'system.run[id]'
zabbix_get -s <agent-host> -p 10050 -k 'system.run[cat /etc/passwd]'
# without zabbix_get, the agent protocol is simple enough to speak over a socket
printf 'system.run[id]\n' | nc <agent-host> 10050
# first confirm the agent answers and which keys are permitted
zabbix_get -s <agent-host> -p 10050 -k agent.ping
Exploitation notes#
- No server or login is needed: reaching 10050 and a permissive agent config (
EnableRemoteCommandsorAllowKey=system.run[*]) is sufficient, so a widely-reachable agent is a direct foothold on its host. - Modern agents deny
system.runby default, so this depends on configuration; testsystem.run[id]and fall back to reading non-command keys (agent.ping,system.uname) to confirm reachability and version. - Agents are often only firewalled to the Zabbix server, so this is most useful from the server's vantage (after compromising the server) to pivot to every monitored host, or where agents are exposed more broadly.
- This is the agent-side counterpart to item command execution (which reaches the agent via the server) and complements server-side scripts.