flawopen.com/SSRF/SSRF avec fetch() dans Node.js
fetch() de Node.js empêche-t-il les SSRF ?
Non. fetch() côté serveur envoie une requête depuis le serveur. Si l’appelant choisit la destination, il peut viser des systèmes accessibles au serveur mais pas à lui-même. C’est comme demander à un coursier de confiance de livrer un colis sans vérifier l’adresse. Le risque dépend du réseau, de l’identité, de la politique URL et des redirections.
providerId, et une origine configurée par l’application. Elle évite les URL arbitraires.Cause : le serveur fait confiance à la destination fournie
Le fetch() de Node.js est un client HTTP général, pas une politique anti-SSRF. Il ne choisit pas les réseaux accessibles ; CORS du navigateur n’établit pas de frontière côté serveur. Analyser l’URL ne suffit pas : un hôte autorisé peut résoudre vers une adresse interdite, et une réponse peut rediriger vers un autre hôte. Les fonctions qui récupèrent avatar, webhook, document ou aperçu fourni par l’utilisateur peuvent exposer le serveur.
Comment la requête franchit la frontière de confiance
L’appelant influence une URL
Un endpoint accepte une URL entière ou assez de données pour la construire, par exemple pour prévisualiser une image.
Le serveur envoie la requête
Le client HTTP utilise la route réseau, le DNS, le proxy et l’identité disponibles au processus serveur.
Une redirection change la destination
Fetch suit les redirections par défaut. Une destination validée initialement peut répondre par un Location vers un hôte interdit.
La réponse expose des données accessibles
Si réseau et politique l’autorisent, des services internes ou métadonnées cloud peuvent être atteints. Cela dépend de l’environnement, pas de chaque appel fetch.
Exemples Node.js vulnérable et plus sûr
// Ne récupérez pas une URL arbitraire fournie par l’appelant.
const response = await fetch(userProvidedUrl);
// L’appelant choisit une clé, jamais une destination réseau.
const destinations = new Map([
["status", new URL("https://status.example/")],
["docs", new URL("https://docs.example/")],
]);
const target = destinations.get(providerId);
if (!target) throw new Error("Unknown provider");
const response = await fetch(target, {
redirect: "error",
signal: AbortSignal.timeout(3000),
});
if (!response.ok) throw new Error("Upstream request failed");
Si l’utilisateur doit fournir une URL
Préférez un identifiant fournisseur associé à une destination fixe. Si des URL publiques arbitraires sont indispensables, n’autorisez que les schémas et ports requis ; rejetez user-info, loopback, adresses privées, link-local et autres destinations IPv4/IPv6 interdites ; validez toutes les adresses résolues et forcez la connexion à utiliser une adresse validée sans seconde résolution non contrôlée. Désactivez les redirections automatiques ou validez chaque étape. Appliquez des règles de sortie réseau indépendantes, y compris le blocage des métadonnées telles que 169.254.169.254 et l’adresse IPv6 activée. Limitez durée, taille de réponse et concurrence ; ne transmettez pas d’identifiants internes à la destination.
Liste de prévention SSRF
- ✓Remplacez si possible toute URL libre par une association fixe entre une clé fournisseur validée et une destination définie par l’application.
- ✓Imposez
https:et les ports attendus ; rejetez identifiants d’URL, hôtes inattendus, IP littérales et plages interdites. - ✓Désactivez les redirections avec
redirect: "error"; si elles sont nécessaires, validez chaque destination avant connexion. - ✓Prévenez le DNS rebinding en validant toutes les réponses A/AAAA et en liant la connexion à une adresse validée tout en conservant la vérification du nom. Couvrez aussi reprises et proxies.
- ✓Utilisez un pare-feu ou proxy de sortie qui bloque loopback, réseaux privés, link-local et métadonnées, IPv6 compris. Les contrôles applicatifs seuls ne suffisent pas.
- ✓Fixez limites de durée, d’octets et de concurrence ; ne transmettez ni cookies, ni en-têtes d’autorisation, ni identifiants cloud.
- ✓Sur AWS, imposez IMDSv2 et restreignez l’accès aux métadonnées en défense supplémentaire ; cela ne remplace ni validation d’URL ni filtrage réseau.
Questions fréquentes
Non. Redirections, variantes IPv4/IPv6, DNS rebinding, proxies et courses entre résolution et connexion contournent les vérifications simples. Préférez une liste autorisée. Si les destinations sont libres, validez chaque adresse et forcez la connexion à utiliser ce résultat ; appliquez la même politique au réseau.
Non. IMDSv2 exige un jeton et réduit certaines expositions, mais une SSRF peut viser d’autres services internes ou métadonnées selon la configuration. Gardez les contrôles de destination et de sortie.
Sources primaires
- OWASP — prévention SSRF
- Node.js — API globale fetch
- Standard WHATWG Fetch — mode de redirection
- AWS — options du service de métadonnées EC2
- CWE-918 — Server-Side Request Forgery