Skip to content

Description

Les failles de falsification de requête côté serveur (SSRF) se produisent lorsqu'une application web permet à un attaquant de forcer le serveur à effectuer des requêtes HTTP vers des destinations arbitraires. Cela permet à un attaquant d'accéder à des ressources internes, d'interagir avec des services non exposés publiquement, et potentiellement de compromettre l'infrastructure interne.


Exemple d'Attaque SSRF

Scénario d'attaque :

  • Une application web propose une fonctionnalité de prévisualisation d'URL ou de téléchargement de contenu distant, par exemple un service qui récupère des images depuis une URL fournie par l'utilisateur.

Exemple de code vulnérable :

python
from flask import Flask, request
import requests

app = Flask(__name__)

@app.route('/fetch', methods=['POST'])
def fetch_url():
    url = request.form['url']
    response = requests.get(url)
    return response.content

Exploitation :

  • Un attaquant peut manipuler l'URL pour accéder à des ressources internes, par exemple en entrant http://127.0.0.1:22 pour scanner les ports locaux.
http
POST /fetch HTTP/1.1
Host: example.com
Content-Type: application/x-www-form-urlencoded

url=http://127.0.0.1:6379/
  • Le serveur effectuerait alors une requête vers Redis sur localhost, révélant potentiellement des informations sensibles.

Prévention des Attaques SSRF

Validation et Filtrage des URLs :

  • Valider les URLs fournies par l'utilisateur et bloquer l'accès aux plages d'adresses privées et localhost.
python
import ipaddress
from urllib.parse import urlparse

def is_safe_url(url):
    try:
        parsed = urlparse(url)
        if parsed.scheme not in ['http', 'https']:
            return False
        
        ip = ipaddress.ip_address(parsed.hostname)
        if ip.is_private or ip.is_loopback or ip.is_link_local:
            return False
        
        return True
    except:
        return False

@app.route('/fetch', methods=['POST'])
def fetch_url():
    url = request.form['url']
    if not is_safe_url(url):
        return "Invalid URL!"
    
    response = requests.get(url)
    return response.content

Liste blanche de domaines autorisés :

  • Maintenir une liste de domaines autorisés et ne permettre l'accès qu'à ces domaines.
python
ALLOWED_DOMAINS = ['api.example.com', 'images.trusted-site.com']

@app.route('/fetch', methods=['POST'])
def fetch_url():
    url = request.form['url']
    parsed = urlparse(url)
    
    if parsed.hostname not in ALLOWED_DOMAINS:
        return "Domain not allowed!"
    
    response = requests.get(url)
    return response.content

Utilisation de proxies et isolation réseau :

  • Configurer des proxies dédiés ou utiliser des conteneurs isolés pour les requêtes externes.
python
@app.route('/fetch', methods=['POST'])
def fetch_url():
    url = request.form['url']
    proxies = {
        'http': 'http://proxy-server:8080',
        'https': 'https://proxy-server:8080'
    }
    
    response = requests.get(url, proxies=proxies, timeout=5)
    return response.content

Détection des Failles SSRF

Revue de Code :

  • Examiner le code source pour identifier les endroits où l'application effectue des requêtes HTTP basées sur des entrées utilisateur.

Tests Manuels :

  • Effectuer des tests manuels en manipulant les paramètres d'URL pour tenter d'accéder à des ressources internes.

Utilisation d'Outils de Sécurité :

  • Utiliser des outils de sécurité tels que Burp Suite, OWASP ZAP, ou des scanners spécifiques pour détecter les failles SSRF.

Exemples de Prévention

Validation robuste avec DNS resolution :

python
import socket
import ipaddress

def resolve_and_validate(hostname):
    try:
        ip = socket.gethostbyname(hostname)
        ip_obj = ipaddress.ip_address(ip)
        
        if ip_obj.is_private or ip_obj.is_loopback:
            return False
        return True
    except:
        return False

@app.route('/fetch', methods=['POST'])
def fetch_url():
    url = request.form['url']
    parsed = urlparse(url)
    
    if not resolve_and_validate(parsed.hostname):
        return "Invalid destination!"
    
    response = requests.get(url, timeout=10)
    return response.content

Configuration de timeouts et limitations :

python
@app.route('/fetch', methods=['POST'])
def fetch_url():
    url = request.form['url']
    
    try:
        response = requests.get(
            url, 
            timeout=5,
            allow_redirects=False,
            headers={'User-Agent': 'SafeBot/1.0'}
        )
        return response.content
    except requests.exceptions.RequestException:
        return "Request failed!"

Utilisation de bibliothèques sécurisées :

python
from requests_toolbelt import sessions

def create_safe_session():
    session = sessions.BaseUrlSession()
    session.mount('file://', None)  # Block file:// URLs
    session.mount('ftp://', None)   # Block FTP
    return session

@app.route('/fetch', methods=['POST'])
def fetch_url():
    url = request.form['url']
    session = create_safe_session()
    response = session.get(url)
    return response.content

CatégorieInformation
TTPForcer le serveur à effectuer des requêtes vers des destinations arbitraires pour accéder à des ressources internes
CWECWE-918 (Server-Side Request Forgery (SSRF))
Description de l'attaqueSSRF se produit lorsqu'une application web effectue des requêtes HTTP vers des URLs contrôlées par l'attaquant, permettant l'accès à des ressources internes, la reconnaissance de réseau, et potentiellement l'exécution d'actions non autorisées sur des services internes.
Impacts potentiels- Accès aux métadonnées cloud (AWS, Azure, GCP)
- Scan de ports internes et reconnaissance réseau
- Accès à des services internes non exposés
- Exfiltration de données depuis des APIs internes
- Contournement de pare-feu et restrictions réseau
Comment la détecter- Analyse de code pour les requêtes HTTP basées sur des entrées utilisateur
- Tests de pénétration avec des URLs internes et de métadonnées
- Monitoring des requêtes sortantes anormales
- Utilisation d'outils de scan spécialisés (SSRFmap, etc.)
Remédiations/mitigations- Valider et filtrer toutes les URLs d'entrée
- Utiliser des listes blanches de domaines autorisés
- Bloquer l'accès aux plages d'adresses privées et localhost
- Implémenter des timeouts et limitations de requêtes
- Utiliser des proxies dédiés pour les requêtes externes
- Isolation réseau des services sensibles
Lien de référenceOWASP - Server-Side Request Forgery (SSRF)