
nuclei-templates용 POC_CVE-2026-45185
이 저장소는 일반적인 익스플로잇 PoC 저장소가 아닙니다. CVE-2026-45185에 대한
projectdiscovery/nuclei-templates에 기여하기 위한 템플릿의 동작을 재현하고 검토하는
로컬 검증 실험실입니다.
The nuclei code template is not a version-only detector.
It directly controls STARTTLS, BDAT, TLS close_notify, and a following
SMTP plaintext byte on the same TCP connection.
This sequence matches in the local vulnerable Exim 4.99.2 GnuTLS lab and does
not match in the patched Exim 4.99.3 GnuTLS lab under the same conditions.
현재 검증 신호는 원격 SMTP 응답 오라클이며, UAF 쓰기 자체를 직접 관찰하는 것이 아닙니다.
내부적으로 이 CVE는 use-after-free로, TLS 종료 후 줄바꿈 바이트(\r/\n)가 해제된 GnuTLS 전송 버퍼에
기록될 수 있습니다. 실제로 클라이언트가 SMTP 응답을 통해 해제된 버퍼 쓰기를 직접 관찰하는 것은
현실적이지 않습니다. 따라서 이 README와 템플릿은 bdat_ungetc -> tls_ungetc UAF 쓰기 또는 RCE를
직접 증명한다고 주장하지 않습니다. 대신 템플릿은 트리거 흐름 중에 나타나는 수신 스택/상태 복구 차이를
감지합니다.
취약점 메커니즘을 추적하는 동안, STARTTLS + BDAT 처리 중 TLS close_notify 후에
BDAT 수신 스택의 하위 계층에 오래된 tls_* 함수 포인터가 남아 함수 포인터로
올바르게 복원되지 않는 현상을 관찰했습니다. 이 상태는 서버가 다음 SMTP 명령을 처리하는 방식에서
드러납니다. 분할된 BDAT가 첫 번째 완료에 도달한 후 동일 세션에서 을 보내면,
취약한 Exim 4.99.2 GnuTLS 실험실은 을 반환하는 반면,
패치된 Exim 4.99.3 GnuTLS 실험실은 로 정상 처리합니다. 이 명확한 취약/패치 응답 차이가
로컬 승인된 nuclei 코드 템플릿의 매처로 사용됩니다.
smtp_*NOOP421 lost input connection250 OK더 깊은 취약점 흐름 분석은 CVE-2026-45185-Technical-Analysis.md를 참조하십시오.
| 대상 | 버전 | TLS 백엔드 | STARTTLS | CHUNKING | 포트 | 예상 nuclei 결과 |
|---|---|---|---|---|---|---|
| 취약 | Exim 4.99.2 | GnuTLS | 예 | 예 | 127.0.0.1:2525 | 일치 |
| 패치 | Exim 4.99.3 | GnuTLS | 예 | 예 | 127.0.0.1:2526 | 불일치 |
공통 SMTP 봉투 수신자 (RCPT TO):
Docker 실험실의 lab_rcpt ACL은 이 봉투 수신자를 허용합니다. 일반 SMTP 대상에서
RCPT TO가 거부되면 시퀀스가 BDAT 본문 파서에 도달하지 못할 수 있으므로 템플릿에 허용된
수신자가 필요합니다.
이 값은 BDAT 본문 내부의 To: 헤더와 다릅니다. RCPT TO 수신자는 서버의 수신자 검사를
통과해야 하는 SMTP 봉투 주소입니다. BDAT 본문의 To: 값은 메시지 헤더 텍스트일 뿐이며,
서버에 사서함으로 존재하거나 허용될 필요가 없습니다.
templates/CVE-2026-45185.yaml
템플릿 이름:
Exim 4.97-4.99.2 GnuTLS STARTTLS BDAT - Same-Session Response Check
템플릿은 metadata.verified: true로 작성되었으며 code 및 intrusive 태그가 있습니다.
POC_2026_45185/ 디렉토리에서 다음 명령을 실행하십시오.
docker compose build
docker compose up -d
템플릿 구문 검증:
nuclei -duc -validate -code -t templates/CVE-2026-45185.yaml
실행 전 로컬 코드 템플릿 서명:
nuclei -duc -code -t templates/CVE-2026-45185.yaml -sign
취약한 실험실에 대해 실행:
nuclei -code \
-t templates/CVE-2026-45185.yaml \
-u 127.0.0.1:2525 \
-var [email protected] \
-debug
예상 결과:
CVE-2026-45185: vulnerable response oracle matched
패치된 실험실에 대해 실행:
nuclei -code \
-t templates/CVE-2026-45185.yaml \
-u 127.0.0.1:2526 \
-var [email protected] \
-debug
예상 결과:
no match
NO-MATCH: patched-like response: NOOP succeeded after split trigger
nuclei code 프로토콜은 기본적으로 실행되지 않으므로 -code가 필요합니다.
또한 nuclei는 서명되지 않은 code 템플릿을 차단합니다. 로컬 nuclei 개인 키가 암호로 보호된 경우
대화형 터미널에서 서명 명령을 실행하고 해당 암호를 입력하십시오. 다이제스트가 템플릿 내용을
포함하므로 템플릿을 변경할 때마다 다시 서명하십시오.
다음 스크린샷은 템플릿이 서명된 후 로컬 실험실 응답 오라클 결과를 보여줍니다. 이는 위에서 설명한 동일 세션 응답 차이에 대한 검증 증거이며, 내부 UAF 쓰기의 직접적인 디버거나 ASAN 증명이 아닙니다.
취약한 Exim 4.99.2 GnuTLS 실험실 (127.0.0.1:2525):

패치된 Exim 4.99.3 GnuTLS 실험실 (127.0.0.1:2526):

이 CVE의 핵심은 SMTP 배너나 버전 확인이 아닙니다. 템플릿은 동일한 TCP 연결에서 다음과 같은 전송 상태 전환을 생성해야 합니다:
평문 SMTP EHLO
-> STARTTLS
-> 동일 TCP 연결에서 TLS 핸드셰이크
-> TLS EHLO / MAIL FROM / RCPT TO / BDAT 70 LAST
-> BDAT 본문의 처음 69바이트를 TLS 애플리케이션 데이터로
-> TCP 소켓을 닫지 않고 TLS close_notify
-> 동일 TCP 연결에서 평문으로 마지막 본문 바이트
-> 동일 세션 평문 NOOP 응답 확인
YAML 템플릿 내부의 Python 코드는 다음 모든 조건이 통과된 후에만 고정 마커를 출력합니다. nuclei 매처는 해당 마커만 일치시킵니다.
Exim 식별 발견됨
AND 평문 EHLO에서 STARTTLS 광고됨
AND 평문 EHLO에서 CHUNKING 광고됨
AND STARTTLS가 수락됨
AND TLS EHLO에서 CHUNKING 광고됨
AND MAIL FROM이 수락됨
AND RCPT TO가 수락됨
AND 분할 close_notify BDAT가 첫 번째 완료에 도달함
AND 첫 번째 완료에 "250 OK id=" 포함
AND 동일 세션 평문 NOOP 응답에 "421" 포함
AND 동일 세션 평문 NOOP 응답에 "lost input connection" 포함
템플릿은 다음 신호 중 하나만으로는 일치하지 않습니다:
버전만
타임아웃만
연결 끊김만
빈 응답만
수신자 거부
STARTTLS/CHUNKING 광고만
두 실험실 모두 분할 BDAT 메시지를 첫 번째 완료까지 처리합니다.
250- 70 byte chunk, total 72
250 OK id=...
차이는 동일한 SMTP 세션에서 다음 SMTP 평문 명령이 전송될 때 나타납니다.
취약한 4.99.2:
NOOP -> 421 exim-lab.local lost input connection
QUIT -> 421 exim-lab.local lost input connection
RSET -> 421 exim-lab.local lost input connection
패치된 4.99.3:
NOOP -> 250 OK
QUIT -> 221 exim-lab.local closing connection
RSET -> 250 Reset OK
해석:
관찰:
두 실험실 모두 분할 BDAT 메시지 완료에 도달합니다.
취약한 실험실만 동일 세션에서 다음 평문 SMTP 명령 루프로 깔끔하게 복귀하지 못합니다.
증거:
취약한 후속 응답은 421 lost input connection입니다.
패치된 후속 응답은 250 OK 또는 221 closing connection입니다.
추론:
이 차이는 STARTTLS close_notify 후 수신 스택/상태 복구 차이와 일치합니다.
템플릿은 BDAT 본문으로 다음 70바이트 메시지를 사용합니다.
From: [email protected]\r\n
To: [email protected]\r\n
Subject: poc\r\n
\r\n
body
SMTP 봉투 수신자는 템플릿 변수 recipient를 통해 별도로 전달됩니다.
본문의 To: 헤더는 텍스트이며 SMTP RCPT TO가 수락되는지 여부와 무관하므로
서버에 존재하거나 수락될 필요가 없습니다.
분할 형태:
BDAT 70 LAST
TLS 본문: 처음 69바이트, "bod"로 끝남
TLS 이벤트: close_notify
평문: 마지막 바이트 "y"
후속: NOOP
두 실험실 모두 Exim, STARTTLS 및 CHUNKING을 광고하는지 수동으로 확인할 수 있습니다.
printf 'EHLO lab-client.local\r\nQUIT\r\n' | nc -w 3 127.0.0.1 2525
printf 'EHLO lab-client.local\r\nQUIT\r\n' | nc -w 3 127.0.0.1 2526
예상 신호:
Exim
STARTTLS
CHUNKING
정상적인 STARTTLS 경로도 확인할 수 있습니다:
openssl s_client -starttls smtp -connect 127.0.0.1:2525 -crlf
openssl s_client -starttls smtp -connect 127.0.0.1:2526 -crlf
debugging/ 및
notes/source-walkthrough-progress.md에서 별도로 추적됩니다.POC_2026_45185/
compose.yaml
images/ 로컬 nuclei 검증 스크린샷
vulnerable/ Exim 4.99.2 + GnuTLS 디버그 빌드
patched/ Exim 4.99.3 + GnuTLS 디버그 빌드
nuclei-templates/ 서브모듈: 로컬 nuclei 템플릿 작업 공간