open-redirect-vulnerabilityVi siete mai accorti che molti browser per aiutare l’utente ogni tanto correggono in modo automatico quello che scrivi nell’URL? Da questo aiuto deriva il problema di cui vi parlerò in questo post. Ci sono due browser attualmente molto utilizzati Chrome e Firefox che vanno contro le regole dettate da RFC. Di fatto se digitiamo nel browser ///sito.it i browser trasformano l’URL errata in http://sito.it creando una vulnerabilità di open-redirect.

Pensiamo come uno sviluppatore

Se dovessimo implementare questo /pagina?next_url=/messaggi andremo a controllare nel successivo step se next_url è relativo o assoluto ma localizzato sullo stesso dominio.

Assumiamo che esiste una regexp che controlla le prime lettere.

Faremo questo:

1. URL inizia con / bypassa //sito.it
2. URL inizia con / ma non inizia con // quindi bypassa anche /\sito.it
3. A questo punto utilizzeremo le librerie di parsing URL, seguendo le regole RFC. Dichiareremo che \ non è permesso nelle URL perché nessuna libreria accetterà mai questo carattere. RFC in questo caso, vince.

Ad una prima impressione ///sito.it sembrerebbe chiaramente un path relativo. Non credete?
1. / è la path 2. / è per l’host e il 3. […] ?

Secondo le regole https://dvcs.w3.org/hg/url/raw-file/tip/Overview.html#urls

– Uno schema URL è formato da // opzionalmente seguito da informazioni utente con “@”, poi l’host, opzionalmente “:”, porta, e opzionalmente una path relativa o un “?” seguito da una query.

//<user>:<password>@<host>:<port>/<url-path>

Prendiamo come esempio https://test.com se volessimo fare un URL redirect?

Come abbiamo visto:

/sito.it è una path relativa, quindi caricherà https://test.com/sito.it

//sito.it è uno schema URL quindi caricherà https://sito.it

Si è accesa la lampadina???

Purtroppo vi smonto subito. La domanda è: quindi se metto ///sito.it verrà rediretto? NO. Purtroppo anche questa è una path relativa perché la terza parte è / così non potrà essere uno schema URL perché come abbiamo detto prima per esserlo bisogna che sia // seguito da un host che non contenga slash.

Questo secondo l’RFC. Ma c’è chi non rispetta le regole.

Supponiamo di caricare https://test.com///sito.it

La cosa è che Chrome e Firefox lo parsano come uno schema URL e caricano https://sito.it, Safari lo vede come una path, Opera carica https:////x.com (WTF?)

Ora che abbiamo questa vulnerabilità, pensiamo il redirect così come segue.

http://www.facebook.com/test?to=///sito.it#password dove password potrebbe essere un dato sensibile da passare alla nostra pagina opportunamente modificata per ricevere dati. Sappiamo bene che non esiste questa URL non la provate ;-) era solo un esempio.

Usa le librerie, Luke…

Di solito su internet troviamo spesso url come /login?to=/notifica. La questione è come validano questa URL i programmatori?

Facciamo un po di pratica con il parsing delle URL. Vediamo per i diversi linguaggi di programmazione la parte ?next=///test.com

Perl (la vede come una path)
use URI;
print URI->new(“///test.com”)->path;

Python (la vede come una path)
import urllib
>>> urlparse.urlparse(‘//test.com’)
ParseResult(scheme=”, netloc=’test.com’, path=”, params=”, query=”, fragment=”)
>>> urlparse.urlparse(‘///test.com’)
ParseResult(scheme=”, netloc=”, path=’/sito.com’, params=”, query=”, fragment=”)
>>> urlparse.urlparse(‘//////test.com’)
ParseResult(scheme=”, netloc=”, path=’////test.com’, params=”, query=”, fragment=”)

Ruby (la vede come una path)
1.9.3-p194 :004 > URI.parse(‘///test.com’).path
=> “/test.com”
1.9.3-p194 :005 > URI.parse(‘///test.com’).host
=> nil

Node.js (la vede come una path)
> url.parse(‘//test.com’).host
undefined
> url.parse(‘///test.com’).host
undefined
> url.parse(‘///test.com’).path
‘///test.com’

PHP (BINGO!!!)
print_r( parse_url(“///test.com”));

Questo infatti non funziona (ma in teoria dovrebbe). Dovresti essere felice! Ma…aspetta, mentre tutti gli altri linguaggi non parsano /\youtube.com perché non è valido. PHP lo vede come una path.

print_r( parse_url(“/\test.com”));
Anche questo è vulnerabile.

Implicazioni di sicurezza

Di base, con /\sito.it e ///sito.it noi possiamo sfruttare un open redirect per la maggior parte dei siti web.

L’unica protezione per questa vulnerabilitè la FULL PATH.
Location: http://miosito/ + parametri[:next]

I redirects possono exploitare diversi Single Sign On o soluzioni OAuth: per esempio 302 redirect con #access_token per poi prendere il controllo totale dell’account per esempio con il Facebook Connect. :-)

Cheers!