Documenti di Didattica
Documenti di Professioni
Documenti di Cultura
com
13
Condizioni di gara
205
206 24 peccati capitali della sicurezza del software
RIFERIMENTI CWE
Il riferimento CWE a questo problema è molto diretto, ma ci sono diversi nodi figli che
illustrano l'entità del problema e il numero di modi in cui può emergere.
Alcuni di questi problemi non sono comuni e non sono trattati in questo capitolo, ad esempio, le revoche
di certificati tendono ad essere rare nella maggior parte degli scenari di utilizzo e, se non è nel tuo scenario,
c'è una soluzione chiara, che consiste nell'insistere nel controllare il CRL (lista di revoca dei certificati), oltre a
fissare un limite di tempo ridotto per quanto tempo un elenco potrebbe essere valido.
Peccato 13: Race Condition 207
LINGUE INTERESSATE
Come per molti problemi, è possibile creare race condition in qualsiasi lingua. Un
linguaggio di alto livello che non supporta thread o processi biforcuti non sarà vulnerabile
ad alcuni tipi di race condition, ma le prestazioni relativamente lente di questi linguaggi di
alto livello li rendono più suscettibili agli attacchi in base al tempo di verifica. d'uso
(TOCTOU).
IL PECCATO SPIEGATO
L'errore di programmazione principale che porta a condizioni di gara è fare qualcosa che
qualsiasi buon testo di programmazione ti dirà di non fare, ovvero programmare con effetti
collaterali. Se una funzione non è rientrante e due thread sono contemporaneamente nella
funzione, allora le cose si romperanno. Come probabilmente avrai già capito, quasi ogni tipo di
errore di programmazione, data la sfortuna da parte tua e lo sforzo da parte dell'attaccante, può
essere trasformato in un exploit. Ecco un'illustrazione C++:
Potresti pensare che le tue probabilità che due thread siano contemporaneamente nella funzione
siano basse, ma sotto questa piccolissima quantità di codice C++ si nascondono molte istruzioni. Tutto
ciò che serve è che un thread superi il controllo se l'elenco è vuoto appena prima che un altro chiami
pop_front() sull'ultimo elemento. Come diceva Clint Eastwood nel filmSporco Harry: “Mi sento
fortunato?” Un codice molto simile a questo ha impedito a un ISP di servire i propri clienti per la
maggior parte di un giorno.
Un'altra incarnazione del problema sono le condizioni di corsa del segnale. Questo attacco è
stato descritto pubblicamente per la prima volta in "Delivering Signals for Fun and Profit:
Understanding, Exploiting, and Preventing Signal-Handling Related Vulnerabilities" di Michal
Zalewski, disponibile all'indirizzo http://lcamtuf.coredump.cx/signals.txt. Il problema qui è che
molte applicazioni UNIX non si aspettano di incontrare i tipi di problemi che vedresti nelle app
multithread.
208 24 peccati capitali della sicurezza del software
Codice peccaminoso
Anche se sceglieremo C, questo codice potrebbe essere scritto in qualsiasi lingua e c'è ben poco
che sia specifico della lingua al riguardo. Questo è un errore che è una combinazione
Peccato 13: Race Condition 209
carattere*tmp;
FILE* pTempFile;
Sembra abbastanza innocuo, ma l'attaccante può, in generale, indovinare quale sarà il prossimo
nome file. In un'esecuzione di test sul sistema dell'autore, chiamate ripetute hanno generato file
denominati MyApp1, MyApp2, MyApp3 e così via. Se i file vengono creati in un'area in cui l'aggressore
può scrivere, l'aggressore potrebbe essere in grado di creare in anticipo il file temporaneo,
eventualmente sostituendolo con un collegamento. Se l'applicazione sta creando diversi file
temporanei, l'attacco diventa molto più semplice.
Peccati correlati
Ci sono diversi problemi correlati trattati qui. Il peccato principale è l'incapacità di scrivere codice che
gestisca correttamente la concorrenza. I peccati correlati non utilizzano controlli di accesso adeguati,
trattati in Sin 12, e il mancato utilizzo di numeri casuali generati correttamente, trattati in Sin 18. Quasi
tutte le race condition dei file temporanei sono solo problemi perché sono stati utilizzati controlli di
accesso impropri, che è tipicamente aggravato da versioni precedenti del sistema operativo che non
forniscono directory temporanee adeguatamente protette per utente. La maggior parte dei sistemi
operativi attuali fornisce spazio scratch per utente e, anche se non viene fornito, è sempre possibile per
lo sviluppatore dell'applicazione creare spazio scratch sotto la home directory di un utente.
La mancata generazione corretta di numeri casuali entra in gioco quando è necessario creare
un file, una directory o un altro oggetto univoco in un'area pubblica. Se usi un generatore di
numeri pseudo-casuali o, peggio ancora, incrementi prevedibilmente il nome, allora l'attaccante
può spesso indovinare cosa creerai dopo, che spesso è il primo passo sulla tua strada verso la
rovina.
Si noti che molte delle funzioni per i nomi di file temporanei fornite dal sistema sono
garantite per creare nomi di file univoci, non nomi di file imprevedibili. Se stai creando file o
directory temporanei in un luogo pubblico, potresti voler utilizzare le funzioni di
generazione di numeri casuali appropriate per creare i nomi. Un approccio è documentato
nel capitolo 23 di Scrittura di codice sicuro, seconda edizionedi Michael Howard e David C.
LeBlanc (Microsoft Press, 2002), e anche se il codice di esempio è per Windows, l'approccio è
molto portabile.
210 24 peccati capitali della sicurezza del software
- Più di un thread o processo deve scrivere sulla stessa risorsa. La risorsa potrebbe essere la
memoria condivisa, il file system (ad esempio, da più applicazioni Web che manipolano i dati
in una directory condivisa), altri archivi di dati come il registro di Windows o persino un
database. Potrebbe anche essere una variabile condivisa!
- Creazione di file o directory in aree comuni, come directory per file temporanei
(come /tmp e /usr/tmp in sistemi simili a UNIX).
- Gestori di segnali.
crea nuovi nomi di file utilizzando input veramente casuali e riprova a creare il file. Se usi caratteri
correttamente randomizzati (facendo attenzione a mappare solo caratteri legali per il tuo file system),
le possibilità di doverlo chiamare due volte saranno basse. Sfortunatamente, la chiamata fopen() di C
non ha un modo standard per richiedere O_EXCL, quindi è necessario utilizzare open() e quindi
convertire il valore restituito in un valore FILE*.
Su un sistema Microsoft, non solo le chiamate API Windows native come CreateFile sono più
flessibili, ma tendono anche a funzionare meglio. Inoltre, è possibile stabilire controlli di accesso
al file (o altro oggetto) in modo atomico al momento della creazione, il che elimina ancora più
possibilità di malizia.
Non dipendere mai solo da routine come mktemp(3) per creare un "nuovo" nome file; dopo
l'esecuzione di mktemp(3), un utente malintenzionato potrebbe aver già creato un file con lo stesso
nome. La shell UNIX non ha un'operazione integrata per farlo, quindi qualsiasi operazione comels > /
tmp/list.$$è una condizione di gara in attesa di accadere; gli utenti di shell dovrebbero invece usare
mktemp(1). Alcuni degli strumenti di analisi del codice stanno iniziando a essere in grado di trovare
potenziali race condition e deadlock nel codice C/C++ durante l'analisi statica.
ESEMPIO PECCATI
Le seguenti voci in Common Vulnerabilities and Exposures (CVE) su http://
cve.mitre.org/ sono esempi di race condition.
212 24 peccati capitali della sicurezza del software
CVE-2008-0379
Dalla descrizione CVE:
La race condition nel controllo Enterprise Tree ActiveX (EnterpriseControls.dll 11.5.0.313) in Crystal
Reports XI Release 2 consente agli aggressori remoti di causare un Denial of Service (arresto
anomalo) ed eventualmente eseguire codice arbitrario tramite il metodo SelectedSession, che
attiva un overflow del buffer.
CVE-2008-2958
Dalla descrizione IBM/ISS:
CVE-2001-1349
Dalla descrizione CVE:
Sendmail prima della 8.11.4 e 8.12.0 prima della 8.12.0.Beta10, consente agli utenti locali di causare un
denial of service e possibilmente corrompere l'heap e ottenere privilegi tramite race condition nei
gestori di segnali.
Questa è la condizione di corsa del segnale documentata nell'articolo di Zalewski sulla consegna dei
segnali, a cui abbiamo fatto riferimento in precedenza. La condizione sfruttabile si verifica a causa di un
double-free su una variabile globale che viene colpita al rientro nella routine di gestione del segnale. Sebbene
né l'avviso di Sendmail, né il database delle vulnerabilità di SecurityFocus facciano riferimento a codice exploit
disponibile pubblicamente, è interessante notare che esiste un collegamento (morto) al codice exploit nel
documento originale.
CAN-2003-1073
Dalla descrizione CVE:
Una race condition nel comando at per Solaris da 2.6 a 9 consente agli utenti locali di eliminare file
arbitrari tramite l'argomento -r con sequenze .. (punto punto) nel nome del processo, modificando quindi
la struttura della directory dopo aver verificato le autorizzazioni per eliminare il file e prima che la
cancellazione avvenga effettivamente.
Peccato 13: Race Condition 213
CVE-2000-0849
Dalla descrizione CVE:
La condizione di competizione nel server Microsoft Windows Media consente agli aggressori remoti
di causare un Denial of Service nel servizio Unicast di Windows Media tramite una richiesta errata,
nota anche come vulnerabilità "Unicast Service Race Condition".
FASI DI RISCATTO
Uno dei primi passi verso la redenzione è capire come scrivere correttamente il codice rientrante.
Anche se non pensi che l'applicazione verrà eseguita in un ambiente con thread, se le persone provano
a eseguire il porting dell'applicazione o a superare i blocchi dell'applicazione utilizzando più thread, lo
apprezzeranno quando non programmi con effetti collaterali. Una considerazione sulla portabilità è
che Windows non implementa correttamente fork(), la creazione di nuovi processi in Windows è molto
costosa e la creazione di nuovi thread è molto economica.
Mentre la scelta di utilizzare processi o thread varia a seconda del sistema
operativo scelto e dell'applicazione, il codice che non dipende dagli effetti collaterali
sarà più portabile e molto meno soggetto a race condition.
Se si sta tentando di gestire contesti di esecuzione simultanea, tramite processi o thread
biforcuti, è necessario proteggersi attentamente sia dalla mancanza di blocco delle risorse
condivise sia dal blocco errato delle risorse. Questo argomento è stato trattato in modo molto
più dettagliato altrove, quindi lo tratteremo solo brevemente qui. Cose da considerare:
- Se il tuo codice genera un'eccezione non gestita mentre mantieni un blocco, bloccherai qualsiasi
altro codice che richiede il blocco. Un modo per uscirne è trasformare l'acquisizione e il rilascio
del blocco in un oggetto C++ in modo che quando lo stack si svolge, il distruttore rilascerà il
blocco. Tieni presente che potresti lasciare la risorsa bloccata in uno stato instabile; in alcuni casi,
potrebbe essere preferibile eseguire un deadlock piuttosto che continuare in uno stato indefinito.
- Acquisisci sempre più blocchi nello stesso ordine e rilasciali nell'ordine opposto
rispetto a come sono stati acquisiti. Se pensi di aver bisogno di più serrature per fare
qualcosa, pensaci ancora un po'. Un design più elegante può risolvere il problema
con minore complessità.
214 24 peccati capitali della sicurezza del software
- Fai il meno possibile mentre tieni un lucchetto. Per contraddire il consiglio del punto
elenco precedente, a volte più blocchi possono consentire di utilizzare un buon livello di
granularità e ridurre effettivamente la possibilità di un deadlock e migliorare
sostanzialmente le prestazioni dell'applicazione. Questa è un'arte, non una scienza.
Progetta attentamente e fatti consigliare da altri sviluppatori.
- Non dipendere mai da una chiamata di sistema per completare l'esecuzione prima che un'altra
applicazione o thread possa essere eseguita. Le chiamate di sistema possono variare da migliaia a
milioni di istruzioni. Dal momento che è sbagliato aspettarsi che una chiamata di sistema venga
completata, non iniziare nemmeno a pensare che due chiamate di sistema vengano completate
insieme.
Se stai eseguendo un gestore di segnali o un gestore di eccezioni, l'unica cosa veramente sicura da fare
potrebbe essere chiamare exit(). Il miglior consiglio che abbiamo visto sull'argomento è tratto dall'articolo di
Michal Zalewski, "Fornire segnali per divertimento e profitto: comprensione, sfruttamento e prevenzione delle
vulnerabilità correlate alla gestione dei segnali":
- Usa solo chiamate lib rientranti sicure nei gestori di segnali. Ciò richiede importanti
riscritture di numerosi programmi. Un'altra mezza soluzione consiste nell'implementare
un wrapper attorno a ogni libcall insicuro utilizzato, controllando uno speciale flag globale
per evitare il rientro.
- Blocca l'invio del segnale durante tutte le operazioni non atomiche e/o costruisci gestori di
segnale in un modo che non farebbe affidamento sullo stato interno del programma (ad
esempio, impostazione incondizionata di un flag specifico e nient'altro).
Per affrontare i problemi di TOCTOU, una delle migliori difese è creare file in luoghi in cui gli
utenti ordinari non hanno accesso in scrittura. Nel caso delle directory, potresti non avere
sempre questa opzione. Quando si programma per piattaforme Windows, ricordare che un
descrittore di sicurezza può essere allegato a un file (o qualsiasi altro oggetto) al momento della
creazione. Fornire i controlli di accesso al momento della creazione elimina le race condition tra
la creazione e l'applicazione dei controlli di accesso. Per evitare race condition tra il controllo
dell'esistenza di un oggetto e la creazione di uno nuovo, sono disponibili un paio di opzioni, a
seconda del tipo di oggetto.
L'opzione migliore, che può essere utilizzata con i file, consiste nello specificare il flag CREATE_NEW
nell'API CreateFile. Se il file esiste, la chiamata avrà esito negativo. La creazione di directory è più semplice:
tutte le chiamate a CreateDirectory falliranno se la directory esiste già. Anche così, c'è un'opportunità per i
problemi. Diciamo che hai inserito la tua app in C:\Program Files\MyApp, ma un utente malintenzionato ha già
creato la directory. L'attaccante avrà ora il controllo completo dell'accesso alla directory, che include il diritto
di eliminare i file all'interno della directory, anche se il file stesso non concede l'accesso all'eliminazione a
quell'utente. Diversi altri tipi di oggetto non consentono il passaggio di un parametro per determinare la
semantica create new rispetto a open always e queste API avranno esito positivo, ma restituiranno
ERROR_ALREADY_EXISTS a GetLastError. Il corretto
Peccato 13: Race Condition 215
modo per affrontare questo problema se vuoi assicurarti di non aprire un oggetto esistente è scrivere
codice come questo:
if(hMutex == NULL)
restituire falso;
if(GetUltimoErrore() == ERRORE_GIA_ESISTENTE) {
CloseHandle(hMutex);
restituire falso;
}
ALTRE RISORSE
- “La contesa delle risorse può essere usata contro di te" di David Wheeler:
www-106.ibm.com/developerworks/linux/library/
l-sprace.html?ca=dgr-lnxw07RACE
- Argomenti di ricerca RAZOR: http://razor.bindview.com/
publish/papers/signals.txt
- “Fornire segnali per divertimento e profitto: comprensione, sfruttamento e
prevenzione delle vulnerabilità correlate alla gestione dei segnali” di Michal
Zalewski: www.bindview.com/Services/Razor/Papers/2001/signals.cfm.
RIEPILOGO
- Farescrivere un codice che non dipenda dagli effetti collaterali.
217
218 24 peccati capitali della sicurezza del software
È essenziale che l'interfaccia umana sia progettata per la facilità d'uso, in modo che gli utenti applichino
regolarmente e automaticamente i meccanismi di protezione in modo corretto. Inoltre, nella misura in cui
l'immagine mentale dell'utente dei suoi obiettivi di protezione corrisponde ai meccanismi che deve utilizzare, gli
errori saranno ridotti al minimo. Se deve tradurre la sua immagine dei suoi bisogni di protezione in un
linguaggio di specificazione radicalmente diverso, commetterà degli errori.
Nel novembre 2000, Scott Culp, allora ingegnere presso il Microsoft Security Response Center
(MSRC), ha redatto le 10 leggi immutabili dell'amministrazione della sicurezza. La seconda legge
è:
RIFERIMENTI CWE
C'è solo un riferimento nel dizionario Common Weakness Enumeration:
Sebbene il titolo sia accurato, offre davvero pochissime informazioni sulla debolezza, quindi il
lettore è invitato a leggere le informazioni più approfondite sul sito Web di CWE.
LINGUE INTERESSATE
Questo non è un problema specifico della lingua; è un problema architettonico o di design!
IL PECCATO SPIEGATO
A prima vista, l'usabilità non sembra essere scienza missilistica. Tutti sono utenti e tutti più
o meno sanno cosa è facile da usare per loro. C'è un “non riesco a vedere la foresta
Peccato 14: Povera Usabilità
219
per gli alberi” problema qui, però. I progettisti di software spesso presumono implicitamente che
qualunque cosa trovino utilizzabile, altre persone lo troveranno utilizzabile. Il primo principio per la
creazione di sistemi utilizzabili e sicuri è che "i progettisti non sono utenti". Parleremo di come agire in
base a tale principio nella sezione "Fasi di rimborso".
Allo stesso modo, i designer spesso non sono in sintonia con il livello di fastidio dei loro
utenti. Ad esempio, potresti avere un'applicazione basata sul Web che richiede un nome
utente e una password per ogni connessione. Questo è più sicuro che consentire un
qualche tipo di gestione delle password, in cui vengono ricordate le credenziali dell'utente.
Tuttavia, i tuoi utenti potrebbero trovarlo intollerabile e scegliere un'applicazione in cui i
progettisti non hanno mai fatto un buon lavoro considerando la sicurezza. In seguito a ciò, il
secondo principio per la creazione di sistemi utilizzabili e sicuri è che "la sicurezza non è
(quasi) mai la priorità dell'utente". Ciò che intendiamo con questo è che tutti gli utenti
diranno di volere la sicurezza, ma saranno disposti a rinunciarvi in un attimo se si frappone
a ciò che stanno facendo. Questo è anche il fenomeno che porta le persone a fare clic sulle
finestre di dialogo di sicurezza senza leggerle,
Abbiamo visto questo effetto in Windows Vista; Microsoft ha fatto un ottimo lavoro nel migliorare
notevolmente la sicurezza di Windows, ma gli utenti si sono concentrati solo su un aspetto relativo alla
sicurezza che li ha infastiditi: i prompt UAC (User Account Control) che richiedevano il consenso
dell'utente prima che eseguisse operazioni potenzialmente sensibili. Microsoft ha affrontato bene
questo problema in Windows 7 riducendo drasticamente il numero di prompt e consentendo all'utente
di configurare la quantità di prompt che deve verificarsi.
Dato che la sicurezza non è la priorità dell'utente, dovresti aspettarti che se l'applicazione non è sicura per
impostazione predefinita, l'utente non capirà come renderla sicura. Se l'utente deve premere un interruttore
per ottenere funzionalità di sicurezza, non accadrà. Allo stesso modo, non aspettarti di poter insegnare agli
utenti a essere sicuri istruendoli, nei tuoi manuali o in linea con la tua applicazione. Anche se questo potrebbe
essere un modo semplice per rinunciare alla responsabilità della sicurezza e spostarla sull'utente, non rende il
mondo un posto più sicuro. Quindi ricorda questo: gli amministratori non vogliono modificare le impostazioni
per essere più sicuri e gli utenti normali non hanno idea di come modificare le impostazioni.
Un altro problema comune è che, quando la sicurezza incontra gli utenti, i progettisti spesso
non riescono a rendere le cose ovvie e facili. Ciò lascia gli utenti frustrati e spesso cercheranno
modi per ingannare il sistema per evitare tali frustrazioni. Ad esempio, supponiamo che, in nome
di un'elevata sicurezza, imposti requisiti rigorosi su una password, come un minimo di otto
caratteri con almeno un carattere non alfanumerico, e che la password non sia ovviamente
basata su una parola del dizionario. Che cosa accadrà? Alcuni utenti dovranno provare 20
password prima di ottenerne una accettata dal sistema. Quindi, lo dimenticheranno o lo
scriveranno sotto le loro tastiere. Questo tipo di frustrazione può allontanare i tuoi utenti, in
particolare se rendi la reimpostazione della password anche lontanamente difficile.
Gli utenti finali e gli amministratori hanno esigenze diverse quando si tratta di sicurezza e
pochissimi software offrono la sicurezza di cui gli utenti hanno bisogno. Gli amministratori
vogliono assicurarsi di poter gestire i sistemi informatici sotto il loro diretto controllo e i
consumatori vogliono essere al sicuro online. A tal fine, gli amministratori desiderano un facile
accesso ai dati critici che consenta loro di prendere le giuste decisioni in materia di sicurezza. Ma
i consumatori sono diversi: in realtà non prendono buone decisioni sulla sicurezza,
indipendentemente dalla quantità di informazioni che metti loro davanti. In effetti, potremmo
sostenere che per la maggior parte degli utenti non tecnici, meno informazioni tecniche sono le
migliori, ne parleremo un po' di più tra un momento. Non è perché sono stupidi; loro non sono.
(E per favore non chiamare i tuoi utenti "lusers"; queste persone direttamente o indirettamente ti
aiutano a pagare le bollette.
Un aspetto dell'usabilità spesso trascurato è il concetto di usabilità aziendale. Immagina che il tuo
compito sia mantenere 10.000 sistemi che eseguono il tuo software in modo corretto e sicuro. Nessuno
ti aiuterà in questo compito. Molte persone hanno lavori che richiedono loro di amministrare un gran
numero di sistemi e queste persone influiscono sulle decisioni di acquisto, quindi vale la pena essere
gentili con loro.
Ti consigliamo di pensare alla creazione di modi centralizzati per controllare le impostazioni sui sistemi
client, nonché modi per controllare gli elementi di configurazione relativi alla sicurezza. Se devi accedere a
ognuno di quei 10.000 sistemi, sarà una lunga settimana!
- Troppi messaggiAlla fine sia gli amministratori che gli utenti faranno semplicemente clic
sui pulsanti "OK" o "Sì" di fronte a troppi messaggi o disattiveranno la sicurezza del
prodotto in modo che le finestre di dialogo "scompariranno".
Ricorda, le persone non esperte di computer prendono decisioni sbagliate sulla fiducia nella sicurezza.
Peccato 14: Povera Usabilità
221
Peccati correlati
Uno dei luoghi in cui la sicurezza e l'usabilità sono più in contrasto tende ad essere nei sistemi di
autenticazione, in particolare nei sistemi di password. Anche quando stai cercando di costruire un
sistema di password sicure (cercando di evitare i problemi di Sin 19), puoi vanificare i tuoi stessi
obiettivi se non consideri l'usabilità.
Ciò non significa che non puoi fare nulla durante il controllo del codice. Significa solo che non
consigliamo di utilizzare la revisione del codice invece di eseguire i test appropriati.
Quando cerchi problemi di usabilità che incidono sulla sicurezza, ti consigliamo di
fare quanto segue:
- Segui il codice dell'interfaccia utente finché non trovi le opzioni di sicurezza.Che cosa è attivato e disattivato per impostazione
predefinita? Se il codice non è sicuro per impostazione predefinita, probabilmente c'è un problema. Potrebbe anche essere
- Guarda il sistema di autenticazione.Se l'utente non può autenticare correttamente l'altro lato
di una connessione, esiste comunque un'opzione per accettare la connessione?
Naturalmente, a questo punto l'utente non ha idea di chi si trovi all'altro capo della
connessione. Un buon esempio è una connessione SSL, in cui il software dell'utente si
connette a un server, ma il nome nel certificato dice che il nome del server è qualcos'altro e la
maggior parte degli utenti non se ne accorgerà mai. (Questo è spiegato brevemente.)
222 24 peccati capitali della sicurezza del software
Un'altra cosa che potresti guardare qui è se esiste un modo ovvio per reimpostare una password.
In tal caso, il meccanismo può essere utilizzato per negare il servizio? Coinvolge gli esseri umani nel
ciclo che potrebbe essere suscettibile di ingegneria sociale?
ESEMPIO PECCATI
Sfortunatamente, non si trovano molti esempi di problemi di usabilità nei bollettini sulla sicurezza. Ciò
è principalmente dovuto al fatto che alle persone piace trasferire la responsabilità di tali problemi
all'utente finale, invece di dare la colpa al software. È più facile per i fornitori passare la responsabilità
all'utente piuttosto che ammettere di mettere a rischio gli utenti.
Tuttavia, ecco un paio dei nostri esempi preferiti del problema.
La maggior parte degli utenti guarderà questo e penserà: "Che diamine significa?" A
loro non importerà, ma vorranno solo accedere al sito web. Faranno clic sul pulsante Sì
senza fare alcuno sforzo per capire il problema. Gli utenti rari, la cui curiosità ha la meglio
su di loro, sceglieranno di fare clic sul pulsante Visualizza certificato e quindi probabilmente
non sapranno cosa dovrebbero cercare.
Per fortuna, questo problema è stato risolto in Internet Explorer 8.0 e versioni successive: la finestra di
dialogo è sparita! Esamineremo questo particolare problema nella sezione "Fasi di rimborso".
Peccato 14: Povera Usabilità
223
Figura 14-1.Finestra di dialogo di Internet Explorer 6.0 durante l'esplorazione di un sito con un certificato autofirmato
Questa finestra di dialogo è pessima perché è totalmente inutile sia per i non geek che per gli
amministratori. Per la persona non crittografata (la maggior parte del pianeta), questo dialogo non significa
assolutamente nulla. E per l'amministratore, i due valori hash sono inutili a meno che tu non sia disposto a
telefonare alla persona o all'azienda che ha creato il certificato e chiedere loro di recitarti gli hash SHA-1 e
MD5 per conferma.
Per fortuna, questo è stato risolto in Internet Explorer 5.0 e versioni successive con una finestra di dialogo
molto più appropriata.
FASI DI RISCATTO
Esistono sicuramente diversi principi di base che è possibile applicare in fase di progettazione
che tenderanno a produrre sistemi più utilizzabili e più sicuri. Esamineremo questi principi qui,
ma ricorda che la tecnica più efficace per combattere questi problemi è il test di usabilità, non la
tua intuizione.
Quando gli utenti sono coinvolti, rendi l'interfaccia utente semplice e chiara
Come discutiamo in questo capitolo, gli utenti dovrebbero essere protetti dall'affrontare la maggior parte dei
problemi di sicurezza. Ma, quando ciò non è possibile (ad esempio, quando è necessario che gli utenti
scelgano o inseriscano password), è necessario comunicare chiaramente con loro, sia per incoraggiare un
comportamento sicuro sia per evitare di frustrarli!
Ad esempio, ripensa a quando abbiamo discusso di come "la sicurezza non è (quasi) mai la
priorità dell'utente". Abbiamo fornito l'esempio di un sistema di password, in cui l'utente deve
fare numerosi tentativi con una password fino a trovarne una che il sistema accetterà.
La nostra preferenza personale è di non imporre troppe restrizioni sulle password, perché in
tal caso le persone tendono a scrivere o dimenticare le proprie password. Ma per quelle
restrizioni che scegli, è molto meglio chiarirle in anticipo. Indica i tuoi requisiti per la password
proprio accanto al campo della password nel modo più semplice possibile. Hai bisogno di un
minimo di otto lettere e un carattere che non sia una lettera? Se lo fai, allora dillo!
Allo stesso tempo, evita di dare all'utente opzioni e scelte eccessive. Questo non solo può indurre
l'utente a scegliere una configurazione meno sicura, ma può anche rendere l'interoperabilità un
problema. Ad esempio, non è necessario supportare ogni suite di crittografia. Un singolo forte che
utilizza l'Advanced Encryption Standard (AES) è abbastanza buono. Mantienilo semplice! La semplicità è
tua amica quando si tratta di sicurezza.
Peccato 14: Povera Usabilità
225
Dovresti anche evitare di coinvolgere l'utente nelle decisioni sulla fiducia. Ad esempio, nella sezione
"Example Sins", abbiamo parlato della convalida del certificato SSL/TLS nei browser Web (in particolare,
quando si utilizza il protocollo HTTPS). Quando la convalida fallisce, l'utente di solito riceve una strana finestra
di dialogo e gli viene chiesto di prendere una decisione di fiducia, una decisione che l'utente generalmente
non è qualificato a prendere.
Cosa dovrebbe essere fatto? L'approccio migliore sarebbe quello di trattare qualsiasi errore nella convalida del certificato come se il sito Web fosse inattivo, e
questo è esattamente ciò che fa Internet Explorer 8. Ciò sposta l'onere di assicurarsi che il certificato sia a posto dall'utente finale al server Web e al proprietario del
certificato, a cui appartiene. In questo scenario, agli utenti non viene chiesto di effettuare chiamate di giudizio tecnico. Se gli utenti non possono accedere al sito a
causa di errori del certificato, non è diverso dal fatto che il sito sia legittimamente inattivo. Ovviamente, devi bilanciare questo e consentire agli utenti di navigare sul
sito se lo desiderano, ma non dopo aver letto un sacco di goo che non capiscono. Questo tipo di interfaccia utente ha l'effetto collaterale di esercitare pressioni sulle
persone del server Web affinché facciano la cosa giusta. In questo momento gli operatori del sito web sanno che possono combinare nomi di certificati e nomi di URL
perché, per impostazione predefinita, nessun browser fallirà la connessione. Se questo cambiasse e il software del client web fallisse sempre la connessione, gli
operatori del server web dovrebbero fare la cosa giusta. È il classico scenario della gallina e dell'uovo. Questa tecnica dovrebbe essere utilizzata anche per le persone
che non vogliono collegarsi a un'infrastruttura a chiave pubblica (PKI) preesistente. Queste persone creeranno i propri certificati, senza alcuna base per fidarsi di quei
certificati. Tali certificati non dovrebbero funzionare a meno che non vengano prima installati come certificati attendibili (radice). gli operatori del server web
dovrebbero fare la cosa giusta. È il classico scenario della gallina e dell'uovo. Questa tecnica dovrebbe essere utilizzata anche per le persone che non vogliono
collegarsi a un'infrastruttura a chiave pubblica (PKI) preesistente. Queste persone creeranno i propri certificati, senza alcuna base per fidarsi di quei certificati. Tali
certificati non dovrebbero funzionare a meno che non vengano prima installati come certificati attendibili (radice). gli operatori del server web dovrebbero fare la
cosa giusta. È il classico scenario della gallina e dell'uovo. Questa tecnica dovrebbe essere utilizzata anche per le persone che non vogliono collegarsi a
un'infrastruttura a chiave pubblica (PKI) preesistente. Queste persone creeranno i propri certificati, senza alcuna base per fidarsi di quei certificati. Tali certificati non
dovrebbero funzionare a meno che non vengano prima installati come certificati attendibili (radice).
- Il cento per cento dei partecipanti ha notato quando un sito Web aveva o meno una
barra degli indirizzi URL verde.
- Il novantatre percento dei partecipanti preferisce fare acquisti su siti che hanno la barra degli
indirizzi EV verde.
- Il novantasette percento dei partecipanti condividerebbe i dati della propria carta di credito con siti
che visualizzano la barra degli indirizzi EV verde.
le sequenze sono! Lo stesso vale se è necessario informare l'utente di un effettivo evento rilevante per la
sicurezza che si è verificato ma non è direttamente collegato alle azioni dell'utente.
Quando si informa l'utente sui rischi, è una cattiva idea utilizzare informazioni eccessivamente tecniche.
Ad esempio, uno dei tanti motivi per cui la finestra di dialogo HTTPS di cui abbiamo discusso in precedenza è
un meccanismo orribile per rilassare la politica di sicurezza è che le informazioni che fornisce sono troppo
confuse. Un altro grosso problema è che non è perseguibile, di cui parleremo tra poco.
Ti consigliamo di fornire un breve messaggio di errore e quindi informazioni più appropriate agli utenti quando
ne hanno bisogno. Questo è chiamatodivulgazione progressiva. Non inondare l'utente o l'amministratore con
informazioni che non possono utilizzare o comprendere; divulgare progressivamente i dati di cui hanno bisogno, se
ne hanno bisogno.
Due buoni esempi sono il modo in cui Internet Explorer e Firefox forniscono informazioni sui
certificati CA radice. La Figura 14-4 mostra la finestra di dialogo utilizzata da Internet Explorer per
visualizzare ed eventualmente installare un certificato. Se desideri maggiori informazioni sul certificato,
di cui francamente solo una persona esperta avrebbe bisogno, fai clic sulle schede Dettagli e/o
Percorso di certificazione. Le schede sono un meraviglioso meccanismo di divulgazione progressiva.
Rendilo attuabile
Va bene, quindi dici all'utente che è appena successo qualcosa di spaventoso sulla sicurezza. E adesso? C'è
qualcosa che l'utente dovrebbe fare? Forse guardare un file di registro o leggere qualche articolo online?
Aiutare l'utente a risolvere il problema; non lasciarla chiedere: "E adesso?"
Ancora una volta, questo si applica solo quando è assolutamente necessario esporre qualcosa all'utente.
Ripensa al nostro precedente esempio HTTPS. Ok, quindi hai trovato un modo chiaro per dire agli
utenti che il sito che pensavano di visitare non sembra corrispondere al sito che stanno ricevendo
(ovvero, il nome nel certificato non corrisponde). Ora cosa gli dici di fare? Potresti dire agli utenti di
riprovare, ma (indipendentemente dal fatto che il sito sia legittimo o meno) il problema probabilmente
continuerà, almeno per un po'. Potresti consigliare agli utenti di contattare l'amministratore del sito,
ma in molti casi l'amministratore del sito saprà della finestra di dialogo e dirà agli utenti di "fare
semplicemente clic su OK" senza rendersi conto che non possono più distinguere tra il sito reale e un
utente malintenzionato .
In breve, non esiste un modo ovvio per avvisare gli utenti di questa condizione, pur
rendendola perseguibile. Pertanto, probabilmente è meglio non richiamare esplicitamente
la condizione, ma farla sembrare un errore generico, in cui il server è inattivo.
ALTRE RISORSE
- “La protezione delle informazioni nei sistemi informatici” di Saltzer e Schroeder:
http://web.mit.edu/Saltzer/www/publications/protection/
- Ingegneria dell'usabilitàdi Jakob Nielson (Morgan Kaufmann, 1994)
- Sito web di ingegneria dell'usabilità di Jakob Nielson: www.useit.com
RIEPILOGO
- Farecomprendere le esigenze di sicurezza degli utenti e fornire le informazioni
appropriate per aiutarli a svolgere il proprio lavoro.
- Farerenditi conto che solo perché comprendi un testo di sicurezza, ciò non significa che i tuoi
utenti lo capiscano.
- Nonscarica il linguaggio geek in una finestra di dialogo che suona il clacson. Nessun utente lo leggerà.
- Nonrendere facile per gli utenti spararsi ai piedi: nascondere le opzioni che
possono essere pericolose!
- Prendere in considerazionefornire modi per allentare la politica di sicurezza in modo selettivo, ma
essere espliciti e chiari su ciò che l'utente sceglie di consentire.
Questa pagina è stata lasciata vuota intenzionalmente
15
Non si aggiorna facilmente
231
232 24 peccati capitali della sicurezza del software
RIFERIMENTI CWE
La voce CWE principale qui è "Verifica insufficiente dell'autenticità dei dati", ma molti dei punti deboli
secondari sono pertinenti, in particolare "Affidamento alle ricerche DNS in una decisione di sicurezza".
- CWE-353: Mancata aggiunta del valore del controllo di integrità (anche se questo dovrebbe
essere considerato come mancanza di una firma)
LINGUE INTERESSATE
Questo peccato non è specifico della lingua. Qualsiasi linguaggio di programmazione può essere utilizzato per fornire software
agli utenti.
IL PECCATO SPIEGATO
Questo peccato copre molto terreno; va dal rendere difficile l'applicazione di patch al fatto che gli utenti
vengano hackerati quando provano ad aggiornare il loro software.
Navigatore Web Safari. L'installazione di più software aumenta la superficie di attacco dell'utente e,
sfortunatamente per questo esempio, Safari 3.1 presentava un gran numero di gravi falle di sicurezza
subito dopo il rilascio. Un aggiornamento dovrebbe essere qualcosa che l'utente si sente a suo agio
nell'installare automaticamente, senza introdurre nuovo software e potenziali conflitti che ne derivano.
Una leggera eccezione a questa regola è che a volte è necessario introdurre nuove funzionalità in
un service pack o in una versione minore, ma in ogni caso non dovresti mai introdurre software
completamente estraneo. Il momento di chiedere agli utenti se desiderano prodotti aggiuntivi è
durante la configurazione iniziale, sebbene l'autore trovi anche questo fastidioso, anche se fatto dalla
sua stessa azienda!
Ignoranza peccaminosa
L'ignoranza può non essere beatitudine. Se sbagli troppo per evitare l'immediato affaticamento,
potresti lasciare l'utente vulnerabile. Se c'è un problema, l'utente deve esserne informato.
Abbiamo scritto un intero capitolo sul non fidarsi del DNS, Sin 24, ma vale la pena ripeterlo qui. Il tuo
software di aggiornamento non deve riporre alcuna fiducia nell'ottenere il server corretto.
Ci sono due parti in questo problema. Il primo è semplicemente non firmare affatto l'aggiornamento. Il
secondo è non verificare correttamente la firma. Questo è trattato in dettaglio in Sin 23, "Uso improprio
di PKI, in particolare SSL/TLS".
Peccato 15: Non si aggiorna facilmente
235
Il secondo problema è trattato a lungo in Sin 24, "Trusting Network Name Resolution", ma vale la
pena menzionarlo qui. Ora che ti abbiamo convinto a non fidarti del DNS o del server delle patch e a
firmare i tuoi aggiornamenti, non utilizzare un set obsoleto di algoritmi per firmare le tue patch,
soprattutto non MD5. Le firme MD5 sono completamente rotte e un utente malintenzionato potrebbe
creare malware che corrisponde alla tua patch.
Mentre siamo in tema di firma, firma i tuoi file binari con un server che è tenuto fuori
dalla rete: in primo luogo, non vuoi che la tua chiave privata venga compromessa, e anche
se hai un bel dispositivo hardware per mantenere il privato key safe (consigliato), non vuoi
che persone non autorizzate (dipendenti scontenti o hacker) vadano in giro per la rete
firmando cose a tuo nome.
Quindi hai ricevuto il pacchetto di aggiornamento dal server, attraverso la rete e sul disco locale,
e tutto verifica: cos'altro potrebbe andare storto? Se l'aggiornamento è progettato per essere
utilizzato da amministratori o componenti di sistema, è necessario firmare i singoli file eseguibili
oppure decomprimerlo mediante un processo attendibile in un'area attendibile. La directory di
sistema %temp% non funzionerà.
Questo è davvero più un problema con l'impostazione iniziale dell'applicazione per iniziare, ma se hai
commesso il peccato di scrivere binari in una directory controllata dall'utente in primo luogo,
probabilmente continuerai a peccare e scrivere aggiornamenti in anche un'area controllata dall'utente.
Ciò consente a qualsiasi app che è stata compromessa a livello di utente di compromettere anche la tua
app e di assicurarsi che rimanga compromessa. La firma non aiuta qui, dal momento che il codice che
controlla la firma è in esecuzione anche a livello di utente e deve essere considerato anch'esso
compromesso.
- I file consumati da un processo o servizio con privilegi sono scrivibili da utenti senza
privilegi. Se il file è firmato e la firma viene verificata prima dell'utilizzo da parte del
processo privilegiato, non è un problema.
- Esegui un aggiornamento e tenta di installare software aggiuntivo. Se questa è
un'impostazione predefinita, è peggio che suggerire semplicemente nuovo software ogni volta
che correggi i tuoi bug.