Il controllo PasswordBox di WPF? Ecco come ti svelo la password e come la proteggo nel VisualTree

Windows Presentation Foundation introduce un nuovo controllo per l’immissione delle password ma purtroppo, come per il TextBox Win32, non è troppo complicato svelare la parola magica nascosta sotto gli asterischi.

Il metodo più veloce consiste nell’analizzare il VisualTree (l’albero visuale dei controlli) tramite Snoop ed andare a leggere direttamente la proprietà Password del controllo.

Unsecure_WPF_LogOn

 

In pochi secondi la password può così essere trovata ma possiamo rendere la vita più difficile ad occhi indiscreti con poche righe di codice.

Innanzitutto come possiamo nascondere un valore di una proprietà da Snoop?

Snoop visualizza sia le proprietà di dipendenza sia le proprietà CLR ma noi creeremo una proprietà di dipendenza ad hoc per ingannare il programma (perlomeno nella versione attuale).

Proviamo prima di passare “al sodo” a creare una semplice Window in un nuovo progetto WPF chiamata MainWindow e ad inserire una normale DependencyProperty chiamata MyString1 con un valore di default facilmente riconoscibile:

MyString1

Snoopando MainWindow (gergo che significa: aprendo Snoop, selezionando la nostra applicazione in esecuzione, cliccando “Snoop this application” e cercando nel TreeView l’elemento MainWindow) possiamo vedere e modificare il valore di default MyString1.

Aggiungendo al costruttore della classe il codice

MyStringNuovoValore

anche il nuovo valore viene visualizzato da Snoop al caricamento della Window, tutto funziona a dovere.

Creiamo ora una nuova DependencyProperty chiamata MyString2 inserendo però nel “wrapper” CLR il codice di una normale proprietà CLR:

MyString2

Come si comporterà adesso Snoop con MyString2? Semplice continuerà a leggere la DependencyProperty gestita dal sistema di proprietà WPF mentre “il codice“ userà il wrapper CLR. In parole povere Snoop leggerà col metodo GetValue MyString2 mentre il codice leggerà MyString2 tramite _myString2.

Perfetto, abbiamo trovato come farla franca a Snoop!

Per esemplificare meglio allego il codice sorgente di AntiSnoopSample, un piccolo programma che ho scritto per mostrare le potenzialità di una proprietà di dipendenza “scritta male” in cui includo nella Window anche una proprietà solamente CLR MyString3 per dimostrare che Snoop legge correttamente anche le proprietà non di dipendenza.

Con quello che abbiamo imparato torniamo al nostro problema, analizzando il controllo PasswordBox notiamo subito che è marcato con sealed (non può essere ereditato), questo ci esclude una derivazione diretta di un nostro controllo che memorizzi la password in un campo non leggibile facilmente da Snoop.

Object_Browser_PasswordBox

A questo punto possiamo scegliere due strade: derivare dal controllo TextBox un “nostro PasswordBox” o cercare di ovviare tale limitazione tramite la gestione dell’evento PasswordChanged.

L’evento PasswordChanged viene scatenato quando il valore della proprietà viene modificato quindi possiamo copiare il carattere inserito in un campo privato interno alla nostra Window e sostituire la password del PasswordBox con degli asterischi (nel codice allegato la password è sostituita con dei cerchi). Ora proviamo a recuperare con Snoop la nostra password: otterremo solamente degli asterischi. Nella nostra applicazione dovremmo utilizzare il campo privato (nel codice this.pwd) per poter utilizzare la password in chiaro.

Snoop_secure_WPF_LogOn

Questa scelta ha però diverse limitazioni, per via del controllo PasswordBox “chiuso” non è possibile rilevare la posizione del cursore di testo. Non è possibile quindi replicare esattamente la password nel campo privato se è stato incollato del testo o se è stato premuto il tasto canc o backspace.

Dovremo limitarci a cancellare tutta la password all’avvenire di una di queste condizioni ma tutto sommato in alcuni scenari potrebbe andar bene.

Se invece scegliamo la strada della derivazione avremo maggiore flessibilità ma anche maggiore “responsabilità”, il codice dovrà infatti individuare la posizione delle modifiche nella password e riprodurle in un campo non visibile da Snoop.

Ho implementato a titolo esemplificativo il controllo SecurePasswordBox derivandolo da un TextBox, tutta la logica è eseguita nell’override dell’evento OnTextChanged e la password in chiaro è recuperabile tramite l’usuale proprietà Text del controllo. Snoop non permette di leggere la proprietà Text propria del SecurePasswordBox perchè, come spiegato, il suo wrapper CLR implementa un normale campo privato invece di chiamare SetValue/GetValue.

Snoop chiamando GetValue legge effettivamente “base.Text” ovvero il testo contenuto nel controllo eredito impostato però ad una serie di asterischi, la nostra privacy è al sicuro da Snoopate maliziose. Missione compiuta.

Scarica il codice sorgente dell’articolo

NOTA BENE: Queste soluzioni non vogliono essere definitive, una versione modificata di Snoop potrebbe benissimo leggere le password anche in questi casi o comunque l’attaccante potrebbe analizzare la memoria del programma e trovare in ogni caso la password, queste soluzioni vogliono difendere la sicurezza dell’applicazione sviluppata da un problema comune di facile applicazione.

Il consiglio è di non permettere in ambienti delicati l’esecuzione arbitraria in Full Trust di qualsiasi programma per evitare spiacevoli sorprese.

Print | posted on martedì 30 settembre 2008 01:23

Comments on this post

No comments posted yet.

Your comment:

 (will show your gravatar)
 
Please add 8 and 6 and type the answer here: