Skip to main content
  1. Concetti/

Path Traversal

·5 mins
Alessio Barnini
Author
Alessio Barnini
Table of Contents

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/passwd

Vettori 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 %25 e' 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
#

FileContenuto utile
/etc/passwdUtenti, servizi attivi, home directory
/etc/hostsHostname interni, altri server nella rete
/proc/self/environVariabili d'ambiente del processo (possibili API key)
/var/log/apache2/access.logLog di accesso — utile per log poisoning
../../../var/www/html/config.phpCredenziali 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
Intuizione Rapida

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: . 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);
}
In Sintesi

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
#

  1. Input: L'utente invia ../../etc/passwd.
  2. 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.
  3. Verifica (Sanitizzazione): Il server ora confronta il percorso reale (/etc/passwd) con la directory autorizzata (/var/www/images/).
  4. Risultato: Poiché /etc/passwd non inizia con /var/www/images/, l'accesso viene negato.
Important

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

Related