Server-side request forgery (SSRF)¶
La falsification de requête côté serveur (Server-Side Request Forgery) est une vulnérabilité qui permet à un attaquant d'amener l'application serveur à émettre des requêtes vers une destination qu'elle n'aurait pas dû contacter. Au lieu d'attaquer directement, on détourne le serveur lui-même pour qu'il agisse comme relais : c'est lui qui effectue la requête, avec ses propres droits et depuis sa propre position réseau.
C'est précisément ce qui rend la SSRF intéressante. Le serveur se trouve souvent dans une zone de confiance à laquelle l'attaquant n'a pas accès directement : il peut joindre des services internes, des interfaces d'administration restreintes à localhost, ou des composants d'infrastructure protégés par le pare-feu périmétrique. En faisant porter la requête par le serveur, on hérite de cette position privilégiée.
Principe de fonctionnement¶
Une SSRF apparaît dès qu'une application récupère une ressource distante à partir d'une URL que l'utilisateur peut influencer. Le cas typique est une fonctionnalité qui prend une URL en paramètre — vérification de disponibilité d'un stock auprès d'un service tiers, génération d'aperçu de lien, import depuis une URL, webhook. Si la valeur n'est pas correctement validée, on remplace la cible légitime par une cible de notre choix.
Considérons une requête qui interroge un service interne de stock :
POST /product/stock HTTP/1.1
Host: vulnerable-shop.example
Content-Type: application/x-www-form-urlencoded
stockApi=http://stock.internal.example:8080/product?id=42
En modifiant la valeur de stockApi, on demande au serveur d'aller chercher une tout autre ressource. Pointer vers http://localhost/admin revient à demander au serveur d'accéder à sa propre interface d'administration — et comme la requête provient de la machine elle-même, les contrôles qui restreignent cette interface aux accès locaux sont satisfaits :
À partir de là, on peut non seulement consulter ces pages internes mais aussi y déclencher des actions, en reconstruisant les requêtes correspondantes (par exemple une suppression d'utilisateur via l'URL d'administration adéquate).
Cibler les services internes¶
La première chose à tester est l'accès aux ressources locales du serveur et à son réseau interne. Les adresses qui désignent la machine elle-même ou son voisinage immédiat sont les cibles naturelles :
http://localhost/ethttp://127.0.0.1/pour la boucle locale ;- les plages privées (
http://192.168.0.0/16,http://10.0.0.0/8,http://172.16.0.0/12) pour les autres machines du réseau interne ; - les métadonnées d'instance dans un environnement cloud, souvent exposées sur une adresse de lien-local, qui peuvent révéler des informations sensibles de configuration.
Quand on ne connaît pas l'adressage interne, on peut balayer les plages privées et observer les différences de réponse (temps de réponse, code de statut, taille) pour cartographier les hôtes et les ports actifs.
Contourner les filtres en liste noire¶
Beaucoup d'applications tentent de bloquer la SSRF en interdisant certaines valeurs — typiquement localhost et 127.0.0.1. Ces filtres par liste noire sont fragiles, car une même adresse admet de nombreuses représentations équivalentes.
Pour désigner la boucle locale sans écrire 127.0.0.1, plusieurs écritures fonctionnent selon le parseur :
- la forme décimale
http://2130706433/; - la forme octale
http://017700000001/; - une notation abrégée comme
http://127.1/; - d'autres noms qui résolvent vers la boucle locale.
Lorsque le filtre cible un mot-clé sensible dans le chemin (par exemple admin), on peut jouer sur l'encodage. Encoder le mot une ou plusieurs fois (%61dmin, voire un double encodage %2561dmin) suffit parfois à passer le filtre, si le composant qui valide l'URL et celui qui l'utilise ne décodent pas l'entrée de la même manière. Cette différence de traitement entre deux étapes est le ressort de la plupart des contournements.
Outillage
Sous Burp Suite, l'extension Hackvertor facilite ces manipulations : on sélectionne la portion à transformer et on applique un encodage d'URL complet, en l'enchaînant plusieurs fois si nécessaire. Penser à appliquer la transformation après avoir balisé la portion concernée, sinon l'encodage porte sur l'ensemble.
Contourner les filtres en liste blanche¶
Certaines applications n'autorisent que les URL correspondant à un domaine de confiance. C'est plus robuste qu'une liste noire, mais l'analyse syntaxique des URL est suffisamment complexe pour offrir plusieurs angles d'attaque. L'idée générale est de construire une URL que le filtre lit comme légitime, mais que le client HTTP du serveur interprète différemment.
On peut placer le domaine attendu dans la partie « informations d'authentification » de l'URL, avant un @. Le filtre voit le domaine de confiance ; le serveur, lui, contacte l'hôte situé après le @ :
On peut utiliser le caractère # pour transformer le domaine attendu en simple fragment, ignoré lors de la connexion :
On peut aussi exploiter la hiérarchie DNS pour faire du domaine attendu un sous-domaine d'un domaine que l'on contrôle :
Enfin, l'encodage d'URL — simple ou double — des caractères structurants permet de désynchroniser l'interprétation entre l'étape de validation et l'étape de requête. Ces techniques se combinent volontiers : rien n'empêche de mêler un @, un fragment et un encodage dans la même charge utile pour franchir un filtre récalcitrant.
Contournement via redirection ouverte¶
Quand l'URL elle-même est trop bien verrouillée pour être manipulée directement, on peut faire porter le détournement par une autre fonctionnalité : une redirection ouverte. Le principe consiste à fournir au serveur une URL parfaitement légitime — donc acceptée par le filtre — mais qui, une fois suivie, redirige vers la cible interne.
Concrètement, on cherche dans l'application une requête qui accepte un paramètre de redirection (souvent un path= ou équivalent, derrière un bouton, une icône ou un lien). On fournit alors comme URL de la fonctionnalité vulnérable une adresse autorisée pointant vers cette redirection, et on règle le paramètre de redirection sur la cible voulue :
Le serveur valide l'URL externe (le domaine est de confiance), la requête part, la redirection s'opère, et le serveur suit cette redirection jusqu'à la ressource interne. Le filtre n'a vu que le domaine légitime.
SSRF aveugle¶
On parle de SSRF aveugle (blind SSRF) lorsque le serveur effectue bien la requête mais que sa réponse n'est jamais renvoyée dans la page. Le code s'exécute côté serveur sans qu'aucun retour ne le confirme : on ne dispose d'aucune indication directe que l'attaque a fonctionné.
La détection passe alors par des techniques hors-bande (OAST, Out-of-band Application Security Testing). L'idée est de provoquer une interaction réseau du serveur vers un système que l'on contrôle, puis de surveiller cette interaction. Si une requête arrive bien sur notre système, c'est la preuve que le serveur a traité notre URL — donc qu'il est vulnérable.
L'approche la plus pratique repose sur Burp Collaborator : on génère un nom de domaine unique, on l'injecte dans le paramètre testé, et on surveille les interactions reçues. Une requête HTTP entrante en provenance de l'application confirme la SSRF.
Résolution DNS sans requête HTTP
On peut tester avec son propre domaine en vérifiant si une requête de résolution DNS parvient, ce qui est souvent le cas même quand la connexion HTTP qui suit échoue. Si la résolution DNS passe mais que la requête HTTP n'aboutit pas, cela traduit en général un filtrage réseau des requêtes HTTP sortantes — pas une absence d'exécution. Autrement dit, l'interaction DNS suffit à prouver que la charge utile a bien été traitée par le serveur.
Selon le point d'injection, l'URL pointant vers notre système hors-bande peut aussi être placée ailleurs que dans le paramètre évident — par exemple dans l'en-tête Referer d'une requête, que certains composants suivent automatiquement.
Aide-mémoire¶
| Objectif | Piste |
|---|---|
| Atteindre la machine elle-même | localhost, 127.0.0.1 et leurs variantes (décimale, octale, abrégée) |
| Atteindre le réseau interne | Plages privées 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 |
| Contourner une liste noire | Représentations alternatives de l'adresse, encodage simple ou multiple du mot-clé |
| Contourner une liste blanche | @ avant l'hôte cible, fragment #, sous-domaine contrôlé, encodage d'URL |
| Quand l'URL est verrouillée | Redirection ouverte via un paramètre path= légitime |
| Aucune réponse visible | Techniques hors-bande (Burp Collaborator), interaction DNS comme preuve |
Pour une liste exhaustive des contournements de validation d'URL, l'aide-mémoire de référence de PortSwigger est une ressource utile à garder sous la main.