2013-05-22 2 views
21

In Java war die alte Art, einen geheimen Schlüssel wie ein Passwort zu speichern, char[], da Sie seine Daten überschreiben konnten, wenn Sie damit fertig waren. Dies hat sich jedoch seither als unsicher erwiesen, da der Garbage Collector beim Umorganisieren des Heap die Dinge kopieren wird. Auf bestimmten Architekturen ist es möglich, dass eine Seite freigegeben wird, und das Geheimnis bleibt bestehen, wenn ein anderes Programm dieselbe Seite zuweist.Ist es möglich, in Java Geheimnisse auf dem Stack zu speichern?

Das ist schrecklich hässlich, aber was ist, wenn das Geheimnis auf dem Stapel von run eines Threads gespeichert wurde? Es wäre noch Vorsicht geboten, den Thread elegant zu beenden, so dass er seine Daten auf Null setzen könnte, aber dieses Problem war auch in der alten Form vorhanden.

Ein großes Problem, das ich sofort feststellen kann, ist, dass ich mir keinen sicheren Weg vorstellen kann, um Daten in den Container zu bekommen. Sie können die Wahrscheinlichkeit eines ausgelaufenen Geheimnisses minimieren, indem Sie Streams mit sehr kleinen internen Puffern verwenden, aber am Ende werden Sie mit dem gleichen Problem wie char[] enden. [Edit: Würde ein einzelnes Mitglied private static byte und eine Flagge funktionieren? Dies würde Sie jedoch auf ein Geheimnis pro ClassLoader beschränken. Dies fügt mehr Hässlichkeit hinzu, aber es könnte leicht genug sein, sich hinter einer gut geschriebenen Schnittstelle zu verstecken.]

Also ich habe eine Menge Fragen, wirklich.

Ist der Stapel von diesen Angriffstypen sicherer als der Heap? Gibt es reine Java-Mechanismen, um eine Stapel-zu-Stapel-Kopie zwischen zwei verschiedenen Stapelrahmen auf eine Weise durchzuführen, die für dieses Problem nützlich wäre? Wenn nicht, würde die JVM diese Art von Operation sogar in Bytecode unterstützen?

[Edit: Bevor die Menschen zu viel Sorge, dies ist eher ein Gedankenexperiment als alles andere. Ich habe absolut nicht die Absicht, "in der Produktion zu testen" oder es in einem aktuellen Projekt zu verwenden. Mir ist klar, dass das, worüber ich rede, wirklich hässlich ist, wahrscheinlich schrecklich sperrig, und wirkt gegen die gesamte JVM-Struktur. Ich bin nur daran interessiert, ob es möglich ist, ob es meine Ziele tatsächlich erreicht, und welche Arten von heroics es dauern würde, um sie geschehen.]

+5

Wenn Sie über einen Angreifer zu Recht besorgt sind, um Daten wie diese bekommen Zugang, die Chancen sind Sie sowieso geschraubt sind, weil jeder Angreifer ausgefeilt genug besorgt zu sein auf diesem Niveau anspruchsvoll genug ist, fast alles brechen Sie können Wirf sie an. –

+0

Im Prinzip stimme ich zu, aber das ist ein sehr schlechtes Argument, um eine Bedrohung zu schließen. Wie auch immer, ich habe diesen Weg eingeschlagen, als ich eine Liste von Sicherheitsanforderungen durchgesehen habe, die mir mein Kunde zur Verfügung gestellt hat. Einer besteht darin, dass wir Geheimnisse immer im Speicher auf Null setzen. Wenn dies nicht geschieht, wird der Kunde sie überprüfen. Der Klient ist schlau genug zu verstehen, dass 'char []' nicht funktionieren wird, aber sie verlangen auch, dass wir Java benutzen. Zum Glück sind sie vernünftige Leute, sie erkennen den Konflikt und es ist nicht zu groß. Aber es hat mich dazu gebracht zu denken ... –

+0

sehr schlechtes Argument gegen das Schließen einer Bedrohung * - Entschuldigung, Bearbeitungszeitraum abgelaufen. –

Antwort

12

Ich würde eine direkte ByteBuffer verwenden. Der verwendete Speicher wird nicht kopiert und befindet sich nur an einer Stelle für die Lebensdauer des ByteBuffers. BTW nicht verwenden clear(), da dies nur die Position zurückgesetzt. Sie können es überschreiben mit

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

Ist der Stapel nicht mehr sicher vor dieser Art von Angriffen als der Halde?

Ich würde nicht so denken.

Gibt es irgendwelche reinen Java-Mechanismen, um eine Stapel-zu-Stapel-Kopie zwischen zwei verschiedenen Stapelrahmen auf eine Weise durchzuführen, die für dieses Problem nützlich wäre?

Sie könnten das Geheimnis als ein oder zwei long s speichern.

Wenn nicht, würde die JVM sogar diese Art von Operation in Bytecode unterstützen?

Der Byte-Code wurde entwickelt, um Java zu unterstützen, und bietet wenig mehr als das, was Sie in Java tun können.

Ich bin nur daran interessiert, ob es möglich ist, ob es meine Ziele tatsächlich erreicht, und welche Arten von heroics es dauern würde, bis es

Verwenden Sie eine direkte ByteBuffer wie ich vorgeschlagen habe geschehen. ;)

+0

"Der verwendete Speicher wird nicht kopiert ..." - Verwendet er intern nicht ein 'byte []'? Das ist auf dem Heap gespeichert und ebenso anfällig wie jedes andere Array (wie das oben erwähnte 'char []'), um die Reorganisation durch den GC zu haufen. –

+2

Ein Heap ByteBuffer verwendet ein Byte [], ein direkter ByteBuffer verwendet nativen Speicher. Nativer Speicher wird nicht von der GC berührt. –

+0

Ich würde fragen, ist das sicherer als Speichern in JVM-Speicher? –

Verwandte Themen