Utilizzi impropri dell’header HTTP X-Forwarded-For

L’header X-Forwarded-For, come tutti gli header HTTP che hanno come prefisso “X-”, è un campo non definito da una RFC ma introdotto da Squid. E’ utilizzato per segnalare al server Web l’IP assegnato al client, che fa uso di un proxy.

Quando si scrive un’applicazione Web normalmente si tiene traccia o si utilizza in vari modi l’indirizzo IP del client che ha effettuato la richiesta. In tal senso è veramente semplice ottenere l’indirizzo IP tramite un qualsiasi linguaggio lato server.

Ecco come potrebbe presentarsi una tipica richiesta che passa attraverso Squid:

Host: www.example.org
User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.9.1.3) Gecko/20090824 Firefox/3.5.3 (.NET CLR 3.5.30729)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: it-it,it;q=0.8,en-us;q=0.5,en;q=0.3
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
X-Forwarded-For: 192.168.30.25
Proxy-Connection: keep-alive

L’header X-Forwarded-For, essendo sotto il pieno controllo del client, può essere utilizzato da un attacker per veicolare qualsiasi contenuto. Capita spesso di vedere un utilizzo completamente errato di X-Forwarded-For:

//PHP style
$ip = $_SERVER['X_FORWARDED_FOR'] ? $_SERVER['X_FORWARDED_FOR'] : $_SERVER['REMOTE_ADDR'];

oppure

// C# style
String _ip = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
If (_ip == "" || _ip.ToLower == "unknown")
_ip = Request.ServerVariables["REMOTE_ADDR"];

La logica del codice precedente fa in modo che se l’header X-Forwarded-For è presente viene preso il suo contenuto, senza nessun tipo di validazione, come indirizzo IP del client. In questo non è difficile creare ad arte richieste per ingannare l’applicazione:

X-Forwarded-For: 1.2.3.4

oppure

X-Forwarded-For: ‘ ; SELECT VERSION() –

La logica giusta per gestire gli indirizzi IP è quella di utilizzare il contenuto dell’header X-Forwarded-For in maniera non esclusiva e sopratutto di trattarlo come un qualsiasi user-input.

 

Cookie, HTTP e HTTPS

I cookie sono una parte fondamentale del protocollo HTTP, essendo esso state-less, è necessario memorizzare le informazioni della sessione sull’applicazione Web direttamente nel Web Browser.

Questa piccola premessa (consiglio un approfondimento tramite la voce cookie su Wikipedia) per arrivare a dire: su HTTP i cookie possono essere intercettati e usati da un attaccante.  Credo che molti diranno: “Niente di nuovo sulla piazza”.
In soccorso a questo problema è nato il protocollo HTTPS che incapsula HTTP in una connessione cifrata con il Web Server di destinazione. In questo modo un attacco MITM diventa più complesso o per lo meno più macchinoso.
Sarebbero tutte rose e fiori se gli sviluppatori avessero recepito l’uso del flag “Secure” dell’header Cookie di HTTP. Questo flag impone al Web Browser di inviare il cookie solamente in presenza di un canale sicuro, interpretato durante l’implementazione nei Web Browser della RFC 2965 come l’HTTPS.

Il paper “Surf Jack – HTTPS will not save you” ha fatto notare una cosa molto importante: è inutile utilizzare le connessioni HTTPS quando i cookie non hanno il flag “Secure” attivo. Il perchè lo si può capire dallo screencast che segue:

Il cookie di sessione, non avendo attivo il flag “Secure”, viene inviato al Web Server anche su connessioni in chiaro. In questo modo un ataccante che si trova in condizioni di fare hijacking (tramite una qualsiasi tecnica) sarà in grado di dirottare (con un HTTP Redirect) la vittima in HTTP, in modo che il browser invii i cookie, del dominio target, in chiaro.

Il problema è più diffuso di quanto sembra, non credo che fino ad ora ne fosse stato considerato correttamente l’impatto. Ad esempio Google ha introdotto solo recentemente una funzione in Gmail che permette di utilizzare la Webmail solo tramite HTTPS inserendo il flag “Secure” sui cookie che contengono l’id della sessione.