Fühlen Sie sich frei, mich zu korrigieren, wenn meine Annahmen hier falsch sind, aber lassen Sie mich erklären, warum ich frage.
Entnommen aus MSDN, a SecureString
:
Stellt Text dar, der vertraulich behandelt werden sollte. Der Text wird aus Datenschutzgründen verschlüsselt und bei Nichtgebrauch aus dem Computerspeicher gelöscht.
Ich verstehe, es ist absolut sinnvoll, ein Passwort oder andere private Informationen in einem SecureString
über a zu speichern System.String
, weil Sie steuern können, wie und wann es tatsächlich im Speicher gespeichert wird, weil a System.String
:
ist unveränderlich und kann, wenn es nicht mehr benötigt wird, nicht programmgesteuert für die Speicherbereinigung geplant werden. Das heißt, die Instanz ist nach ihrer Erstellung schreibgeschützt und es ist nicht möglich vorherzusagen, wann die Instanz aus dem Computerspeicher gelöscht wird. Wenn ein String-Objekt vertrauliche Informationen wie ein Kennwort, eine Kreditkartennummer oder persönliche Daten enthält, besteht daher das Risiko, dass die Informationen nach ihrer Verwendung angezeigt werden, da Ihre Anwendung die Daten nicht aus dem Computerspeicher löschen kann.
Bei einer GUI-Anwendung (z. B. einem SSH-Client) muss die Anwendung SecureString
jedoch aus a erstellt werden System.String
. Alle Textsteuerelemente verwenden eine Zeichenfolge als zugrunde liegenden Datentyp .
Dies bedeutet, dass jedes Mal, wenn der Benutzer eine Taste drückt, die alte Zeichenfolge verworfen wird und eine neue Zeichenfolge erstellt wird, um den Wert im Textfeld darzustellen, selbst wenn eine Kennwortmaske verwendet wird. Und wir können nicht steuern, wann oder ob einer dieser Werte aus dem Speicher verworfen wird .
Jetzt ist es Zeit, sich beim Server anzumelden. Erraten Sie, was? Sie müssen zur Authentifizierung eine Zeichenfolge über die Verbindung übergeben . Konvertieren wir also unsere SecureString
in eine System.String
.... und jetzt haben wir eine Zeichenfolge auf dem Heap, ohne dass er gezwungen werden kann, die Garbage Collection zu durchlaufen (oder Nullen in den Puffer zu schreiben).
Mein Punkt ist : Egal , was Sie tun, irgendwo entlang der Linie, die SecureString
sich geht in eine umgewandelt werden System.String
, es bedeutet , zumindest gibt es auf dem Heap zu einem bestimmten Zeitpunkt (ohne Gewähr für Garbage Collection).
Mein Punkt ist nicht : ob es Möglichkeiten gibt, das Senden einer Zeichenfolge an eine SSH-Verbindung zu umgehen oder zu umgehen, dass ein Steuerelement eine Zeichenfolge speichert (benutzerdefiniertes Steuerelement erstellen). Für diese Frage können Sie "ssh-Verbindung" durch "Anmeldeformular", "Registrierungsformular", "Zahlungsformular", "Lebensmittel-Sie-würden-Ihren-Welpen-aber-nicht-Ihre-Kinder-Formular füttern" ersetzen. etc.
- Ab wann wird die Verwendung eines
SecureString
tatsächlich praktikabel? - Lohnt es sich jemals die zusätzliche Entwicklungszeit, um die Verwendung eines
System.String
Objekts vollständig zu beseitigen ? - Ist es der springende Punkt
SecureString
, einfach die Zeit zu reduzieren, die sich aSystem.String
auf dem Heap befindet (um das Risiko zu verringern, zu einer physischen Auslagerungsdatei zu wechseln)? - Wenn ein Angreifer hat bereits die Mittel für eine Heap - Prüfung, dann wird er höchstwahrscheinlich entweder (A) hat bereits die Mittel , Tastenanschläge zu lesen, oder (B) , die bereits auf den Rechner hat ... So würde mit einem
SecureString
verhindern , dass er in der Einstiegs- Daten sowieso? - Ist das nur "Sicherheit durch Dunkelheit"?
Tut mir leid, wenn ich die Fragen zu dick stelle, hat mich die Neugier gerade überwältigt. Fühlen Sie sich frei, einige oder alle meiner Fragen zu beantworten (oder mir zu sagen, dass meine Annahmen völlig falsch sind). :) :)
SecureString
keine wirklich sichere Zeichenfolge ist. Dies ist lediglich eine Möglichkeit, das Zeitfenster zu verkürzen, in dem jemand Ihr Gedächtnis überprüfen und die vertraulichen Daten erfolgreich abrufen kann. Dies ist nicht kugelsicher und sollte es auch nicht sein. Aber die Punkte, die Sie ansprechen, sind sehr gültig. Siehe auchAntworten:
Es gibt tatsächlich sehr praktische Anwendungen von
SecureString
.Wissen Sie, wie oft ich solche Szenarien gesehen habe? (Die Antwort lautet: viele!):
RedGate
Software verwendet, die im Ausnahmefall den "Wert" lokaler Variablen erfassen konnte, was erstaunlich nützlich ist. Ich kann mir jedoch vorstellen, dass versehentlich "String-Passwörter" protokolliert werden.Wissen Sie, wie Sie all diese Probleme vermeiden können?
SecureString
. Es stellt im Allgemeinen sicher, dass Sie keine dummen Fehler als solche machen. Wie vermeidet es das? Indem Sie sicherstellen, dass das Kennwort im nicht verwalteten Speicher verschlüsselt ist und auf den tatsächlichen Wert nur zugegriffen werden kann, wenn Sie zu 90% sicher sind, was Sie tun.In dem Sinne
SecureString
funktioniert ziemlich einfach:1) Alles ist verschlüsselt
2) Benutzeranrufe
AppendChar
3) Entschlüsseln Sie alles in UNMANAGED MEMORY und fügen Sie den Charakter hinzu
4) Verschlüsseln Sie alles erneut in UNMANAGED MEMORY.
Was ist, wenn der Benutzer Zugriff auf Ihren Computer hat? Wäre ein Virus in der Lage, auf alle zuzugreifen
SecureStrings
? Ja. Alles, was Sie tun müssen, ist sich anzuschließen,RtlEncryptMemory
wenn der Speicher entschlüsselt wird. Sie erhalten den Speicherort der unverschlüsselten Speicheradresse und lesen sie aus. Voila! Tatsächlich könnten Sie einen Virus erstellen, der ständig nach seiner Verwendung suchtSecureString
und alle Aktivitäten damit protokolliert. Ich sage nicht, dass es eine leichte Aufgabe sein wird, aber es kann getan werden. Wie Sie sehen können, ist die "Leistungsfähigkeit" vonSecureString
vollständig verschwunden, sobald sich ein Benutzer / Virus in Ihrem System befindet.Sie haben ein paar Punkte in Ihrem Beitrag. Sicher, wenn Sie einige der UI-Steuerelemente verwenden, die intern ein "String-Passwort" enthalten, ist die Verwendung von actual
SecureString
nicht so nützlich. Trotzdem kann es vor Dummheit schützen, die ich oben aufgeführt habe.Wie bereits erwähnt, unterstützt WPF auch PasswordBox, das
SecureString
intern über seine SecurePassword- Eigenschaft verwendet wird.Das Endergebnis ist; Wenn Sie vertrauliche Daten (Passwörter, Kreditkarten usw.) haben, verwenden Sie
SecureString
. Dies ist, was C # Framework folgt. In derNetworkCredential
Klasse wird beispielsweise das Kennwort als gespeichertSecureString
. Wenn man sich anschaut , diese können Sie über ~ 80 verschiedene Verwendungen in .NET - Framework von sehenSecureString
.Es gibt viele Fälle, in denen Sie in einen
SecureString
String konvertieren müssen , da dies von einigen APIs erwartet wird.Das übliche Problem ist entweder:
Sie haben einen guten Punkt angesprochen: Was passiert, wenn auf
SecureString
konvertiert wirdstring
? Dies kann nur aufgrund des ersten Punktes geschehen. Beispielsweise weiß die API nicht, dass es sich um vertrauliche Daten handelt. Ich persönlich habe das nicht gesehen. Das Entfernen von Zeichenfolgen aus SecureString ist nicht so einfach.Es ist nicht einfach aus einem einfachen Grund ; Es war nie beabsichtigt, den Benutzer SecureString in einen String konvertieren zu lassen, wie Sie sagten: GC wird aktiv. Wenn Sie sehen, dass Sie das tun, müssen Sie einen Schritt zurücktreten und sich fragen: Warum mache ich das überhaupt oder brauche ich das wirklich? deswegen?
Es gibt einen interessanten Fall, den ich gesehen habe. Die WinApi-Funktion LogonUser verwendet nämlich LPTSTR als Kennwort, was bedeutet, dass Sie anrufen müssen
SecureStringToGlobalAllocUnicode
. Das gibt Ihnen im Grunde ein unverschlüsseltes Passwort, das sich in einem nicht verwalteten Speicher befindet. Sie müssen das loswerden, sobald Sie fertig sind:Sie können die
SecureString
Klasse jederzeit mit einer Erweiterungsmethode erweitern, z. B.ToEncryptedString(__SERVER__PUBLIC_KEY)
mit einerstring
InstanzSecureString
, die mit dem öffentlichen Schlüssel des Servers verschlüsselt ist. Nur der Server kann es dann entschlüsseln. Problem gelöst: Garbage Collection sieht niemals die "ursprüngliche" Zeichenfolge, da Sie sie niemals im verwalteten Speicher verfügbar machen. Genau das wird inPSRemotingCryptoHelper
(EncryptSecureStringCore(SecureString secureString)
) gemacht.Und als etwas fast Verwandtes: Mono SecureString verschlüsselt überhaupt nicht . Die Implementierung wurde auskommentiert, weil ..warte darauf .. "Es verursacht irgendwie einen Bruch des Nunit-Tests" , was zu meinem letzten Punkt führt:
SecureString
wird nicht überall unterstützt. Wenn die Plattform / Architektur nicht unterstützt wirdSecureString
, erhalten Sie eine Ausnahme. Es gibt eine Liste der Plattformen, die in der Dokumentation unterstützt werden.quelle
SecureString
eine Menge wäre mehr sinnvoll, wenn es einen Mechanismus waren für deren einzelne Zeichen zugreifen. Die Effizienz eines solchen Mechanismus könnte verbessert werden, indem ein StrukturtypSecureStringTempBuffer
ohne öffentliche Mitglieder vorhanden ist, derref
an dieSecureString
Methode "Ein Zeichen lesen" übergeben werden könnte [wenn die Verschlüsselung / Entschlüsselung in 8-Zeichen-Blöcken verarbeitet wird, könnte eine solche Struktur Daten enthalten für 8 Zeichen und die Position des ersten dieser Zeichen innerhalb desSecureString
].SecureString
es verwenden, es den ganzen Weg durch den Stapel verwendet werden muss.EngineSettings
in Ihrer Erweiterungsmethode?SecureString
sie nicht für Neuentwicklungen verwendet werden sollte ?Das sind nur wenige Probleme in Ihren Annahmen.
Erstens verfügt die SecureString-Klasse nicht über einen String-Konstruktor. Um ein Objekt zu erstellen, weisen Sie ein Objekt zu und hängen die Zeichen an.
Bei einer GUI oder einer Konsole können Sie jede gedrückte Taste ganz einfach an eine sichere Zeichenfolge übergeben.
Die Klasse ist so konzipiert, dass Sie versehentlich nicht auf den gespeicherten Wert zugreifen können. Dies bedeutet, dass Sie das
string
Passwort nicht direkt von ihm erhalten können.Um es beispielsweise zur Authentifizierung über das Web zu verwenden, müssen Sie geeignete Klassen verwenden, die auch sicher sind.
In .NET Framework gibt es einige Klassen, die SecureString verwenden können
(Mehr)
Zusammenfassend kann die SecureString-Klasse nützlich sein, erfordert jedoch mehr Aufmerksamkeit vom Entwickler.
All dies wird anhand von Beispielen in der MSDN-Dokumentation zu SecureString ausführlich beschrieben
quelle
SecureString
über das Netzwerk übertragen, ohne sie in eine zu serialisierenstring
? Ich denke, der Punkt der OP ist, dass es eine Zeit gibt, in der Sie den Wert, der sicher in a gespeichert ist, tatsächlich verwenden möchtenSecureString
, was bedeutet, dass Sie ihn dort rausholen müssen und er nicht mehr sicher ist. In der gesamten Framework-Klassenbibliothek gibt es praktisch keine Methoden, die aSecureString
direkt als Eingabe akzeptieren (soweit ich sehen kann). Was bringt es also, einen Wert überhaupt in a zu haltenSecureString
?char[]
und jeweilschar
über einen Socket senden - und dabei keine durch Müll sammelbaren Objekte erstellen.Ein SecureString ist nützlich, wenn:
Sie erstellen es Zeichen für Zeichen (z. B. aus Konsoleneingaben) oder beziehen es von einer nicht verwalteten API
Sie verwenden es, indem Sie es an eine nicht verwaltete API (SecureStringToBSTR) übergeben.
Wenn Sie es jemals in eine verwaltete Zeichenfolge konvertieren, haben Sie seinen Zweck verfehlt.
UPDATE als Antwort auf einen Kommentar
Nach der Konvertierung in ein BSTR kann die nicht verwaltete Komponente, die das BSTR verwendet, den Speicher auf Null setzen. Nicht verwalteter Speicher ist sicherer in dem Sinne, dass er auf diese Weise zurückgesetzt werden kann.
Es gibt jedoch nur sehr wenige APIs in .NET Framework, die SecureString unterstützen. Sie können also zu Recht sagen, dass dies heute nur einen sehr begrenzten Wert hat.
Der Hauptanwendungsfall, den ich sehen würde, ist eine Clientanwendung, bei der der Benutzer einen hochsensiblen Code oder ein Kennwort eingeben muss. Die Benutzereingaben können zeichenweise verwendet werden, um einen SecureString zu erstellen. Diese können dann an eine nicht verwaltete API übergeben werden, die den BSTR, den sie nach ihrer Verwendung erhält, auf Null setzt. Ein nachfolgender Speicherauszug enthält keine vertrauliche Zeichenfolge.
In einer Serveranwendung ist schwer zu erkennen, wo dies nützlich wäre.
UPDATE 2
Ein Beispiel für eine .NET-API, die einen SecureString akzeptiert, ist dieser Konstruktor für die X509Certificate-Klasse . Wenn Sie mit ILSpy oder ähnlichem spelunkieren, werden Sie feststellen, dass der SecureString intern in einen nicht verwalteten Puffer (
Marshal.SecureStringToGlobalAllocUnicode
) konvertiert wird , der dann mit (Marshal.ZeroFreeGlobalAllocUnicode
) auf Null gesetzt wird .quelle
SecureString
Was wäre ihre Verwendung , da fast keine Methode in der Framework-Klassenbibliothek eine Eingabe akzeptiert ? Sie müssten immerstring
früher oder später zurück konvertieren (oderBSTR
wie Sie bereits erwähnt haben, was nicht sicherer zu sein scheint). Warum sollte man sich überhaupt darum kümmernSecureString
?Microsoft empfiehlt nicht,
SecureString
für neuere Codes zu verwenden.Aus der Dokumentation der SecureString-Klasse :
Welches empfiehlt:
quelle
Wie Sie richtig identifiziert haben,
SecureString
bietet dies einen besonderen Vorteil gegenüberstring
: dem deterministischen Löschen. Es gibt zwei Probleme mit dieser Tatsache:SecureString
. Dies bedeutet , dass man vorsichtig sein muss nie einen GC-Managed unveränderlich erstellenstring
oder einen anderen Puffer, der die sensiblen Daten gespeichert werden (oder Sie den Überblick behalten, dass auch). In der Praxis ist dies nicht immer einfach zu erreichen, da viele APIs nur eine Möglichkeit bieten, damit zu arbeitenstring
, nichtSecureString
. Und selbst wenn Sie alles richtig machen ...SecureString
schützt vor ganz bestimmten Arten von Angriffen (und für einige von ihnen ist es nicht einmal so zuverlässig).SecureString
Ermöglicht es Ihnen beispielsweise, das Zeitfenster zu verkleinern, in dem ein Angreifer den Speicher Ihres Prozesses sichern und die vertraulichen Informationen erfolgreich extrahieren kann (wie Sie richtig betont haben), aber zu hoffen, dass das Fenster für den Angreifer zu klein ist Einen Schnappschuss Ihres Speichers zu machen, wird überhaupt nicht als Sicherheit angesehen.Wann sollten Sie es verwenden? Nur wenn Sie mit etwas arbeiten, mit dem Sie
SecureString
für alle Ihre Bedürfnisse arbeiten können, und selbst dann sollten Sie sich darüber im Klaren sein, dass dies nur unter bestimmten Umständen sicher ist.quelle
Der folgende Text wurde vom HP Fortify Static Code Analyzer kopiert
Zusammenfassung: Die Methode PassString () in PassGenerator.cs speichert vertrauliche Daten auf unsichere Weise (dh in Zeichenfolge), sodass die Daten durch Überprüfen des Heaps extrahiert werden können.
Erläuterung: Im Speicher gespeicherte vertrauliche Daten (wie Kennwörter, Sozialversicherungsnummern, Kreditkartennummern usw.) können verloren gehen, wenn sie in einem verwalteten String-Objekt gespeichert werden. String-Objekte sind nicht fixiert, sodass der Garbage Collector diese Objekte nach Belieben verschieben und mehrere Kopien im Speicher belassen kann. Diese Objekte sind standardmäßig nicht verschlüsselt, sodass jeder, der den Speicher des Prozesses lesen kann, den Inhalt sehen kann. Wenn der Speicher des Prozesses auf die Festplatte ausgelagert wird, wird der unverschlüsselte Inhalt der Zeichenfolge in eine Auslagerungsdatei geschrieben. Da String-Objekte unveränderlich sind, kann das Entfernen des Werts eines Strings aus dem Speicher nur vom CLR-Garbage Collector durchgeführt werden. Der Garbage Collector muss nicht ausgeführt werden, es sei denn, die CLR verfügt über wenig Arbeitsspeicher. Daher gibt es keine Garantie dafür, wann die Garbage Collection stattfinden wird.
Empfehlungen: Speichern Sie vertrauliche Daten nicht in Objekten wie Strings, sondern in einem SecureString-Objekt. Jedes Objekt speichert seinen Inhalt jederzeit in einem verschlüsselten Format im Speicher.
quelle
Ich möchte diesen Punkt ansprechen:
Ein Angreifer hat möglicherweise keinen vollständigen Zugriff auf den Computer und die Anwendung, kann jedoch über Mittel verfügen, um auf einige Teile des Arbeitsspeichers des Prozesses zuzugreifen. Dies wird normalerweise durch Fehler wie Pufferüberläufe verursacht, wenn speziell erstellte Eingaben dazu führen können, dass die Anwendung einen Teil des Speichers verfügbar macht oder überschreibt.
HeartBleed leckt Speicher
Nehmen wir zum Beispiel Heartbleed. Speziell konstruierte Anforderungen können dazu führen, dass der Code dem Angreifer zufällige Teile des Speichers des Prozesses zur Verfügung stellt. Ein Angreifer kann SSL-Zertifikate aus dem Speicher extrahieren. Er muss jedoch nur eine fehlerhafte Anforderung verwenden.
In der Welt des verwalteten Codes werden Pufferüberläufe viel seltener zu einem Problem. Und im Fall von WinForms werden Daten bereits unsicher gespeichert, und Sie können nichts dagegen tun. Dies macht den Schutz mit so
SecureString
ziemlich nutzlos.Die GUI kann jedoch für die Verwendung programmiert werden
SecureString
, und in diesem Fall kann es sich lohnen, das Fenster der Kennwortverfügbarkeit im Speicher zu reduzieren. Beispielsweise ist PasswordBox.SecurePassword von WPF vom TypSecureString
.quelle
Vor einiger Zeit musste ich eine AC # -Schnittstelle für ein Java-Kreditkartenzahlungs-Gateway erstellen, und man benötigte eine kompatible sichere Kommunikationsschlüsselverschlüsselung. Da die Java-Implementierung ziemlich spezifisch war und ich auf eine bestimmte Weise mit den geschützten Daten arbeiten musste.
Ich fand dieses Design recht einfach zu bedienen und einfacher als die Arbeit mit SecureString… für diejenigen, die es gerne verwenden… fühlen Sie sich frei, keine rechtlichen Einschränkungen :-). Beachten Sie, dass diese Klassen intern sind. Möglicherweise müssen Sie sie öffentlich machen.
quelle