Reports
MEDIA[DENEGACIÓN DE SERVICIO]#3867363

MariaDB: un recuento de campos desorbitado en HandlerSocket tumba el servidor

El plugin HandlerSocket de MariaDB reservaba memoria en la pila según el número de campos que indicaba el cliente antes de validarlo. Un valor enorme provocaba un SIGSEGV y dejaba la base de datos caída.

Resumen
Resumen en castellano de un reporte público, no una traducción literal. El código y los comandos se mantienen como en el original.

Resumen

HandlerSocket es un plugin opcional de MariaDB que abre un puerto propio para leer y escribir en los índices de las tablas como si fuesen un almacén clave-valor, sin pasar por el analizador SQL. Las peticiones exec de ese protocolo llevan un número de sentencia preparada, un operador, un recuento de campos y los valores de esos campos.

El fallo está en el orden de las operaciones. Nada más leer el recuento (fldnum) que envía el cliente, el código reserva memoria en la pila con alloca en función de ese número y empieza a escribir en ella. La comprobación de que el recuento no supera los campos del índice llega después, cuando el daño ya está hecho. El patrón vulnerable, según lo describe el investigador, es este:

fldnum = read_field_count_from_request();
flds = alloca(fldnum * sizeof(string_ref));
for each field:
    flds[i] = string_ref(field_pointer, field_length);

Con un recuento de 1000000000, la reserva en la pila es absurda y el proceso mariadbd recibe un SIGSEGV al escribir el primer registro de campo. El servidor se cae entero.

Condiciones para que afecte:

  • Solo a instalaciones con el plugin HandlerSocket cargado y su puerto de escucha accesible. El puerto SQL normal no está afectado.
  • Si no se han configurado handlersocket_plain_secret ni handlersocket_plain_secret_wr, cualquiera que llegue al puerto puede provocarlo sin autenticarse. Si hay secreto, el atacante tiene que autenticarse antes en HandlerSocket.

El investigador lo reprodujo sobre 13.1.0-MariaDB compilado desde el código oficial (rama preview-13.1-preview, commit 91f37a32f3ee463bdb8287ef951170b5f64201e0) y dejó al fabricante confirmar el rango exacto de versiones afectadas. Lo clasificó como CWE-400 (consumo de recursos sin control) y propuso una puntuación CVSS 3.1 de 7.5:

CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H

En HackerOne el reporte figura con severidad media. Se envió el 16 de julio de 2026 y se hizo público el 7 de octubre de 2026.

Pasos de reproducción

El investigador aportó un directorio poc/ con scripts para montar un objetivo local en Docker a partir del código fuente oficial de MariaDB.

  1. Construir la imagen y arrancar el contenedor con HandlerSocket cargado y su puerto expuesto:
cd poc
chmod +x *.sh docker-entrypoint-hs.sh
./build-local-image.sh
./run-local-target.sh

Para probar otra etiqueta o rama oficial:

cd poc
MARIADB_REF='<official-tag-or-branch>' MARIADB_EXPECTED_COMMIT='' ./build-local-image.sh
./run-local-target.sh
  1. Comprobar que el entorno cumple las condiciones: plugin HandlerSocket cargado, puerto de lectura o escritura de HandlerSocket accesible y la tabla de prueba creada:
CREATE DATABASE hs_verify;
CREATE TABLE hs_verify.t (id INT PRIMARY KEY, v VARCHAR(32));
INSERT INTO hs_verify.t VALUES (1, 'one');
  1. Lanzar la prueba de concepto contra el puerto de HandlerSocket. Abre el índice con una petición open normal y después manda una petición exec con un recuento de campos desmesurado:
cd poc
./run-poc.sh --host 127.0.0.1 --port 9998

Si HandlerSocket tiene secreto configurado, hay que pasarlo:

cd poc
./run-poc.sh --host 127.0.0.1 --port 9998 --secret '<secret>'
  1. Observar el resultado. La apertura responde bien, la petición exec no recibe respuesta y el puerto deja de estar accesible:
open response: 0	1
exec response: <empty>
RESULT: VULNERABLE - listener is no longer reachable after trigger

El contenedor termina con Exited (139) / Segmentation fault. El investigador adjuntó también un vídeo de toda la secuencia.

Impacto

Quien pueda conectar con el puerto de HandlerSocket puede tumbar el proceso mariadbd con una petición manipulada, y con él toda la base de datos, no solo HandlerSocket. Si no hay secreto configurado, no hace falta ninguna credencial. El investigador deja claro que solo ha demostrado la denegación de servicio: no hay pruebas de ejecución de código, fuga ni alteración de datos.

Remediación

El comportamiento esperado, según el reporte, es que HandlerSocket rechace un recuento de campos excesivo antes de reservar memoria y que el servicio de MariaDB siga funcionando.

Qué aprender de este caso

  • Busca alloca (o arrays de tamaño variable en la pila) cuyo tamaño salga de un campo del protocolo: un recuento de elementos, una longitud o un número de columnas. Si ese valor llega del cliente sin tope previo, basta con un número enorme para desbordar la pila.
  • El orden importa: comprobar que fldnum no supera el número de columnas del índice antes de reservar memoria, no después. Una validación correcta pero tardía no sirve de nada si antes ya se ha escrito en el búfer.
  • En protocolos alternativos al principal (como el puerto de HandlerSocket frente al puerto SQL) conviene revisar los controles por separado. Si tienes un plugin así activado, configura un secreto y no expongas su puerto fuera de la red de confianza.
  • Para datos de tamaño controlado por el usuario, mejor memoria del montón con un límite explícito que la pila, donde un fallo de reserva no se puede detectar y acaba en un SIGSEGV.