Come rendere sicure le applicazioni Web
Ecco alcune regole da seguire per prevenire gli attacchi a un sito Interneta cura di Maurizio Bergami
La maggior parte delle applicazioni Web sono vulnerabili a un attacco esterno. Le note intrusioni nei siti di CD Universe e di Egghead.com sono solo pochi esempi di un problema crescente. Le armi più importanti per rendere sicuri i siti da un attacco sono la consapevolezza dei rischi e la conoscenza delle problematiche tecniche sottostanti. Quando un malintenzionato prende di mira un’applicazione Web, generalmente si pone quattro domande: (1) Posso vedere ciò che gli utenti stanno guardando? (2) Posso impersonare un utente? (3) Posso impersonare il gestore del sito? (4) Posso usare i computer del sito per eseguire i miei comandi?
Posso vedere ciò che gli utenti stanno guardando?
Il metodo ovvio per prevenire che altri possano leggere i dati in transito è la cifratura della connessione fra un sito e i suoi utenti. Quasi tutti i browser e i server Web possono inviare e ricevere dati su canali cifrati, gestiti da due protocolli strettamente correlati: Ssl e Tsl. L’Ssl (Secure Sockets Layer) è stato creato da Netscape; il Tsl (Transport Security Layer), più recente, è un protocollo indipendente compatibile con Ssl 3.0. La figura 1, nella pagina successiva, mostra questi protocolli elencati nella scheda Avanzate delle Opzioni Internet in Microsoft Internet Explorer. I browser si connettono ai siti Web usando l’Http (HyperText Transfer Protocol), così come indicato all’inizio della Url nella barra degli indirizzi: http://www.qualchesito.com. Quando il browser si connette a un sito sicuro usa invece l’Https (HyperText Transfer Protocol Secure), che non è altro che l’Http cifrato grazie a Ssl o Tsl; in questo caso l’Url è del tipo https:// www.qualchesito.com. Per stabilire una connessione sicura, il browser per prima cosa chiede al server Web il suo certificato digitale, per verificarne l’effettiva identità; contemporaneamente invia anche l’elenco degli algoritmi di cifratura che è in grado di utilizzare. Il server invia il certificato richiesto e indica l’algoritmo che intende usare per la codifica dei dati. Il browser a questo punto verifica il certificato, controllandone la firma digitale per identificare eventuali segni di manomissione e accertandosi che l’Url al quale è collegato corrisponda effettivamente al campo Common Name del certificato. Se uno di questi test fallisce, il browser dà un messaggio di avviso. La cifratura simmetrica è usata per le comunicazioni fra browser e server; questo termine indica che la stessa chiave segreta di sessione viene usata sia per cifrare sia per decifrare. Il browser genera la chiave una volta che il certificato del server è stato convalidato, ma poi necessita di un modo sicuro per trasmetterla al server. Questo si ottiene attraverso la cifratura a doppia chiave. Il browser codifica la chiave di sessione usando la chiave pubblica del server (contenuta nel certificato digitale appena ricevuto) e poi la trasmette al server stesso. Il server invece decifra la chiave di sessione usando la propria chiave privata e manda un avviso di ricevuta (acknowledgement) al browser. Raggiunto questo stadio è stato stabilito un collegamento cifrato. Il browser e il server possiedono entrambi la stessa chiave di sessione e hanno aderito entrambi all’uso dello stesso algoritmo di cifratura. Il traffico susseguente userà questo collegamento cifrato e il browser, per indicare che è stato stabilito un collegamento sicuro, mostrerà nella propria barra di statoun’icona che rappresenta un lucchetto giallo chiuso. Come mostrato in figura 2, l’utente del sito può verificare l’identità del server facendo clic su questa icona per esaminare il certificato del server. Stabilire un collegamento cifrato richiede semplicemente che il server ottenga un certificato firmato da un’autorità di certificazione ben conosciuta, ad esempio VeriSign. Tuttavia la cifratura è in grado solamente di evitare che altri vedano i dati inviati e ricevuti da un server Web, ma non è in grado di evitare falsificazioni di identità e neppure protegge il sito da attacchi con intenti criminosi.
Posso impersonare il visitatore di un sito?
Abbiamo appena descritto il modo in cui gli utenti possono autenticare un sito Web, ovvero come possono essere sicuri che il server al quale si sono collegati sia effettivamente chi afferma di essere. Come fa invece un sito Web a riconoscere i propri utenti? La maggior parte dei server Web supporta due schemi di autenticazione tramite password: uno più semplice da implementare ma anche meno sicuro e uno – più robusto – basato sul cosiddetto digest. Entrambi gli schemi operano mandando una “sfida” al browser: quando il browser la riceve per la prima volta, fa comparire una finestra di dialogo che richiede il nome utente e la password. Usando il metodo di autenticazione più semplice il browser trasmette al server il nome utente e la password sotto forma di testo semplice e in chiaro (cioè non cifrato). Con il secondo metodo di autenticazione il browser trasmette invece un particolare testo cifrato (detto appunto digest) ottenuto a partire dal nome utente e dalla password. In entrambi i casi il server verifica i dati ricevuti e, se sono corretti, risponde con un messaggio di approvazione; il browser a sua volta memorizza in cache le informazioni di logon per tutta la sessione di lavoro in modo che l’utente non debba reinserirle ad ogni pagina visitata. Questi schemi di autenticazione si possono implementare con una semplice impostazione del server Web: non è necessario aggiungere codice all’applicazione. Tuttavia non sono una panacea. Il primo problema riguarda ancora lo spionaggio dei dati in transito: se gli utenti mandano il nome utente e la password in chiaro, un attaccante può catturarli. Questo problema può essere risolto in modo semplice trasmettendo le informazioni dell’utente usando l’Ssl; il frammento di codice Http che segue mostra come farlo:
form action=”https://foo.com/login.asp” method=”post” User ID: input type=”text” name=”user” br Password: input type=”password” name=”password” br input type=”submit” value=”Login” /form
Se un malintenzionato non può spiare le comunicazioni fra il sito Web e i visitatori, forse può fare una cosa ancora migliore: impersonare un utente. Il punto debole che rende questo possibile è proprio lo stesso utente. La maggior parte dei navigatori del Web scelgono password non sicure e, ancora peggio, tendono a usare la stessa coppia nome utente/password per tutti i siti che richiedono una procedura di logon. Un modo per risolvere il problema è quello di rendere obbligatoria la scelta di una password “robusta” quando un utente registra il proprio account. Il codice dell’applicazione Web può confrontare la password proposta con il contenuto di un vocabolario per respingere parole comuni e può costringere ad usare numeri o l’uso misto di maiuscole e minuscole. Nel caso di una intranet sulla quale siano presenti molti siti che richiedono l’autenticazione, può essere usata una tecnologia di accesso di tipo single sign-on, come ad esempio Microsoft Passport, grazie alla quale basta autenticarsi su un sito per essere riconosciuti automaticamente da tutti gli altri senza bisogno di ulteriori logon. Password difficili da indovinare comunque non sono sufficienti se il sito è vulnerabile agli attacchi.
Posso impersonare il gestore del sito?
Una volta che gli utenti hanno avuto accesso al sito, si vuole che le loro credenziali rimangano valide finché non decidono di uscirne. Ma come si può ottenere questo risultato? Non c’è connessione permanente fra il browser e il server: viene stabilita una connessione separata per ogni pagina richiesta. Come fa quindi un server Web a verificare le credenziali dell’utente dopo il logon iniziale? Risposta: il browser memorizza il nome utente e la password per tutto il tempo in cui la propria finestra rimane aperta, e li ritrasmette al server ogni volta che si ricollega ad esso. Il server quindi confronta ogni volta le informazioni ricevute con quelle presenti nel suo database degli utenti e consente o nega l’accesso a seconda che esista o meno una corrispondenza. Come già detto in precedenza, il browser tenta di confermare l’identità del sito al quale si è collegato confrontando l’Url con il Common Name contenuto nel certificato digitale del server. Questa è una precauzione ragionevole, ma non è in grado di contrastare tutti gli attacchi di impersonificazione del server. Il Domain Name Service (Dns), che traduce i nomi come www.lamiabanca.it in indirizzi Ip numerici, è un anello vulnerabile della catena della sicurezza: se un malintenzionato riuscisse ad accedere al server Dns e ne modificasse i registri facendo in modo da farli puntare a uno dei propri computer invece che a quelli legittimi, tale computer potrebbe poi reindirizzare tutte le richieste Https – ad esempio – da www.lamiabanca.it a www.sitofinto.com/{stringa di caratteri lunga e incomprensibile}. Dato che durante il reindirizzamento il browser mostra di default la parte finale dell’indirizzo, se quest’ultimo è abbastanza lungo da mettere la porzione www.sitofinto.com fuori dal campo di vista, la maggior parte degli utenti non noteranno di essere collegati a un sito dal nome diverso da quello desiderato. Se il gestore di www.sitofinto.com ottenesse poi un certificato digitale da VeriSign, il browser indicherebbe una connessione del tutto lecita e non darebbe alcun messaggio di avviso. Solo facendo clic sull’icona a forma di lucchetto per visionare i dettagli del certificato digitale l’utente potrebbe rendersi conto dell’inganno. Dato che è molto facile costruire una pagina Web identica a un’altra, il malintenzionato a questo punto potrebbe realizzare una schermata di accesso simile in tutto per tutto a quella di www.lamiabanca.com e usarla per catturare nomi utente e password, inserite dai visitatori ignari di essere collegati a un sito di un pirata informatico. In un certo senso questa è la versione per Internet di una truffa usata anche nel mondo fisico: fece scalpore, anni addietro, il caso di un bancomat fasullo collocato al di fuori di un importante stadio poco prima dell’inizio di una partita. Molti tifosi tentarono di prelevare denaro, con l’unico risultato di veder sparire la tessera subito dopo l’inserimento del Pin, mentre a video compariva un messaggio di errore e un invito a contattare la propria banca per la restituzione. Iniziata la partita gli ingegnosi truffatori recuperarono i bancomat e poterono effettuare in tutta tranquillità numerosi prelievi usando le tessere inghiottite dal dispositivo e i relativi Pin debitamente registrati.
Posso usare il computer di un sito per eseguire i miei comandi?
Alcuni tipi attacchi sfruttano le vulnerabilità dei software usati dai server Web per installare e far eseguire del codice dannoso. Un tipo di attacco molto noto è quello del buffer overrun (letteralmente: tracimazione del buffer), che prevede l’invio di una quantità eccessiva di dati al server. Il seguente frammento di codice C++ è vulnerabile a un attacco di buffer overrun perché non controlla se i dati in arrivo superino il limite previsto di 255 caratteri:
void ByYourCommand( char* pszData ) { char szBuffer [255 ]; strcpy( szBuffer, pszData ); …}
Cosa accade se la funzione strcpy() provoca un overflow del buffer basato su stack? La figura 3 mostra l’aspetto dello stack delle chiamate di sistema dopo che è stata eseguita la funzione ByYourCommand(): lo stack cresce a partire dalla parte alta della memoria e il buffer si riempie dal fondo della memoria. Scrivendo troppi dati all’interno del buffer, un attaccante può arrivare a sovrascrivere il cosiddetto function call record: si tratta di una struttura di dati che contiene i valori del registro salvati dal codice della funzione insieme con l’indirizzo di ritorno della funzione stessa. Sovrascrivendo quest’ultimo con un altro valore diventa possibile mandare in esecuzione sul computer attaccato un programma a piacere. Un pirata informatico naturalmente vorrà mandare in esecuzione il codice da lui stesso caricato sul sistema, ma come può riuscire ad introdurlo sul computer attaccato? Semplice: scrivendolo nel buffer dei dati! La stringa che viene passata alla semplice funzione appena vista potrebbe facilmente contenere alcune istruzioni capaci di avviare lo scaricamento da Internet di un cavallo di Troia come Back Orifice. Esistono molti casi documentati di questi tipi di attacchi alle applicazioni Web. Gli hacker sanno che le funzioni vulnerabili come quella appena mostrata sono di solito richiamate dal codice che elabora l’input dell’utente. Di conseguenza provano a mandare stringhe di input lunghissime al server e stanno a vedere che cosa succede. Nel caso in cui si verifichi effettivamente un overflow del buffer, il thread che elabora la richiesta molto probabilmente andrà in crash e l’hacker lo verrà facilmente a sapere dato che il browser segnalerà un timeout Http oppure un errore interno Http della serie 500. Come si può evitare che un’applicazione Web venga sfruttata illecitamente? Prima di tutto è fondamentale aggiungere le ultime patch di sicurezza del software di sistema utilizzato. Se non è possibile farlo tempestivamente con le risorse interne è opportuno assumere un amministratore di sistema che possa occuparsene. Ancora meglio, conviene scrivere del codice che renda automatica la procedura. Poi bisogna cercare tutto il codice esistente che è stato scritto usando linguaggi che permettono un accesso diretto alla memoria – come il C, il C++ e Delphi – ed esaminarlo per trovare eventuali vulnerabilità a errori di buffer overflow. La verifica del codice consente di capire se un’applicazione è suscettibile agli attacchi di questo genere, ma si può evitare completamente il problema usando linguaggi di programmazione che non consentono accesso diretto alla memoria, per esempio meccanismi di scripting come JavaScript e Perl oppure un linguaggio interpretato come Java. Sono altrettanto sicuri gli imminenti linguaggi della piattaforma .NET di Microsoft, ovvero il C# e il Visual Basic.net. Se il codice è scritto con linguaggi sicuri, gli operatori di un sito Web possono dedicarsi a compiti più interessanti che fare la guardia ai possibili buffer overflow. Non bisogna credere ciecamente alle promesse delle varie tecnologie: nessuna di esse è perfetta. Occorre capire come funzionano e scoprirne le debolezze. Sta ai responsabili dei siti gestire intelligentemente l’esposizione al rischio.




Ancora nessun commento.