Le applicazioni Web presentano, per architetti, progettisti e sviluppatori, una serie complessa di problemi di protezione. Le applicazioni Web più sicure e con le maggiori capacità di recupero sono quelle progettate sin dall'inizio con una particolare attenzione alla protezione.
È necessario applicare valide procedure architetturali e di progettazione e incorporare considerazioni di distribuzione e criteri di protezione aziendali durante le prime fasi di progettazione. In caso contrario, le applicazioni prodotte non potranno essere distribuite in un'infrastruttura esistente senza compromettere la protezione.
In questo modulo viene presentata una serie di linee guida di progettazione e architetturali per creare applicazioni protette. Tali linee guida sono state organizzate in base alle categorie di vulnerabilità più comuni delle applicazioni. Si tratta di aree chiave della protezione delle applicazioni Web e in cui più spesso vengono commessi errori.
Il modulo consente di:
| • | Identificare i problemi chiave concernenti la progettazione e l'architettura, per garantire applicazioni Web protette. |
| • | Valutare i problemi di distribuzione chiave in fase di progettazione. |
| • | Progettare strategie per migliorare la convalida dell'input dell'applicazione Web. |
| • | Progettare meccanismi sicuri di gestione delle sessioni e autenticazione. |
| • | Scegliere un modello di autorizzazione appropriato. |
| • | Implementare procedure di gestione degli account efficaci e proteggere le sessioni utente. |
| • | Utilizzare la crittografia per garantire riservatezza, impossibilità di ripudio, impossibilità di manomissione e autenticazione. |
| • | Prevenire la manipolazione dei parametri. |
| • | Progettare strategie di controllo e registrazione. |
Sebbene siano contenute in un testo sulla protezione ASP.NET, le informazioni presenti in questo modulo sono pertinenti per chiunque sia interessato allo sviluppo di applicazioni Web protette.
Il modulo si concentra sulle linee guida e i principi da seguire quando si progetta un'applicazione.
Per trarre il massimo vantaggio dal modulo:
| • | Acquisire informazioni sui pericoli per l'applicazione, in modo da garantire che vengano affrontati nella progettazione. Leggere il modulo 2 "Pericoli e contromisure", per comprendere i pericoli da considerare. Nel modulo 2 sono elencati i pericoli che potrebbero danneggiare l'applicazione e che devono essere presi in considerazione già in fase di progettazione. |
| • | Utilizzare un approccio sistematico nelle aree chiave in cui l'applicazione potrebbe essere vulnerabile ad attacchi. Concentrarsi sulle considerazioni di distribuzione, la convalida dell'input, l'autenticazione e l'autorizzazione, la crittografia e la riservatezza dei dati, la gestione di configurazione, sessioni e eccezioni e le adeguate procedure di controllo e registrazione per garantire la responsabilità personale. |
Le applicazioni Web comportano per progettisti e sviluppatori numerose difficoltà. A causa dell'assenza in HTTP di informazioni sullo stato, la registrazione dello stato della sessione per singolo utente diventa responsabilità dell'applicazione. Per poter eseguire tale operazione, l'applicazione deve essere in grado di identificare l'utente utilizzando una forma di autenticazione. Poiché tutte le successive decisioni di autorizzazione si basano sull'identità dell'utente, è essenziale che il processo di autenticazione sia sicuro e che il meccanismo di gestione delle sessioni utilizzato per registrare gli utenti autenticati sia ben protetto. La progettazione di meccanismi sicuri di autenticazione e gestione delle sessioni è solo uno dei problemi che devono affrontare i progettisti e gli sviluppatori di applicazioni Web. Altre difficoltà nascono dal passaggio dei dati di input e output in reti pubbliche. Tra i problemi principali infine si inseriscono le strategie per evitare la manipolazione dei parametri e la divulgazione di dati riservati.
Alcuni dei problemi principali che devono essere affrontati con procedure di progettazione sicure sono illustrati nella figura 4.1.

Figura 4.1
Problematiche relative alla progettazione dell'applicazione
Le linee guida di progettazione di questo modulo sono organizzate per categoria di vulnerabilità dell'applicazione. L'esperienza dimostra che un'inadeguata progettazione in queste aree, in particolare, provoca vulnerabilità di protezione. La tabella 4.1 elenca le categorie di vulnerabilità e per ciascuna di esse evidenzia i potenziali problemi causati da una progettazione inadeguata.
Tabella 4.1. Vulnerabilità delle applicazioni Web e potenziali problemi dovuti a una progettazione inadeguata
| Categoria di vulnerabilità | Potenziale problema dovuto a un'inaccurata progettazione |
Convalida dell'input | Attacchi eseguiti incorporando stringhe dannose in stringhe di query, campi di modulo, cookie e intestazioni HTTP. Sono inclusi gli attacchi di esecuzione di comandi, script tra siti, SQL injection e overflow del buffer. |
Autenticazione | Spoofing dell'identità, violazione di password, incremento di privilegi e accesso non autorizzato. |
Autorizzazione | Accesso a dati riservati o con restrizioni, manomissione ed esecuzione di operazioni non autorizzate. |
Gestione della configurazione | Accesso non autorizzato a interfacce di amministrazione, possibilità di aggiornare i dati di configurazione e accesso non autorizzato ad account utente e profili account. |
Dati sensibili | Divulgazione di informazioni riservate e manomissione dei dati. |
Gestione delle sessioni | Acquisizione di identificatori di sessione, che provoca il dirottamento di sessione e lo spoofing dell'identità. |
Crittografia | Accesso a dati riservati o credenziali di account, o a entrambi. |
Manipolazione dei parametri | Attacchi di attraversamento di percorsi, esecuzione di comandi e superamento dei meccanismi di controllo dell'accesso, tra gli altri, che portano alla divulgazione di informazioni, all'incremento di privilegi e alla negazione del servizio. |
Gestione delle eccezioni | Negazione del servizio e divulgazione di dettagli di sistema riservati. |
Controllo e registrazione | Impossibilità di individuare segni di intrusione e di provare le azioni di un utente e difficoltà a diagnosticare i problemi. |
Durante la fase di progettazione dell'applicazione è necessario analizzare i criteri e le procedure di protezione aziendali insieme all'infrastruttura in cui deve essere distribuita l'applicazione. In genere, l'ambiente di destinazione non è flessibile e il progetto dell'applicazione deve riflettere le restrizioni. Talvolta sono necessari compromessi di progettazione dovuti, ad esempio, a restrizioni sui protocolli o sulle porte o a specifiche topologie di distribuzione. Identificare i vincoli nella parte iniziale della fase di progettazione, per evitare sorprese in seguito, e coinvolgere i membri dei team della rete e dell'infrastruttura per agevolare il processo.
La figura 4.2 illustra i diversi aspetti della distribuzione che devono essere presi in considerazione in fase di progettazione.

Figura 4.2
Considerazioni sulla distribuzione
I criteri di protezione determinano quali operazioni possono eseguire le applicazioni e quali gli utenti e, cosa ancora più importante, definiscono delle restrizioni per stabilire cosa le applicazioni e gli utenti non sono autorizzati a fare. In fase di progettazione delle applicazioni è consigliabile identificare e operare entro la struttura definita dai criteri di protezione aziendali, per essere certi di non violare criteri che potrebbero impedire la distribuzione dell'applicazione.
Comprendere la struttura di rete dell'ambiente di destinazione e i requisiti di protezione di base della rete in termini di regole di filtraggio, restrizioni sulle porte, protocolli supportati e così via.
Identificare con quale probabilità i firewall e i criteri firewall incideranno sulla progettazione e la distribuzione dell'applicazione. Potrebbero essere presenti firewall per separare Internet, di fronte alle applicazioni dalla rete interna. Potrebbero poi esserci ulteriori firewall davanti al database. Questi firewall possono incidere sulle porte di comunicazione possibili e, quindi, sulle opzioni di autenticazione dal server Web ai server applicazioni e database remoti. L'autenticazione Windows richiede, ad esempio, porte aggiuntive.
In fase di progettazione stabilire quali protocolli, porte e servizi sono autorizzati ad accedere alle risorse interne dai server Web della rete perimetrale. Identificare, inoltre, i protocolli e le porte richiesti dal progetto dell'applicazione e analizzare i potenziali pericoli associati all'apertura di nuove porte o all'utilizzo di nuovi protocolli.
Comunicare e registrare qualsiasi ipotesi formulata sulla protezione a livello di rete e di applicazione e le funzioni dei componenti. In questo modo si evita che i controlli di protezione vengano tralasciati quando sia il team di sviluppo che quello di rete presuppongono che sia l'altro team ad occuparsi del problema. Prestare attenzione alle difese di protezione fornite dall'applicazione basandosi sulla rete. Valutare le implicazioni di una modifica alla configurazione di rete. Se si implementa una specifica modifica di rete, in che grado ne risulta compromessa la protezione?
La considerazione circa la topologia di distribuzione dell'applicazione e l'esistenza di un livello di applicazioni remote è di importanza fondamentale e deve essere incorporata nel progetto. Se è presente un livello di applicazioni remote è necessario valutare come proteggere la rete tra i server, per affrontare il pericolo di ascolto e intercettazione di rete e garantire la riservatezza e l'integrità dei dati sensibili.
Valutare, inoltre, il flusso di identità e identificare gli account che verranno utilizzati per l'autenticazione di rete quando l'applicazione si connette a server remoti. Un approccio comune consiste nell'utilizzare un account di processo con privilegi minimi e creare un account duplicato (con mirroring) sul server remoto con la stessa password. In alternativa, è possibile utilizzare un account di processo di dominio, più facilmente amministrabile ma più difficile da proteggere a causa della difficoltà di limitare l'uso dell'account in rete. Spesso la presenza di un firewall o di domini separati senza relazioni di trust rende l'approccio dell'account locale l'unico praticabile.
Gli scenari Intranet, Extranet e Internet implicano tutti delle difficoltà. Le domande da porsi sono le seguenti: Come verrà passata l'identità del chiamante attraverso più livelli applicativi alle risorse di back-end? Dove verrà eseguita l'autenticazione? È possibile considerare attendibile l'autenticazione a livello front-end e utilizzare una connessione attendibile per accedere alle risorse back-end? Negli scenari Extranet è necessario valutare anche se si considerano attendibili gli account partner.
Per ulteriori informazioni su questi e altri problemi specifici degli scenari, vedere le sezioni "Intranet Security", "Extranet Security" e "Internet Security" dell'articolo "Building Secure ASP.NET Web Applications: Authentication, Authorization, and Secure Communication" all'indirizzo http://msdn.microsoft.com/library/en-us/dnnetsec/html/secnetlpMSDN.asp (in inglese).
La convalida dell'input è un problema spinoso la cui soluzione spetta principalmente agli sviluppatori dell'applicazione. Tuttavia, la corretta convalida dell'input è una delle misure di difesa più efficaci contro gli attuali attacchi alle applicazioni. La corretta convalida dell'input è una valida contromisura che consente di evitare gli script tra i siti, l'inserimento di comandi SQL, gli overflow del buffer e altri attacchi di input.
La convalida dell'input è un processo complesso perché la domanda circa quale sia da ritenersi l'input valido tra le applicazioni e anche all'interno di una singola applicazione non ha una sola risposta. Allo stesso modo, non esiste un'unica definizione di input dannoso. A questa difficoltà si deve aggiungere il fatto che l'uso che l'applicazione fa dell'input determina il rischio di attacco. Chiedersi, ad esempio, se si archiviano dati che verranno utilizzati da altre applicazioni, oppure se l'applicazione utilizza input di origini dati create da altre applicazioni.
Di seguito sono riportati alcuni suggerimenti per migliorare la convalida dell'input dell'applicazione Web:
| • | Presupporre che tutto l'input è dannoso. |
| • | Centralizzare l'approccio. |
| • | Non basarsi sulla convalida lato client. |
| • | Prestare attenzione ai problemi di canonicalization. |
| • | Vincolare, rifiutare e sterilizzare l'input. |
La convalida dell'input inizia con il presupposto fondamentale che tutto l'input sia dannoso fino a prova contraria. Se la sua origine è esterna ai confini di trust, l'input deve essere convalidato, a prescindere dal fatto che provenga da un servizio, una condivisione file, un utente o un database. Se, ad esempio, si chiama un servizio Web esterno che restituisce stringhe, come è possibile sapere che non vi sono inclusi comandi dannosi? Inoltre, se diverse applicazioni eseguono scritture in un database condiviso, quando si leggono i dati, come è possibile sapere se sono sicuri?
La strategia di convalida dell'input deve essere un elemento base della progettazione dell'applicazione. Valutare l'ipotesi di un approccio centralizzato alla convalida, utilizzando, ad esempio, un codice comune di convalida e filtro nelle librerie condivise. Questo garantisce che le regole di convalida siano applicate in modo coerente, consente di ridurre gli sforzi di sviluppo e agevola la gestione futura.
In molti casi, singoli campi richiedono una specifica convalida, ad esempio con espressioni regolari opportunamente sviluppate. Tuttavia, in genere è possibile individuare routine comuni per convalidare campi utilizzati regolarmente come indirizzi di posta elettronica, titoli, nomi, indirizzi postali, inclusi i CAP, e così via. Questo approccio è indicato nella figura 4.3.

Figura 4.3
Approccio centralizzato alla convalida dell'input
Il codice lato server deve eseguire proprie operazioni di convalida. Che cosa accadrebbe se un utente malintenzionato aggirasse il client o arrestasse le routine di script lato client disattivando, ad esempio, JavaScript? Utilizzare la convalida lato client per ridurre il numero di cicli di andata e ritorno al server ma non affidarsi a essa per garantire la protezione. Questo è un esempio di difesa a più livelli.
I dati in forma canonica si presentano nel loro aspetto standard o più semplice. Si definisce "canonicalization" il processo di conversione dei dati nella loro forma canonica. I percorsi file e gli URL sono particolarmente soggetti a problemi di canonicalization e molti degli attacchi andati a buon fine sono il risultato diretto di bug di canonicalization. Esaminare, ad esempio, la seguente stringa, che contiene un percorso file in forma canonica.
c:\temp\somefile.dat
Le stringhe riportate di seguito rappresentano lo stesso file.
somefile.dat c:\temp\subdir\..\somefile.dat c:\ temp\ somefile.dat ..\somefile.dat c%3A%5Ctemp%5Csubdir%5C%2E%2E%5Csomefile.dat
Nell'ultimo esempio i caratteri sono stati specificati in formato esadecimale:
| • | %3A equivale ai due punti. |
| • | %5C equivale a una barra rovesciata. |
| • | %2E equivale al punto. |
In generale, è consigliabile evitare di progettare applicazioni che accettano nomi file di input dall'utente, per impedire che si verifichino problemi di canonicalization. Valutare progetti alternativi. Fare in modo, ad esempio, che sia l'applicazione a determinare il nome file per l'utente.
Se è necessario accettare nomi file di input, verificarne la validità del formato prima di prendere decisioni di protezione come concedere o negare l'accesso al file specificato.
Per ulteriori informazioni su come gestire i nomi file ed eseguire operazioni I/O dei file in modo sicuro, vedere le sezioni "I/O file" dei moduli 7 "Creazione di assembly protetti" e 8 "Protezione dall'accesso di codice".
L'approccio preferenziale alla convalida dell'input consiste nel definire cosa sia consentito sin dall'inizio. È molto più semplice convalidare i dati basandosi su tipi, schemi e intervalli validi noti che cercando caratteri non validi noti. In fase di progettazione si è già consapevoli di cosa l'applicazione debba aspettarsi. L'intervallo di dati validi è, in genere, un insieme più circoscritto del potenziale input dannoso. Tuttavia, per garantire una difesa a più livelli, può essere opportuno anche rifiutare i caratteri non validi noti e quindi sterilizzare l'input. La strategia consigliata è illustrata nella figura 4.4.

Figura 4.4
Strategia di convalida dell'input: vincolare, rifiutare e sterilizzare l'input
Per creare una strategia efficace di convalida dell'input, esaminare i seguenti approcci e i relativi compromessi:
| • | Vincolare l'input. |
| • | Convalidare i dati in base al tipo, alla lunghezza, al formato e all'intervallo. |
| • | Rifiutare l'input non valido noto. |
| • | Sterilizzare l'input. |
Vincolare l'input significa consentire i dati validi. Questo è l'approccio preferenziale. L'idea è quella di definire un filtro dell'input accettabile utilizzando parametri come il tipo, la lunghezza, il formato e l'intervallo. Occorre definire quale sia l'input accettabile per i campi dell'applicazione e imporlo e rifiutare tutti gli altri dati come non validi.
Per vincolare l'input può essere necessario definire set di caratteri sul server, in modo che sia possibile stabilire la forma canonica dell'input in modo localizzato.
Se possibile, eseguire un controllo rigoroso del tipo sui dati di input, ad esempio, nelle classi utilizzate per manipolare ed elaborare i dati di input e nelle routine di accesso ai dati. Utilizzare, ad esempio, stored procedure con parametri per l'accesso ai dati, per trarre vantaggio dal controllo rigoroso del tipo dei campi di input.
Per i campi stringa è necessario controllare anche la lunghezza e, in molti casi, il formato, per verificare che sia appropriato. Ad esempio, i codici postali, i numeri di identificazione personali ed altri campi di questo genere hanno formati ben definiti, che possono essere convalidati utilizzando espressioni regolari. Oltre a rappresentare una valida prassi di programmazione, il controllo accurato riduce la possibilità di sfruttare il codice. Un utente malintenzionato può aggirare il controllo del tipo, ma il controllo della lunghezza della stringa può creargli notevoli difficoltà e impedirgli di sferrare l'attacco preferito.
È buona norma negare i dati "non validi"; anche se non è opportuno fare esclusivo affidamento su questo approccio. Si tratta, infatti, di un metodo in genere meno efficace di quello basato sull'autorizzazione dell'input "valido", descritto in precedenza. La soluzione ottimale è utilizzare il metodo basato sulla negazione in combinazione con un altro approccio. Per negare i dati non validi si presuppone che l'applicazione conosca tutte le variazioni dell'input dannoso. È importante ricordare che esistono diversi modi per rappresentare caratteri, motivo per cui è ancora una volta preferibile l'approccio basato sull'autorizzazione dell'input valido.
Sebbene sia utile per le applicazioni già distribuite e per le situazioni in cui non ci si può permettere di apportare modifiche significative, l'approccio basato sulla "negazione" non è efficace e solido come quello basato sull'"autorizzazione", poiché i dati non validi, come gli schemi utilizzabili per identificare attacchi comuni, mutano continuamente. I dati validi, al contrario, restano costanti nel tempo.
Attraverso la sterilizzazione è possibile rendere sicuri dei dati potenzialmente dannosi. Tale processo può essere utile quando non è possibile garantire che l'intervallo di input consentito sia sicuro. In questa casistica sono incluse quelle situazioni in cui si rimuove un valore null alla fine di una stringa fornita dall'utente o si esegue l'escape di valori in modo che siano trattati come rappresentazioni formali.
Un altro esempio molto comune di sterilizzazione dell'input nelle applicazioni Web è l'uso della codifica URL e HTML per includere dati e trattarli come testo invece che come script eseguibili. I metodi HtmlEncode eseguono l'escape dei caratteri HTML e i metodi UrlEncode codificano un URL in modo che corrisponda a una richiesta URI valida.
Di seguito sono riportati esempi applicati a comuni campi di input, utilizzando gli approcci precedenti:
| • | Campo Cognome. In questo esempio è appropriato utilizzare la procedura per vincolare l'input. Nel caso specifico è possibile consentire i dati di stringa nell'intervallo ASCII A–Z e a–z, e anche trattini e virgolette inglesi (che non hanno alcun significato in SQL) per gestire nomi come O'Dell. Verrà inoltre limitata la lunghezza in base al valore previsto più lungo. | ||||
| • | Campo Quantità. Si tratta di un altro caso in cui è utile vincolare l'input. In questo caso specifico, è possibile utilizzare una semplice restrizione del tipo e dell'intervallo imponendo, ad esempio, che i dati di input corrispondano a valori interi positivi compresi tra 0 e 1000. | ||||
| • | Campo a testo libero. Tra gli esempi sono inclusi i campi di commento nelle aree discussioni. In questo caso, è possibile consentire lettere e spazi e anche caratteri comuni come apostrofi, virgole e trattini. Il set dei caratteri consentiti non include i segni di maggiore e minore, le parentesi quadre e le parentesi graffe. Alcune applicazioni potrebbero consentire agli utenti di contrassegnare il testo utilizzando un set limitato di caratteri di script, come il grassetto "<b>" e il corsivo "<i>", o anche di includere un collegamento a un URL preferito. Nel caso dell'URL la convalida deve codificare il valore in modo che sia considerato un URL. Per ulteriori informazioni sulla convalida di campi a testo libero, vedere "Convalida dell'input" nel modulo 10 "Creazione di pagine e controlli ASP.NET protetti". | ||||
| • | Applicazione Web esistente che non convalida l'input utente. In uno scenario ideale, l'applicazione verifica l'input accettabile per ogni campo o punto di ingresso. Tuttavia, se si dispone di un'applicazione Web esistente che non convalida l'input utente, è necessario un approccio di ripiego per ridurre il rischio fino a quando non sarà possibile migliorare la strategia di convalida dell'input dell'applicazione. Sebbene nessuno dei seguenti approcci garantisca una gestione sicura dell'input, poiché questo dipende dalla provenienza dell'input e dalla modalità di utilizzo dello stesso nell'applicazione, è possibile considerarli come correzioni rapide per un miglioramento della protezione di breve termine:
|
Per ulteriori informazioni ed esempi di codifica dell'input, utilizzando espressioni regolari e controlli di convalida ASP.NET, vedere "Convalida dell'input" nel modulo 10 "Creazione di pagine e controlli ASP.NET protetti".
L'autenticazione è il processo di riconoscimento dell'identità del chiamante. Gli aspetti da considerare sono tre:
| • | Identificare quando è richiesta l'autenticazione nell'applicazione. In genere è richiesta ogni volta che viene attraversato un limite di trust. I limiti di trust includono, di norma, assembly, processi e host. |
| • | Convalidare l'identità del chiamante. Gli utenti in genere si autenticano con nomi utente e password. |
| • | Identificare l'utente al momento delle successive richieste. Quest'operazione richiede una forma di token di autenticazione. |
Per l'autenticazione degli utenti, in molte applicazioni Web viene utilizzato un meccanismo basato sulle password, in cui l'utente fornisce un nome utente e una password in un modulo HTML. In questo caso i problemi da considerare e le domande da porsi includono:
| • | Nomi utente e password vengono inviati in formato non crittografato su un canale non protetto? Se la risposta è affermativa, un utente malintenzionato può intercettare informazioni con un software di monitoraggio di rete, per acquisire le credenziali. Come contromisura proteggere il canale di comunicazione utilizzando SSL (Secure Socket Layer). |
| • | Come vengono archiviate le credenziali? Se si archiviano nomi utente e password in formato non crittografato, in file o in un database, si andrà incontro a problemi. Cosa accadrebbe se la directory dell'applicazione fosse configurata in modo non corretto e un utente malintenzionato individuasse il file e ne scaricasse il contenuto o aggiungesse un nuovo account di accesso con privilegi, oppure se un amministratore insoddisfatto si appropriasse del database dei nomi utenti e delle password? |
| • | Come vengono verificate le credenziali? Se l'unico obiettivo è quello di verificare che l'utente conosca il valore della password, non esiste alcuna necessità di archiviare le password utente. È possibile memorizzare un sistema di verifica nella forma di un valore hash e ricalcolare l'hash utilizzando il valore fornito dall'utente durante il processo di accesso. Per ridurre il pericolo di attacchi del dizionario contro l'archivio delle credenziali, utilizzare password complesse e combinare un valore salt generato in modo casuale con l'hash della password. |
| • | Come viene identificato l'utente autenticato dopo l'accesso iniziale? È necessario un tipo di ticket di autenticazione, ad esempio un cookie di autenticazione. Come viene protetto il cookie? Se viene inviato attraverso un canale non protetto, un utente malintenzionato può acquisirlo e utilizzarlo per accedere all'applicazione. Un cookie di autenticazione rubato equivale a un accesso rubato. |
Di seguito sono riportati alcuni suggerimenti per migliorare l'autenticazione dell'applicazione Web:
| • | Separare le aree pubbliche da quelle con restrizioni. |
| • | Utilizzare criteri di blocco degli account per gli account degli utenti finali. |
| • | Supportare periodi di scadenza delle password. |
| • | Prevedere la possibilità di disabilitare gli account. |
| • | Non memorizzare password in archivi utenti. |
| • | Richiedere password complesse. |
| • | Non inviare password in rete in formato non crittografato. |
| • | Proteggere i cookie di autenticazione. |
A un'area pubblica del sito può accedere qualsiasi utente in modalità anonima. Alle aree con restrizioni, invece, possono accedere solo utenti specifici, che devono autenticarsi sul sito. Prendere in considerazione un tipico sito Web di vendita al dettaglio. È possibile esaminare il catalogo dei prodotti in modo anonimo. Quando si aggiungono articoli al carrello, l'applicazione identifica l'utente con un identificatore di sessione. Infine, quando si inoltra l'ordine, si esegue una transazione protetta che richiede che si acceda al sistema per autenticare la transazione su SSL.
Suddividendo il sito in aree di accesso pubblico e con restrizioni, è possibile implementare regole di autenticazione e autorizzazione separate e limitare l'uso di SSL. Per evitare l'inutile sovraccarico delle prestazioni associato a SSL, progettare il sito in modo da limitare l'uso di SSL alle aree che richiedono l'accesso con autenticazione.
Disabilitare gli account degli utenti finali o scrivere eventi in un registro dopo un determinato numero di tentativi di accesso non riusciti. Se è in uso l'autenticazione Windows, come il protocollo NTLM o Kerberos, questi criteri possono essere configurati e applicati automaticamente dal sistema operativo. Con l'autenticazione basata su form, i criteri di blocco sono responsabilità dell'applicazione e devono essere incorporati nel progetto della stessa.
Verificare che i criteri di blocco degli account non possano essere sfruttati negli attacchi di tipo Denial of Service. Ad esempio, gli account di servizio predefiniti standard come IUSR_NOMECOMPUTER devono essere sostituiti da nomi account personalizzati, per evitare che un utente malintenzionato, che abbia ottenuto il nome del server Web IIS (Internet Information Services), possa bloccare gli account critici.
Le password non devono essere statiche e se ne deve prevedere la modifica come parte delle attività di gestione ordinaria, impostando periodi di scadenza. Valutare l'ipotesi di fornire questo tipo di servizio durante la fase di progettazione.
Se il sistema è compromesso, la possibilità di invalidare deliberatamente le credenziali o disabilitare gli account consente di impedire ulteriori attacchi.
Per verificare le password non è necessario archiviarle. Memorizzare, invece, un valore di hash unidirezionale e quindi ricalcolare l'hash utilizzando le password fornite dagli utenti. Per ridurre il pericolo di attacchi del dizionario contro l'archivio utenti, utilizzare password complesse e combinare un valore salt casuale con la password.
Non facilitare il compito di violare le password ai pirati informatici. Sono disponibili numerose linee guida, ma come regola base richiedere che le password includano un minimo di otto caratteri e una combinazione di lettere maiuscole e minuscole, numeri e caratteri speciali. Se si sta utilizzando la piattaforma per imporre tale funzionalità o si sta sviluppando un proprio sistema di convalida, questo passaggio è necessario per contrastare gli attacchi di tipo brute-force, in cui un utente malintenzionato tenta di violare una password tramite tentativi ed errori sistematici. Utilizzare espressioni regolari per agevolare la convalida di password complesse.
Per esempi di espressioni regolari, vedere "Convalida dell'input" nel modulo 10 "Creazione di pagine e controlli ASP.NET protetti".
Le password non crittografate inviate in rete possono essere intercettate. Per affrontare questo pericolo, proteggere il canale di comunicazione utilizzando, ad esempio, SSL per crittografare il traffico.
Un cookie di autenticazione rubato equivale a un accesso rubato. Proteggere i ticket di autenticazione utilizzando la crittografia e canali di comunicazione sicuri. Limitare, inoltre, il periodo di validità di un ticket di autenticazione, per fronteggiare il pericolo di spoofing che può essere generato dagli attacchi di riproduzione, in cui un utente malintenzionato acquisisce il cookie e lo utilizza per accedere illecitamente al sito. La riduzione del periodo di timeout del cookie non impedisce gli attacchi di riproduzione, ma limita l'intervallo di tempo a disposizione di un utente malintenzionato per accedere al sito utilizzando il cookie rubato.
L'autorizzazione determina le operazioni che l'identità autorizzata può eseguire e le risorse a cui è possibile accedere. Un sistema di autorizzazione inadeguato o inefficiente può consentire la divulgazione di informazioni e la manomissione dei dati. La difesa a più livelli è la strategia di protezione chiave da applicare al sistema di autorizzazione dell'applicazione.
Di seguito sono riportati alcuni suggerimenti per migliorare il sistema di autorizzazione dell'applicazione Web:
| • | Utilizzare più gatekeeper. |
| • | Restringere l'accesso utente alle risorse di sistema. |
| • | Prendere in considerazione la granularità dell'autorizzazione. |
Sul lato server è possibile utilizzare criteri IPSec (IP Security Protocol) per fornire restrizioni host e limitare la comunicazione da server a server. Ad esempio, un criterio IPSec potrebbe impedire a qualsiasi host, ad eccezione di un server Web designato, di connettersi a un server di database. IIS fornisce autorizzazioni Web e restrizioni IP/DNS (Internet Protocol/Domain Name System). Le autorizzazioni Web IIS si applicano a tutte le risorse richieste su HTTP a prescindere dall'utente. Non garantiscono alcuna protezione, se un utente malintenzionato riesce ad accedere al server. Per questo, le autorizzazioni NTFS consentono di specificare elenchi di controllo di accesso su base utente. Infine, ASP.NET fornisce l'autorizzazione URL e file insieme alle richieste di autorizzazione di oggetti Principal. Combinando questi gatekeeper è possibile sviluppare una strategia di autorizzazione efficace.
Le risorse di sistema includono file, cartelle, chiavi del Registro di sistema, oggetti Active Directory, oggetti di database, registri eventi e così via. Utilizzare elenchi di controllo di accesso (ACL) Windows per stabilire quali utenti possono accedere a determinate risorse e quali operazioni posso eseguire. Prestare particolare attenzione agli account utente Internet anonimi; bloccarli con elenchi di controllo di accesso sulle risorse che negano esplicitamente l'accesso a utenti anonimi.
Per ulteriori informazioni sul blocco degli account utente Internet anonimi con elenchi di controllo di accesso Windows, vedere il modulo 16 "Protezione del server Web".
Esistono tre modelli comuni di autorizzazione, ciascuno con diversi gradi di granularità e scalabilità.
L'approccio più granulare si basa sulla rappresentazione. L'accesso alla risorsa si verifica utilizzando il contesto di protezione del chiamante. Gli elenchi di controllo di accesso Windows sulle risorse protette (in genere, file o tabelle, o entrambi) determinano se il chiamante è autorizzato ad accedere alla risorsa. Se l'applicazione garantisce l'accesso principalmente a risorse specifiche dell'utente, questo approccio può essere una scelta valida. Questo metodo ha l'ulteriore vantaggio di consentire l'esecuzione del controllo a livello di sistema operativo nei diversi livelli dell'applicazione, poiché il contesto di protezione del chiamante originale si trasmette a livello di sistema operativo e viene utilizzato per l'accesso alle risorse. Tuttavia, la validità dell'approccio è limitata dal punto di vista della scalabilità, poiché non è supportato il pool di connessioni per l'accesso al database. Di conseguenza, viene utilizzato in genere in un numero limitato di applicazioni basate sull'Intranet. Il modello di rappresentazione è illustrato nella figura 4.5.

Figura 4.5
Modello di personificazione che offre granularità di autorizzazione per utente finale
L'approccio con il minor livello di granularità ma il maggior livello di scalabilità utilizza l'identità di processo dell'applicazione per l'accesso alle risorse. Questo metodo supporta pool di connessioni al database, ma prevede che le autorizzazioni concesse all'identità dell'applicazione nel database siano comuni, a prescindere dall'identità del chiamante originale. L'autorizzazione principale viene eseguita nel livello logico intermedio dell'applicazione utilizzando ruoli, che raggruppano gli utenti che condividono gli stessi privilegi nell'applicazione. L'accesso alle classi e ai metodi viene limitato in base all'appartenenza al ruolo del chiamante. Per supportare il recupero di dati su base utente, un metodo comune consiste nell'includere una colonna delle identità nelle tabelle del database e utilizzare parametri query per restringere i dati recuperati. È possibile, ad esempio, passare l'identità del chiamante originale al database a livello di applicazione (e non di sistema operativo), tramite parametri di stored procedure, e scrivere query simili alla seguente:
SELECT field1, field2, field3 FROM Table1 WHERE {some search criteria} AND
UserName = @originalCallerUserName
Questo modello viene definito come modello di sottosistema attendibile o, talvolta, come modello di server attendibile ed è illustrato nella figure 4.6.

Figura 4.6
Modello di sottosistema attendibile che supporta il pool di connessione al database
La terza opzione consiste nell'utilizzare una serie limitata di identità per l'accesso alle risorse determinata sulla base dell'appartenenza al ruolo del chiamante. Si tratta di una soluzione ibrida, che combina i due modelli descritti in precedenza. I chiamanti vengono mappati a ruoli nel livello logico intermedio dell'applicazione e l'accesso a classi e metodi viene limitato in base all'appartenenza al ruolo. L'accesso alle risorse downstream viene eseguito utilizzando una serie limitata di identità determinata dall'appartenenza al ruolo del chiamante corrente. Il vantaggio di questo approccio è che le autorizzazioni possono essere assegnate ad accessi separati nel database e i pool di connessioni sono ancora efficaci. Lo svantaggio è che la creazione di token di accesso a thread multipli, utilizzati per stabilire diversi contesti di protezione per l'accesso alle risorse di downstream tramite autenticazione Windows, è un'operazione con privilegi che richiede account di processo con privilegi. Vale il principio opposto a quello che prevede l'uso di account con privilegi minimi. Il modello ibrido, in cui vengono utilizzate più identità di servizio attendibili per l'accesso alle risorse di downstream, è illustrato nella figura 4.7.

Figura 4.7
Modello ibrido
Valutare con estrema attenzione la funzionalità di gestione della configurazione dell'applicazione Web. La maggior parte delle applicazioni richiede interfacce che consentano a sviluppatori di contenuti, operatori e amministratori di configurare l'applicazione e gestire elementi come contenuti di pagine Web, account utente, informazioni sul profilo degli utenti e stringhe di connessione al database. Nel caso sia supportata l'amministrazione remota, occorre chiedersi come siano protette le interfacce di amministrazione. Le conseguenze di una violazione della protezione in un'interfaccia di amministrazione possono essere gravi, poiché l'autore dell'attacco finisce, in genere, per eseguire operazioni con privilegi amministratore e ha accesso diretto all'intero sito.
Di seguito sono riportati alcuni suggerimenti per migliorare la protezione della gestione della configurazione dell'applicazione Web:
| • | Proteggere le interfacce di amministrazione. |
| • | Proteggere l'archivio di configurazione. |
| • | Mantenere privilegi di amministrazione separati. |
| • | Utilizzare account di servizio e di processo con privilegi minimi. |
È importante che la funzionalità di gestione della configurazione sia accessibile solo a operatori e amministratori autorizzati. Un passaggio chiave consiste nell'imporre criteri di autenticazione rigorosi nelle interfacce di amministrazione, utilizzando, ad esempio, certificati.
Se possibile, limitare o evitare l'uso delle funzioni di amministrazione remota e richiedere agli amministratori di accedere in locale. Se è necessario supportare l'amministrazione remota, utilizzare canali crittografati, ad esempio con tecnologia VPN o SSL, per garantire la riservatezza dei dati passati attraverso le interfacce amministrative. Valutare anche l'ipotesi di limitare l'amministrazione remota ai computer della rete interna utilizzando criteri IPSec, per ridurre ulteriormente il rischio.
I file di configurazione in formato testo, il Registro di sistema e i database sono opzioni comuni di archiviazione dei dati di configurazione dell'applicazione. Se possibile, evitare di utilizzare file di configurazione nello spazio Web dell'applicazione, per impedire che eventuali vulnerabilità di configurazione del server consentano il download di tali file. Qualsiasi sia l'approccio scelto, proteggere l'accesso all'archivio di configurazione, ad esempio utilizzando elenchi di controlli di accesso Windows o autorizzazioni per il database. Evitare, inoltre, di archiviare segreti come le stringhe di connessione al database o le credenziali account in formato non crittografato. Proteggere questi elementi utilizzando la crittografia e, quindi, restringere l'accesso alla chiave del Registro di sistema, al file o alla tabella contenente i dati crittografati.
Se la funzionalità supportata dalle funzioni di gestione della configurazione dell'applicazione varia a seconda del ruolo dell'amministratore, valutare l'ipotesi di autorizzare ciascun ruolo separatamente utilizzando l'autorizzazione basata sui ruoli. La persona responsabile dell'aggiornamento del contenuto statico di un sito non deve, ad esempio, necessariamente essere autorizzata a modificare il limite di credito di un cliente.
Un aspetto importante della configurazione dell'applicazione è rappresentato dagli account di processo utilizzati per eseguire il processo server Web e dagli account di servizio utilizzati per accedere alle risorse e ai sistemi di downstream. Verificare che tali account abbiano un livello di privilegi minimo. Per evitare che un utente malintenzionato, che sia riuscito a ottenere il controllo di un processo, provochi danni ingenti, è necessario che le identità di processo abbiano accesso estremamente limitato al file system e alle altre risorse di sistema.
Le applicazioni che gestiscono informazioni utente riservate quali, ad esempio, numeri di carta di credito, indirizzi e cartelle cliniche devono prevedere meccanismi che consentano di garantire che i dati restino riservati e inalterati. Inoltre, è necessario che i segreti utilizzati dall'implementazione dell'applicazione, quali password e stringhe di connessione al database, siano protetti. La protezione di dati riservati memorizzati in archivi permanenti e passati in rete è una questione piuttosto complessa.
I segreti includono password, stringhe di connessione al database e numeri di carta di credito. Di seguito sono riportati alcuni suggerimenti per migliorare la protezione del meccanismo di gestione dei segreti dell'applicazione Web:
| • | Se possibile, non archiviare i segreti. |
| • | Non memorizzare i segreti nel codice. |
| • | Non archiviare connessioni al database, password o chiavi in formato non crittografato. |
| • | Evitare di archiviare i segreti nel database dell'autorità di protezione locale (LSA). |
| • | Utilizzare DPAPI (Data Protection API) per la crittografia dei segreti. |
Non è possibile archiviare segreti in un software in un modo assolutamente sicuro. Un amministratore, che ha accesso fisico al server, può accedere ai dati. Ad esempio, per verificare che un utente conosca un segreto non è necessario archiviarlo. Per questo tipo di verifica basta memorizzare un valore hash che rappresenti il segreto e quindi calcolare l'hash utilizzando il valore fornito dall'utente.
Non impostare segreti nel codice. Anche se il codice sorgente non è esposto sul server Web, è possibile estrarre costanti di stringa dai file eseguibili compilati. Una vulnerabilità di configurazione potrebbe consentire a un utente malintenzionato di recuperare l'eseguibile.
Evitare di archiviare segreti come stringhe di connessioni al database, password e chiavi in formato non crittografato. Utilizzare la crittografia e memorizzare stringhe crittografate.
Evitare l'uso di LSA, poiché per accedervi l'applicazione richiede privilegi di amministrazione e questo contraddice il principio di protezione base di eseguire l'applicazione con il livello minimo di privilegi. Inoltre, LSA può archiviare segreti in un numero limitato di slot. È consigliabile, invece, utilizzare DPAPI, disponibile in Microsoft Windows® 2000 e nei sistemi operativi successivi.
Per archiviare segreti come stringhe di connessione al database o credenziali di account di servizio, utilizzare DPAPI. Il vantaggio principale di utilizzare DPAPI è che la responsabilità della gestione della chiave di crittografia/decrittografia spetta al sistema di piattaforma e non all'applicazione. La chiave è associata a un account utente Windows o a un computer specifico, a seconda dei flag passati alle funzioni DPAPI.
L'interfaccia DPAPI è più adatta alla crittografia di informazioni che possono essere ricreate manualmente quando le chiavi master vengono perse, a causa, ad esempio, della necessaria reinstallazione del sistema operativo in seguito a danni al server. I dati che non possono essere recuperati, perché non si conosce il valore non crittografato, quali, ad esempio, le informazioni sulle carte di credito dei clienti, richiedono un approccio alternativo che prevede l'uso della tradizione crittografia simmetrica basata sulle chiavi, come Triple DES.
Per ulteriori informazioni sull'uso di DPAPI dalle applicazioni Web, consultare il modulo 10 "Creazione di pagine e controlli ASP.NET protetti".
I dati riservati, come le credenziali di accesso, e le informazioni di livello applicazione, come i numeri di carta di credito e di conto bancario, devono essere protetti. Occorre garantire la riservatezza tramite la crittografia e l'integrità tramite codici di autenticazione dei messaggi (MAC).
Di seguito sono riportati alcuni suggerimenti per migliorare la protezione dei dati utente riservati offerta dall'applicazione Web:
| • | Recuperare i dati riservati su richiesta. |
| • | Crittografare i dati o proteggere il canale di comunicazione. |
| • | Non memorizzare dati riservati in cookie permanenti. |
| • | Non passare dati riservati utilizzando il protocollo HTTP-GET. |
L'approccio consigliato è recuperare i dati riservati su richiesta, in caso di necessità, piuttosto che renderli permanenti o archiviarli in memoria. Recuperare, ad esempio, il segreto crittografato quando è necessario, decrittografarlo, utilizzarlo e quindi cancellare la memoria (variabile) utilizzata per contenere il segreto in testo normale. Se tali operazioni compromettono le prestazioni, valutare le seguenti opzioni:
| • | Memorizzare il segreto crittografato nella cache. |
| • | Memorizzare il segreto in testo normale nella cache. |
Memorizzare il segreto crittografato nella cache
Recuperare il segreto al momento del caricamento dell'applicazione e archiviarlo in formato crittografato in memoria, quindi decrittografarlo quando l'applicazione lo utilizza. Cancellare la copia in testo normale quando non è più necessaria. Questo approccio consente di evitare di accedere all'archivio dati su richiesta.
Memorizzare il segreto in testo normale nella cache
Evitare il sovraccarico sulle prestazioni rappresentato dalla necessità di decrittografare il segreto più volte e archiviarne una copia in testo normale in memoria. Si tratta dell'approccio meno sicuro ma che garantisce prestazioni ottimali. Valutare gli altri approcci prima di giungere alla conclusione che il risultato in termini di prestazioni vale il rischio di protezione associato all'uso del metodo descritto.
Se si inviano dati riservati al client passandoli in rete, crittografarli o proteggere il canale di comunicazione. Un metodo comune è utilizzare SSL per il passaggio di dati tra il client e il server Web. Per proteggere la trasmissione tra i server si sta affermando, invece, l'uso di IPSec. Per proteggere i dati riservati che passano attraverso diversi intermediari, ad esempio messaggi SOAP (Simple Object Access Protocol) di servizi Web, utilizzare la crittografia a livello del messaggio.
Evitare di memorizzare dati riservati in cookie permanenti. Se si memorizzano dati in testo non crittografato, l'utente finale sarà in grado di visualizzarli e modificarli. Se si crittografano i dati, la gestione delle chiavi può rappresentare un problema. Se, ad esempio, la chiave utilizzata per crittografare i dati nel cookie è scaduta ed è stata riciclata, la nuova chiave non potrà decrittografare il cookie permanente passato dal cliente mediante il browser.
È consigliabile evitare di memorizzare dati riservati utilizzando il protocollo HTTP-GET, poiché, per passare i dati, il protocollo utilizza stringhe di query. I dati riservati non possono essere protetti utilizzando stringhe di query e a tali stringhe accede spesso il server.
Le applicazioni Web si basano sul protocollo HTTP senza informazioni sullo stato, quindi la gestione delle sessioni è una responsabilità di livello applicazione. La protezione delle sessioni è fondamentale per la protezione complessiva di un'applicazione.
Di seguito sono riportati alcuni suggerimenti per migliorare la protezione della gestione delle sessioni dell'applicazione Web:
| • | Utilizzare SSL per proteggere i cookie di autenticazione delle sessioni. |
| • | Crittografare il contenuto dei cookie di autenticazione. |
| • | Limitare la durata delle sessioni. |
| • | Proteggere lo stato delle sessioni dall'accesso non autorizzato. |
Non passare cookie di autenticazione su connessioni HTTP. Impostare la proprietà dei cookie protetti all'interno dei cookie di autenticazione, in modo da indicare ai browser di reinviare i cookie al server solo su connessioni HTTPS. Per ulteriori informazioni, consultare il modulo 10 "Creazione di pagine e controlli ASP.NET protetti".
Crittografare i contenuti del cookie anche se si utilizza SSL. In questo modo si evita che un utente malintenzionato possa visualizzare o modificare il cookie se riesce ad acquisirlo con un attacco di script tra i siti. In questo caso, l'autore dell'attacco può ancora utilizzare il cookie per accedere all'applicazione ma solo finché resta valido.
Ridurre la durata delle sessioni per attenuare il rischio di attacchi di riproduzione e dirottamento di sessione. Più breve è la sessione meno sarà il tempo a disposizione di un utente malintenzionato per acquisire un cookie di sessione e utilizzarlo per accedere all'applicazione.
Valutare la modalità di archiviazione dello stato delle sessioni. Per garantire prestazioni ottimali, è possibile archiviare lo stato delle sessioni nello spazio degli indirizzi dell'applicazione Web. Tuttavia, questo approccio prevede un modesto livello di scalabilità e può essere utilizzato solo limitatamente in scenari Web farm, dove non è garantito che le richieste provenienti da uno stesso utente siano gestite dallo stesso server. In tali scenari è richiesto un archivio degli stati esterno, in un server di stato dedicato, o permanente, in un database condiviso. ASP.NET supporta tutte e tre le opzioni indicate.
È consigliabile proteggere il collegamento di rete dall'applicazione Web all'archivio degli stati utilizzando IPSec o SSL, per ridurre il rischio di ascolto e intercettazione di rete non autorizzati. Valutare inoltre come debba essere autenticata l'applicazione Web in base all'archivio degli stati. Se possibile, utilizzare l'autenticazione Windows, per evitare di passare in rete credenziali di autenticazione in formato non crittografato e trarre vantaggio dai criteri account protetti di Windows.
La crittografia, nella sua forma essenziale, garantisce quanto segue:
| • | Privacy (riservatezza). Questo servizio garantisce la riservatezza di un segreto. |
| • | Non ripudio (autenticità). Questo servizio assicura che un utente non possa negare di aver inviato un particolare messaggio. |
| • | Impossibilità di manomissione (integrità). Questo servizio impedisce che i dati vengano alterati. |
| • | Autenticazione. Questo servizio conferma l'identità del mittente di un messaggio. |
Le applicazioni Web spesso utilizzano la crittografia per proteggere i dati negli archivi permanenti o quando vengono trasmessi in rete. Di seguito sono riportati alcuni suggerimenti per migliorare la protezione dell'applicazione Web quando si utilizza la crittografia:
| • | Non sviluppare sistemi di crittografia personalizzati. |
| • | Mantenere i dati non crittografati vicino all'algoritmo. |
| • | Utilizzare l'algoritmo e la dimensione della chiave corretti. |
| • | Proteggere le chiavi di crittografia. |
Gli algoritmi e le routine di crittografia sono notoriamente difficili da sviluppare. È quindi consigliabile utilizzare i collaudati servizi di crittografia forniti dalla piattaforma che include .NET Framework e il sistema operativo sottostante. Non sviluppare implementazioni personalizzate perché forniscono spesso una protezione inadeguata.
Quando si passa testo normale a un algoritmo, non ottenere i dati fino a quando non si è pronti a utilizzarli e archiviarli in forma di un numero limitato di variabili.
È importante accertarsi di scegliere l'algoritmo appropriato al processo e una chiave la cui dimensione sia tale da fornire un grado di protezione adeguato. In genere, più lunghe sono le chiavi, maggiore è la protezione. Nell'elenco seguente sono riepilogati i principali algoritmi insieme alle dimensioni delle chiavi utilizzate da ciascuno di essi:
| • | DES (Data Encryption Standard) - chiave a 64 bit (8 byte) |
| • | TripleDES - chiave a 128 o 192 bit (16 o 24 byte) |
| • | Rijndael - chiavi a 128 – 256 bit (16 – 32 byte) |
| • | RSA - chiavi 384 – 16.384 bit (48 – 2.048 byte) |
Per la crittografia di dati di grandi dimensioni, utilizzare l'algoritmo di crittografia simmetrica TripleDES. Per una crittografia più lenta ma più efficace di dati di grandi dimensioni utilizzare Rijndael. Per crittografare i dati che devono essere memorizzati per brevi periodi di tempo, è possibile utilizzare un algoritmo più veloce ma meno sicuro come DES. Per le firme digitali utilizzare RSA (Rivest, Shamir e Adleman) o DSA (Digital Signature Algorithm). Per l'hashing utilizzare SHA (Secure Hash Algorithm)1.0. Per gli hash con chiavi utilizzare HMAC (Hash-based Message Authentication Code) SHA 1.0.
Una chiave di crittografia è un numero segreto utilizzato come input per i processi di crittografia e decrittografia. Perché i dati crittografati restino sicuri, la chiave deve essere protetta. Se un utente malintenzionato compromette la chiave di crittografia, i dati crittografati non saranno più sicuri.
Di seguito sono riportati alcuni suggerimenti per proteggere le chiavi di crittografia:
| • | Utilizzare DPAPI per evitare la gestione delle chiavi. |
| • | Ruotare le chiavi periodicamente. |
Come è stato illustrato in precedenza, uno dei principali vantaggi dell'uso di DPAPI è che la gestione delle chiavi è affidata al sistema operativo. La chiave che DPAPI utilizza è derivata dalla password associata all'account di processo che richiama le funzioni DPAPI. Utilizzare DPAPI per passare l'onere della gestione delle chiavi al sistema operativo.
In genere, un segreto statico è più facilmente svelabile. Le domande da porsi sono le seguenti: È stato scritto da qualche parte? L'amministratore incaricato della gestione dei segreti ha cambiato posizione o ha lasciato l'azienda? Non utilizzare troppo le chiavi.
Con gli attacchi di manipolazione dei parametri si modificano i dati inviati tra il client e l'applicazione Web. Può trattarsi di dati inviati mediante stringhe di query, campi di modulo, cookie o intestazioni HTTP. Di seguito sono riportati alcuni suggerimenti per proteggere l'applicazione Web dalla manipolazione dei parametri:
| • | Crittografare lo stato dei cookie riservati. |
| • | Verificare che gli utenti non aggirino i controlli. |
| • | Convalidare tutti i valori inviati dal client. |
| • | Non considerare attendibili le informazioni delle intestazioni HTTP. |
I cookie possono contenere dati riservati, come identificatori o informazioni di sessione, utilizzati come parte del processo di autorizzazione lato server. Per proteggere questo tipo di dati dalla manipolazione non autorizzata, crittografare il contenuto del cookie.
Verificare che gli utenti non aggirino i controlli manipolando parametri. I parametri URL possono essere manipolati dagli utenti finali mediante la casella di testo degli indirizzi del browser. Ad esempio, l'URL http://www.<Sito>/<Applicazione>/sessionId=10 include un valore 10 che può essere modificato in un numero casuale per ricevere un output diverso. Verificare tale eventualità nel codice lato server, non nel codice JavaScript lato client, che può essere disabilitato nel browser.
Limitare il numero di campi in cui l'utente può specificare valori e modificare e convalidare tutti i valori provenienti dal client. Se sono presenti valori predefiniti nei campi di modulo, gli utenti possono modificarli e reinviarli all'origine per ricevere risultati diversi. Se possibile, consentire solo valori validi noti. Ad esempio, se nel campo di input deve essere specificata una provincia, consentire solo gli input corrispondenti a un codice postale.
Le intestazioni HTTP vengono inviate all'inizio di richieste e risposte HTTP. È necessario assicurarsi che nessuna scelta di protezione dell'applicazione Web sia basata sulle informazioni incluse nelle intestazioni HTTP, poiché per un utente malintenzionato la manipolazione delle intestazioni è un'operazione piuttosto semplice. Ad esempio, il campo referer dell'intestazione contiene l'URL della pagina Web da cui ha avuto origine la richiesta. Non prendere alcuna decisione di protezione sulla base del valore del campo referer, per controllare, ad esempio, se la richiesta proviene da una pagina generata dall'applicazione Web, poiché questo campo è facilmente manipolabile.
Una gestione sicura delle eccezioni consente di evitare determinati attacchi di tipo Denial of Service a livello applicazione e può essere utilizzata per impedire la restituzione al client di importanti informazioni di sistema che potrebbero essere utili per eventuali utenti malintenzionati. Senza un'adeguata gestione delle eccezioni, informazioni di grande valore per un eventuale utente malintenzionato quali, ad esempio, i dettagli sullo schema di database, le versioni dei sistemi operativi, le tracce dello stack, i nomi e i percorsi file e le stringhe di query SQL possono essere restituite al client.
È buona norma progettare una soluzione di gestione e registrazione delle eccezioni centralizzata e valutare l'ipotesi di inserire hook in tale sistema di gestione per supportare il monitoraggio centralizzato e degli strumenti al fine di agevolare il compito degli amministratori di sistema.
Di seguito sono riportati alcuni suggerimenti per proteggere la gestione delle eccezioni dell'applicazione Web:
| • | Non divulgare informazioni al client. |
| • | Registrare messaggi di errore dettagliati. |
| • | Rilevare le eccezioni. |
In caso di errore, non esporre informazioni che potrebbero portare alla divulgazione di dati. Non esporre, ad esempio, dettagli sulle tracce dello stack che includono nomi di funzioni e numeri di riga nel caso di build di debug (che non devono essere utilizzate nei server di produzione). Restituire invece al client messaggi di errore generici.
Inviare messaggi di errore dettagliati al registro errori. Inviare informazioni minime al consumer del servizio o dell'applicazione, come un messaggio di errore generico e un ID di registro personalizzato, che possano poi essere mappate ai messaggi dettagliati nei registri eventi. Non registrare password o altri dati riservati.
Utilizzare una gestione delle eccezioni strutturata e rilevare le condizioni di eccezione. In questo modo si evita di lasciare l'applicazione in uno stato incoerente che potrebbe portare alla divulgazione di informazioni e si protegge l'applicazione da attacchi di tipo Denial of Service. Decidere come propagare le eccezioni all'interno dell'applicazione e prestare particolare attenzione a cosa accade a livello dei limiti dell'applicazione.
Per ulteriori informazioni sulla progettazione e l'implementazione di una struttura di gestione delle eccezioni per le applicazioni .NET, vedere l'articolo MSDN "Exception Management Architecture Guide", all'indirizzo http://msdn.microsoft.com/library/en-us/dnbda/html/exceptdotnet.asp (in inglese).
È necessario controllare e registrare le attività nei diversi livelli dell'applicazione. Avvalendosi di registri è possibile rilevare le attività di analisi sospette. Questa strategia fornisce spesso indicazioni tempestive per impedire che si verifichi un vero e proprio attacco; inoltre l'uso di registri consente di affrontare il pericolo di ripudio, ovvero di evitare che gli utenti neghino di aver compiuto determinate azioni. I file di registro potrebbero essere necessari in procedimenti legali per provare eventuali illeciti. In genere, il controllo è considerato più autorevole se i controlli vengono generati al momento preciso dell'accesso alla risorsa e dalle stesse routine che vi accedono.
Di seguito sono riportati alcuni suggerimenti per migliorare la protezione dell'applicazione Web:
| • | Controllare e registrare l'accesso nei diversi livelli dell'applicazione. |
| • | Esaminare il flusso di identità. |
| • | Registrare gli eventi chiave. |
| • | Proteggere i file di registro. |
| • | Eseguire il backup e analizzare i file di registro regolarmente. |
Controllare e registrare l'accesso nei diversi livelli dell'applicazione per evitare il pericolo di ripudio. Utilizzare una combinazione di funzionalità di controllo di piattaforma e registrazione a livello applicazione, quali il controllo Windows, IIS e SQL Server.
Esaminare il modo in cui l'applicazione trasmette l'identità del chiamante su più livelli applicativi. Le opzioni di base sono due. È possibile far passare l'identità del chiamante a livello del sistema operativo utilizzando la delega del protocollo Kerberos. Questo consente di utilizzare le funzionalità di controllo del sistema operativo. Lo svantaggio di tale approccio è che incide sulla scalabilità, perché rende impossibile un efficiente pool di connessioni al database a livello intermedio. In alternativa, è possibile trasmettere l'identità del chiamante a livello applicazione e utilizzare identità attendibili per accedere alle risorse di back-end. Con questo approccio è necessario considerare attendibile il livello intermedio ed esiste il rischio di ripudio. È necessario generare itinerari di controllo nel livello intermedio che possano essere correlati a itinerari di controllo back-end. A questo scopo, è necessario verificare che gli orologi dei server siano sincronizzati, sebbene questa operazione sia già eseguita da Microsoft Windows 2000 e Active Directory.
I tipi di eventi che devono essere registrati includono tentativi di accesso riusciti e non riusciti, modifica e recupero di dati, comunicazioni di rete e funzioni amministrative come l'attivazione o la disattivazione della registrazione. I registri devono includere l'ora e la posizione dell'evento, incluso il nome del computer, l'identità dell'utente corrente e del processo che ha avviato l'evento e una descrizione dettagliata dell'evento.
Proteggere i file di registro utilizzando elenchi di controllo di accesso di Windows e limitare l'accesso ai file di registro. In questo modo gli utenti malintenzionati avranno maggiori difficoltà a manomettere tali file per coprire le proprie tracce. Ridurre al minimo il numero di utenti che possono manipolare i file di registro. Autorizzare l'accesso solo ad account estremamente attendibili come quelli amministratore.
La registrazione delle attività è assolutamente inutile se i file di registro non vengono analizzati. I file di registro devono essere periodicamente rimossi dai server di produzione. La frequenza di tale rimozione dipende dal livello di attività dell'applicazione. Il progetto deve tenere in considerazione il modo in cui i file di registro verranno recuperati e spostati in server non in linea per l'analisi. Tutti i protocolli e le porte aggiuntivi aperti sul server Web a questo scopo devono essere bloccati in modo sicuro.
Nella tabella 4.1 sono riepilogate le linee guida di progettazione illustrate nel presente modulo, organizzate per categoria di vulnerabilità dell'applicazione.
Tabella 4.1. Linee guida di progettazione per l'applicazione
| Categoria | Linee guida |
Convalida dell'input | Non considerare l'input attendibile; valutare l'ipotesi di una convalida centralizzata dell'input. |
Autenticazione | Suddividere il sito per aree anonime, identificate e autenticate. Utilizzare password complesse. Supportare periodi di scadenza delle password e disattivazione degli account. Non archiviare credenziali (utilizzare hash unidirezionali con valori salt). Crittografare i canali di comunicazione per proteggere i token di autenticazione. Passare i cookie di autenticazione basata su form solo su connessioni HTTPS. |
Autorizzazione | Utilizzare account con privilegi minimi. Prendere in considerazione la granularità dell'autorizzazione. Imporre la separazione dei privilegi. Restringere l'accesso utente alle risorse di sistema. |
Gestione della configurazione | Utilizzare account di servizio e di processo con privilegi minimi. Non archiviare credenziali in formato non crittografato. Utilizzare procedure rigorose di autorizzazione e autenticazione sulle interfacce di amministrazione. Non utilizzare LSA. Proteggere il canale di comunicazione per l'amministrazione remota. Evitare di archiviare dati riservati nello spazio Web. |
Dati sensibili | Evitare di archiviare segreti. Crittografare i dati riservati in rete. Proteggere il canale di comunicazione. Fornire controlli di accesso rigorosi sugli archivi di dati riservati. Non memorizzare dati riservati in cookie permanenti. Non passare dati riservati utilizzando il protocollo HTTP-GET. |
Gestione delle sessioni | Limitare la durata delle sessioni. Proteggere il canale. Crittografare il contenuto dei cookie di autenticazione. Proteggere lo stato delle sessioni dall'accesso non autorizzato. |
Crittografia | Non sviluppare sistemi di crittografia personalizzati. Utilizzare funzionalità di piattaforma collaudate. Mantenere i dati non crittografati vicino all'algoritmo. Utilizzare l'algoritmo corretto e una chiave di dimensione appropriata. Evitare la gestione delle chiavi (utilizzare DPAPI). Ruotare le chiavi periodicamente. Archiviare le chiavi in una posizione con restrizioni. |
Manipolazione dei parametri | Crittografare lo stato dei cookie riservati. Non considerare attendibili i campi manipolabili dal client (stringhe di query, campi di modulo, cookie o intestazioni HTTP). Convalidare tutti i valori inviati dal client. |
Gestione delle eccezioni | Utilizzare una gestione delle eccezioni strutturata. Non rivelare dettagli di implementazione dell'applicazione riservati. Non registrare dati riservati come le password. Prendere in considerazione una struttura di gestione delle eccezioni centralizzata. |
Controllo e registrazione | Identificare i comportamenti dannosi. Imparare a riconoscere quale sia il traffico valido. Controllare e registrare le attività in tutti i livelli dell'applicazione. Proteggere l'accesso ai file registro. Eseguire il backup e analizzare i file di registro regolarmente. |
L'orientamento alla protezione deve caratterizzare ogni fase del ciclo di vita di sviluppo del prodotto e deve rappresentare un punto focale della progettazione dell'applicazione. Prestare particolare attenzione alla progettazione di una solida strategia di autenticazione e autorizzazione. È importante ricordare che la maggior parte degli attacchi a livello applicazione si basa su dati di input opportunamente alterati e su una convalida inadeguata degli stessi. Le informazioni fornite nel presente modulo dovrebbero consentire di affrontare questi ed altri aspetti chiave della progettazione e della creazione di applicazioni protette.
Per ulteriori informazioni, vedere le risorse seguenti:
| • | La guida corrente è il secondo volume di una serie il cui intento è quello di supportare i clienti nel miglioramento della protezione delle applicazioni Web. Per ulteriori informazioni sull'architettura, la progettazione, la creazione e la configurazione di sistemi di autenticazione e autorizzazione e di comunicazioni protette nei diversi livelli di un'applicazione Web distribuita, vedere "Microsoft patterns & practices Volume I, Building Secure ASP.NET Web Applications: Authentication, Authorization, and Secure Communication" all'indirizzo http://msdn.microsoft.com/library/en-us/dnnetsec/html/secnetlpMSDN.asp (in inglese). |
| • | L'articolo MSDN "Security Models for ASP.NET Applications" all'indirizzo http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetch02.asp?frame=true (in inglese). |
| • | L'articolo MSDN "Designing Authentication and Authorization" all'indirizzo http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnnetsec/html/SecNetch03.asp?frame=true (in inglese). |
| • | "Elenco di controllo: Analisi dell'architettura e della progettazione" nella sezione "Elenchi di controllo" di questa guida. |