2013-05-22 12 views
21

In Java il vecchio modo di memorizzare un segreto, come ad esempio una password, era usare char[] in quanto si poteva sovrascrivere i propri dati quando si era finito con esso. Tuttavia, da allora è stato dimostrato che non è sicuro poiché il garbage collector copierà le cose mentre riorganizza l'heap. Su alcune architetture è possibile che una pagina venga liberata e il segreto rimarrà quando qualche altro programma assegna quella stessa pagina.È possibile archiviare segreti nello stack in java?

Questo è orribilmente brutto, ma cosa succede se il segreto è stato memorizzato nella pila del metodo run di Thread? Sarebbe comunque necessario fare attenzione a terminare il thread con garbo, in modo che potesse azzerare i suoi dati, ma questo problema era presente anche nel vecchio modo.

Uno dei problemi principali che vedo subito è che non riesco a pensare a un modo sicuro per ottenere dati dentro e fuori dal container. È possibile ridurre al minimo la probabilità di un segreto trapelato utilizzando flussi con buffer interni molto piccoli, ma alla fine si finisce con lo stesso problema di char[]. [Modifica: un singolo membro private static byte e una bandiera funzionano? Sebbene ciò ti limiti a un segreto per ClassLoader. Questo aggiunge più bruttezza, ma potrebbe essere abbastanza facile nascondersi dietro un'interfaccia ben scritta.]

Quindi ho un sacco di domande, davvero.

Lo stack è più sicuro da questi tipi di attacchi rispetto all'heap? Esistono meccanismi Java puri per eseguire una copia da stack a stack tra due diversi stack frame in un modo che sarebbe utile a questo problema? In caso contrario, la JVM supporta anche questo tipo di operazione in bytecode?

[Modifica: Prima che le persone si preoccupino troppo, questo è più di un esperimento mentale che altro. Non ho assolutamente intenzione di "provare in produzione" o di usarlo in qualsiasi progetto corrente. Mi rendo conto che quello di cui sto parlando è davvero brutto, probabilmente orribilmente ingombrante e funziona contro l'intera struttura JVM. Mi interessa sapere se è possibile, se effettivamente raggiunge i miei obiettivi e che tipo di eroismo ci vorrebbe per realizzarlo.]

+5

Se sei legittimamente preoccupato per un utente malintenzionato che ottiene l'accesso a dati come questo, è probabile che tu sia fottuto comunque, perché ogni attaccante abbastanza sofisticato da essere preoccupato a questo livello è abbastanza sofisticato da infrangere la maggior parte qualsiasi cosa tu possa lanciarli contro di loro –

+0

In linea di massima sono d'accordo, ma questo è un argomento molto povero per chiudere una minaccia. In ogni caso, ho iniziato questo percorso quando esaminavo un elenco di requisiti di sicurezza forniti dal mio cliente. Uno è che abbiamo sempre a zero i segreti in memoria. In caso contrario, verrà preso dal cliente in revisione. Il client è abbastanza intelligente da capire che 'char []' non funzionerà, tuttavia impongono anche l'uso di Java. Fortunatamente sono persone ragionevoli, riconoscono il conflitto e non è una preoccupazione troppo grande. Ma mi ha fatto pensare ... –

+0

argomento molto povero contro la chiusura di una minaccia * - scusate, modifica il periodo di tempo scaduto. –

risposta

12

Vorrei utilizzare un ByteBuffer diretto. La memoria che usa non è copiata e si trova solo in un posto per la vita di ByteBuffer. BTW non usa clear() in quanto ciò ripristina semplicemente la posizione. È possibile sovrascrivere con

bb.clear(); 
while(bb.remaining() >= 8) bb.putLong(0); 
while(bb.remaining() > 0) bb.put((byte) 0); 

è la pila più al sicuro da questo tipo di attacchi rispetto al mucchio?

Non ci penso.

Esistono meccanismi Java puri per eseguire una copia da stack a stack tra due diversi stack frame in un modo che sarebbe utile a questo problema?

È possibile memorizzare il segreto come uno o due long s.

In caso contrario, la JVM supporta anche questo tipo di operazione in bytecode?

Il codice byte è progettato per supportare Java e fa molto poco più di quello che è possibile fare in Java.

io sono solo interessati a sapere se è possibile, sia che si tratti in realtà compie i miei obiettivi, e che tipo di eroismo che ci vuole per farlo accadere

Utilizzare un ByteBuffer diretta come ho suggerito. ;)

+0

"La memoria che usa non è copiata intorno ..." - Non usa un 'byte []' internamente? Questo è archiviato nell'heap e altrettanto suscettibile di qualsiasi altro array (come il 'char []' ho menzionato sopra 'per ammassare la riorganizzazione da parte del GC. –

+2

Un heap ByteBuffer utilizza un byte [], un ByteBuffer diretto utilizza la memoria nativa. La memoria nativa non viene toccata dal gc. –

+0

Chiederei è più sicuro rispetto all'archiviazione nella memoria jvm? –