### 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égorie | Information |
| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **TTP** | Forcer le serveur à effectuer des requêtes vers des destinations arbitraires pour accéder à des ressources internes |
| **CWE** | CWE-918 (Server-Side Request Forgery (SSRF)) |
| **Description de l'attaque** | SSRF 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)<br>- Scan de ports internes et reconnaissance réseau<br>- Accès à des services internes non exposés<br>- Exfiltration de données depuis des APIs internes<br>- 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<br>- Tests de pénétration avec des URLs internes et de métadonnées<br>- Monitoring des requêtes sortantes anormales<br>- Utilisation d'outils de scan spécialisés (SSRFmap, etc.) |
| **Remédiations/mitigations** | - Valider et filtrer toutes les URLs d'entrée<br>- Utiliser des listes blanches de domaines autorisés<br>- Bloquer l'accès aux plages d'adresses privées et localhost<br>- Implémenter des timeouts et limitations de requêtes<br>- Utiliser des proxies dédiés pour les requêtes externes<br>- Isolation réseau des services sensibles |
| **Lien de référence** | [OWASP - Server-Side Request Forgery (SSRF)](https://owasp.org/www-community/attacks/Server_Side_Request_Forgery) |