Comment récupérer une URL ou un webhook fourni par l'utilisateur sans SSRF ?
l'équipe heygrc
Validez la cible avant de la récupérer : exigez https, résolvez l'hôte et rejetez les adresses privées, internes et locales (y compris les points de terminaison des métadonnées cloud). Privilégiez une liste autorisée lorsque les destinations sont connues, et ne suivez pas les redirections aveuglément. La falsification de requête côté serveur est un problème de validation des entrées (NIST 800-53 SI-10), et la vérification doit être effectuée dans le code qui émet la requête.
Valider la cible
N'autorisez que les schémas que vous prévoyez (généralement https) et rejetez les adresses dans les plages privées, de boucle locale, locales et de métadonnées. Validez l'adresse résolue au moment de la connexion, et pas seulement l'URL au préalable, car le DNS peut résoudre différemment entre une vérification préalable et la requête réelle (rebind DNS).
Privilégier une liste autorisée
Si l'ensemble des destinations est connu (une liste fixe de points de terminaison partenaires), autorisez-les via une liste blanche plutôt que d'accepter des URL arbitraires. Plus l'entrée que vous acceptez est restreinte, moins il y a de risques d'erreur.
Ne pas suivre les redirections aveuglément
Une redirection peut envoyer une URL publique validée vers une adresse interne à l'étape suivante. Révalidez à chaque redirection, ou désactivez le suivi des redirections pour les cibles fournies par l'utilisateur.
async function send(url, payload) {- return fetch(url, { method: 'POST', body: payload })+ // safeFetch valide l'adresse RÉSOLUE au moment de la connexion+ return safeFetch(url, { method: 'POST', body: payload, allowRedirects: false })}Valider l'adresse résolue au moment de la connexion, et pas seulement l'URL au préalable (qu'un rebind DNS peut contourner), empêche une cible manipulée d'atteindre des services internes.