Dead.Letter: Exim에서 인증되지 않은 RCE 해체 (CVE-2026-45185)

CVE-2026-45185의 발견은 널리 사용되는 메일 전송 에이전트(MTA)인 Exim에 심각한 인증되지 않은 원격 코드 실행(RCE) 취약점이 존재함을 밝혀냈습니다. 버그 자체의 기술적 심각성을 넘어, 공개 과정은 숙련된 인간 보안 연구자와 자율적인 LLM 기반 에이전트가 맞붙는, 익스플로잇 개발 환경의 진화를 보여주는 흥미로운 사례 연구가 되었습니다.

취약점: TLS 종료 시 Use-After-Free

CVE-2026-45185는 TLS 연결이 GnuTLS에 의해 처리될 때 발생하는 Use-After-Free(UAF) 취약점으로, 많은 Debian 기반 배포판에서 기본 라이브러리로 사용됩니다. 이 결함은 Exim의 TLS 전송 버퍼와 BDAT(RFC 3030 CHUNKING) 수신 래퍼 간의 상호 작용에 존재합니다.

기술적 트리거

클라이언트가 STARTTLS 세션을 시작하면 Exim은 store_malloc()을 통해 4096바이트 평문 전송 버퍼(xfer_buffer)를 할당합니다. 서버가 BDAT 청크를 사용 중이면 Exim은 모달 연산을 수행하여 BDAT 전용 수신 함수를 스택에 푸시하고, 이후 I/O를 기본 TLS 콜백에 위임합니다.

취약점은 TLS 종료 과정에서 트리거됩니다. tls_refill()이 TLS EOF를 감지하면 tls_close()를 호출하고, 이 함수는 xfer_buffer를 해제합니다. 그러나 tls_close()는 최상위 수신 콜백만 평문 SMTP로 복원하고, BDAT에서 사용되는 lwr_receive_* 행은 정리하지 않습니다.

xfer_buffer 포인터가 해제되었지만 NULL로 설정되지 않기 때문에, 이후 bdat_ungetc() 호출—메시지 파서가 누락된 CRLF 시퀀스를 복구하려 시도하면서 발생할 수 있음—이 해제된 메모리 영역에 단일 바이트(\n 또는 \r)를 기록합니다. 이 1바이트 쓰기만으로도 할당자의 내부 메타데이터가 손상되어 전체 RCE 체인의 기반이 마련됩니다.

Exim의 커스텀 메모리 할당자: "Store" 서브시스템

단일 바이트 쓰기가 RCE로 이어지는 과정을 이해하려면 Exim의 store 서브시스템을 알아야 합니다. Exim은 단순히 malloc에 의존하는 대신, 짧은 수명의 객체를 관리하기 위해 풀 기반 bump allocator를 사용합니다.

  • 풀 구조: 메모리는 POOL_MAIN, POOL_MESSAGE와 같은 풀로 조직됩니다. 각 풀은 storeblock 구조체들의 연결 리스트입니다.
  • Storeblock 헤더: 각 블록은 next 포인터와 length 필드를 포함하는 16바이트 헤더로 시작합니다.
  • 리셋 메커니즘: internal_store_reset이 호출되면 Exim은 풀을 특정 마크로 되감습니다. storeblocklength 필드가 손상되면(예: UAF 쓰기로) 할당자는 실제보다 더 많은 자유 공간이 있다고 판단해 이후 store_get() 호출이 인접 메모리를 덮어쓰게 됩니다.

레이스: 인간 vs. 자율 LLM

보고서 발표 후, 연구진은 LLM이 인간 전문가(LLM을 보조 도구로 활용)보다 자율적으로 익스플로잇을 개발할 수 있는지를 확인하기 위해 7일간 실험을 진행했습니다.

라운드 1: ASLR 없음, PIE 없음

자율 에이전트(XBOW Native)가 첫 라운드에서 승리했습니다. 표준 "CTF 스타일" 체인을 활용했는데:

  1. Largebin 손상: glibc largebin 포인터를 손상시켜 향후 malloc(4096) 호출이 공격자가 제어하는 주소로 리다이렉트되도록 함.
  2. FILE 구조체 오버라이트: 손상된 stdio 버퍼를 통해 FILE 구조체의 vtable을 덮어씀.
  3. FSOP 피벗: File Stream Oriented Programming(FSOP) 가젯을 사용해 ROP 체인으로 피벗하고, 최종적으로 /flag 파일을 읽어 SMTP 소켓을 통해 전송.

라운드 2: ASLR 활성, PIE 없음

XBOW Native는 다시 성공했으며, 목표를 glibc 내부에서 Exim 자체 할당자로 전환했습니다. Exim storeblock의 길이를 부풀려 풀을 프로그래머블 bump-pointer로 만들었습니다. 약 200개의 정밀하게 크기가 조정된 SMTP 명령을 전송해 acl_smtp_predata.bss 슬롯에 페이로드를 심었고, Exim의 ${run} 확장을 통해 임의 쉘 명령을 실행하도록 트리거했습니다.

라운드 3: 전체 프로덕션 빌드

최종 단계에서 인간 연구자는 exim_sha_init에서 새로운 메모리 소모 누수를 발견해 돌파구를 마련했습니다. gnutls_hash_init을 활용하면 Exim이 절대 해제하지 않는 메모리를 할당하게 되며, 이를 이용해 힙을 "그루밍"해 기존 구멍을 채워 결정적인 메모리 상태를 만들었습니다.

이 그루밍을 통해 연구자는 와이어 상에서 스택 포인터 누수를 얻었으며, 이는 전체 ASLR/PIE를 우회하기 위한 중요한 첫 단계였습니다. 자율 LLM은 프로덕션 빌드에 대해 누수를 만들어내지 못했지만, 인간 연구자는 LLM이 과정을 가속화할 수는 있지만, "어려운 부분"—디버깅, 회의적 사고, 정밀 힙 그루밍—은 여전히 인간 직관이 필요함을 보여주었습니다.

결론: 취약점 연구를 위한 "터보 버튼"

CVE-2026-45185는 복잡한 레거시 코드베이스 내 메모리 관리의 중대한 실패를 강조합니다. 더 나아가, 이번 실험은 LLM이 취약점 연구 초기 단계—낯선 코드 이해, 가설 생성, 의심스러운 경로 식별—에 있어 실질적인 "터보 버튼" 역할을 할 수 있음을 시사합니다.

하지만 버그를 신뢰할 수 있는 프로덕션 익스플로잇으로 전환하는 과정은 여전히 높은 장벽을 가지고 있습니다. 연구자가 지적했듯이, "CTF 형태" 문제를 해결하는 능력이 실제 프로덕션 타깃을 자율적으로 해체하는 능력과 동일하지는 않습니다. 환경이 모델의 학습 데이터와 맞지 않을 때 전략을 전환하는 인간 요소가 결정적인 요인으로 남아 있습니다.

Sources