Cosa fa#
Un attaccante manipola un parametro che il server usa per costruire un percorso file, inserendo sequenze ../ per uscire dalla directory base e leggere file arbitrari sul filesystem.
Path Traversal è navigazione non autorizzata nel filesystem
TL;DR#
# Il server carica un'immagine in questo modo:
GET /image?filename=37.jpg
# Il server risolve internamente:
/var/www/images/37.jpg
# L'attaccante sostituisce filename con un path traversal:
GET /image?filename=../../../etc/passwd
# Il server risolve:
/var/www/images/../../../etc/passwd → /etc/passwdVettori di attacco#
Il parametro vulnerabile non e' solo nel query string. Qualsiasi punto dove il server riceve un nome o percorso file puo' essere un vettore:
- Query parameter:
?filename=37.jpg - Body POST:
{"file": "report.pdf"}in una API JSON - Cookie:
document=invoice.pdf - Path segment:
/files/37.jpg - Header HTTP:
X-File-Name:,Referer:
Come costruire il payload#
Per uscire da una directory servono sequenze ../ proporzionali alla profondita' del path base.
- Regola dei troppi
../: Su Unix, aggiungere sequenze oltre la root (/) e' sicuro; il path rimane/. Partire con 8-10../garantisce di arrivare alla radice.
Tecniche di Bypass (Evasione Filtri)#
Gli sviluppatori spesso implementano filtri per bloccare le sequenze ../. Esistono diverse tecniche per aggirarli:
1. Filtri non ricorsivi#
Se il server rimuove ../ in modo non ricorsivo (una sola volta), si usa una sequenza nidificata:
- Payload:
....//o....\/ - Risultato dopo il filtro:
../
2. URL Encoding & Double Encoding#
Utile se il server decodifica l'input dopo aver applicato i filtri di sicurezza:
- Single Encoding:
%2e%2e%2f - Double Encoding:
%252e%252e%252f(dove%25e' l'crypto del simbolo%)
3. Validazione del Prefisso (Base Folder)#
Se il server richiede che il percorso inizi con una cartella specifica:
- Payload:
/var/www/images/../../../etc/passwd
4. Null Byte Injection (%00)#
Utilizzato su sistemi legacy (es: PHP < 5.3) per terminare la stringa del percorso prima di un'estensione forzata dal server:
- Payload:
../../../etc/passwd%00.jpg - Effetto: Il sistema operativo smette di leggere allo zero binario, ignorando
.jpg.
Target utili#
| File | Contenuto utile |
|---|---|
/etc/passwd | Utenti, servizi attivi, home directory |
/etc/hosts | Hostname interni, altri server nella rete |
/proc/self/environ | Variabili d'ambiente del processo (possibili API key) |
/var/log/apache2/access.log | Log di accesso — utile per log poisoning |
../../../var/www/html/config.php | Credenziali database |
Mitigazioni e Difesa: La Canonicalizzazione#
Il modo più efficace per prevenire il Path Traversal è evitare di passare input fornito dall'utente direttamente alle API del filesystem. Se non è possibile evitarlo, la Canonicalizzazione (Canonicalization) è la linea di difesa fondamentale.
Cos'è la Canonicalizzazione?#
È il processo di conversione di un percorso (path) che può contenere caratteri "rumorosi" (../, ./, link simbolici, crypto multipli) nella sua forma più semplice, univoca e assoluta.
Perché è fondamentale?#
Un server può essere ingannato da stringhe diverse che puntano allo stesso file:
../../etc/passwd/var/www/html/../../etc/passwd/etc/passwd
La Canonicalizzazione è come se il server eseguisse un cd virtuale fino alla destinazione finale per vedere dove atterra realmente, ignorando i trucchi sulla "busta".
L'Analogia del Recinto (Dev vs SOC)#
Immagina che la tua cartella sicura sia un recinto chiamato /var/www/html/. Tutto quello che c'è fuori è privato.
L'attaccante invia: /var/www/html/../../../etc/passwd.
Visione Developer (Senza Canonicalizzazione): Il codice controlla solo la stringa grezza: "Inizia con /var/www/html/?". Risposta: SÌ. Il controllo passa, ma il sistema operativo risolve i
../e legge il file fuori dal recinto.Visione SOC Analyst (Con Canonicalizzazione): Il codice prima "pulisce" il percorso risolvendo i
../. La stringa diventa:/etc/passwd. Il codice ora controlla la "vera faccia" dell'input: "Il percorso REALE (/etc/passwd) inizia con /var/www/html/?". Risposta: NO. L'attacco viene bloccato perché hai guardato dove puntava davvero, non cosa c'era scritto sulla busta.
Esempio in Pseudo-codice: Controllo Debole vs Robusto#
// --- VISIONE DEVELOPER (DEBOLE) ---
// Input: "/var/www/html/../../../etc/passwd"
if (userInput.startsWith("/var/www/html/")) {
// PASSATO: La stringa inizia effettivamente con il prefisso richiesto.
// DISASTRO: Il Sistema Operativo risolverà i ../ e leggerà /etc/passwd.
fs.readFile(userInput);
}
// --- VISIONE SOC ANALYST (ROBUSTO) ---
// Input: "/var/www/html/../../../etc/passwd"
const realPath = path.resolve(userInput); // Canonicalizzazione
// realPath ora è diventato "/etc/passwd"
if (realPath.startsWith("/var/www/html/")) {
// BLOCCATO: "/etc/passwd" NON inizia con "/var/www/html/".
fs.readFile(realPath);
}la Canonicalizzazione è il processo di trasformazione di un percorso relativo o "sporco" (es. ../../etc/passwd) nella sua forma assoluta e univoca (es. /etc/passwd).
Come funziona la difesa corretta#
- Input: L'utente invia
../../etc/passwd. - Canonicalizzazione: Il sistema operativo o il linguaggio (es.
realpath()in PHP,os.path.abspath()in Python) risolve tutti i puntatori e restituisce il percorso reale:/etc/passwd. - Verifica (Sanitizzazione): Il server ora confronta il percorso reale (
/etc/passwd) con la directory autorizzata (/var/www/images/). - Risultato: Poiché
/etc/passwdnon inizia con/var/www/images/, l'accesso viene negato.
Senza la canonicalizzazione, il server confronta "mele con pere": una stringa relativa (../../) contro un prefisso assoluto. La difesa fallisce sempre.
Esempi di Implementazione#
PHP:
<?php
$base_dir = '/var/www/images/';
$requested = $_GET['filename'];
// realpath risolve tutti i ../ e i link simbolici (Canonicalizzazione)
$full_path = realpath($base_dir . $requested);
// Verifica che il percorso risolto inizi con la directory base
if ($full_path !== false && strpos($full_path, $base_dir) === 0) {
readfile($full_path);
} else {
header('HTTP/1.0 403 Forbidden');
die('Access denied.');
}
?>
Node.js:
const path = require('path');
const fs = require('fs');
const baseDir = path.join(__dirname, 'images');
const requestedFile = req.query.filename;
// path.resolve() risolve il percorso assoluto (Canonicalizzazione)
const fullPath = path.resolve(baseDir, requestedFile);
// Verifica che il path risolto sia ancora all'interno di baseDir
if (fullPath.startsWith(baseDir)) {
fs.readFile(fullPath, (err, data) => {
// ... processa file
});
} else {
res.status(403).send('Access denied');
}Scenario Reale#
Un analista Blue Team riceve un alert IDS per richieste HTTP anomale. Nei log vede:
GET /api/download?file=../../../../etc/passwd HTTP/1.1
La sequenza crescente di ../ e' un pattern riconoscibile.
Risposta: blocco IP, analisi dei log per confermare se il server ha risposto con 200 OK (esfiltrazione riuscita) o 403/404.
Collegato a#
- ctf — categoria
- bandit-07 — LFI su OTW Natas


