Ich versuche, den Zweck von .NETs SecureString zu verstehen. Von MSDN:
Eine Instanz der System.String-Klasse ist unveränderlich und kann, wenn sie 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.
Ein SecureString-Objekt ähnelt einem String-Objekt darin, dass es einen Textwert hat. Der Wert eines SecureString-Objekts wird jedoch automatisch verschlüsselt, kann geändert werden, bis Ihre Anwendung es als schreibgeschützt markiert, und von Ihrer Anwendung oder dem .NET Framework-Garbage Collector aus dem Computerspeicher gelöscht werden.
Der Wert einer Instanz von SecureString wird automatisch verschlüsselt, wenn die Instanz initialisiert oder der Wert geändert wird. Ihre Anwendung kann die Instanz unveränderlich machen und weitere Änderungen verhindern, indem Sie die MakeReadOnly-Methode aufrufen.
Ist die automatische Verschlüsselung die große Auszahlung?
Und warum kann ich nicht einfach sagen:
SecureString password = new SecureString("password");
anstatt
SecureString pass = new SecureString();
foreach (char c in "password".ToCharArray())
pass.AppendChar(c);
Welchen Aspekt von SecureString vermisse ich?
quelle
SecureString
Neuentwicklung mehr: github.com/dotnet/platform-compat/blob/master/docs/DE0001.mdAntworten:
Ich würde SecureString nicht mehr verwenden. Sieht so aus, als würden PG-Leute die Unterstützung dafür einstellen. Möglicherweise sogar in Zukunft - https://github.com/dotnet/apireviews/tree/master/2015-07-14-securestring .
quelle
Einige Teile des Frameworks, die derzeit verwendet werden
SecureString
:System.Windows.Controls.PasswordBox
Kontrolle von WPF wird das Kennwort intern als SecureString gespeichert (als Kopie angezeigtPasswordBox::SecurePassword
).System.Diagnostics.ProcessStartInfo::Password
Anwesen ist einSecureString
X509Certificate2
nimmt einSecureString
für das PasswortDer Hauptzweck besteht darin, die Angriffsfläche zu reduzieren, anstatt sie zu beseitigen.
SecureStrings
sind im RAM "angeheftet", damit der Garbage Collector sie nicht verschiebt oder Kopien davon erstellt. Außerdem wird sichergestellt, dass der Klartext nicht in die Swap-Datei oder in Core-Dumps geschrieben wird. Die Verschlüsselung ähnelt eher einer Verschleierung und wird jedoch einen entschlossenen Hacker nicht aufhalten, der in der Lage wäre, den symmetrischen Schlüssel zu finden, der zum Ver- und Entschlüsseln verwendet wird.Wie andere gesagt haben, liegt der Grund, warum Sie ein
SecureString
Zeichen für Zeichen erstellen müssen, in dem ersten offensichtlichen Fehler, etwas anderes zu tun: Vermutlich haben Sie den geheimen Wert bereits als einfache Zeichenfolge. Worum geht es also?SecureString
s sind der erste Schritt zur Lösung eines Henne-Ei-Problems. Obwohl die meisten aktuellen Szenarien erfordern, dass sie wieder in reguläre Zeichenfolgen umgewandelt werden, um sie überhaupt nutzen zu können, bedeutet ihre Existenz im Framework jetzt eine bessere Unterstützung für sie in der Zukunft - zumindest bis zu einem Punkt, an dem Ihr Programm nicht das schwache Glied sein muss.quelle
Bearbeiten : Verwenden Sie SecureString nicht
Aktuelle Richtlinien besagen nun, dass die Klasse nicht verwendet werden sollte. Die Details finden Sie unter folgendem Link: https://github.com/dotnet/platform-compat/blob/master/docs/DE0001.md
Aus dem Artikel:
DE0001: SecureString sollte nicht verwendet werden
Motivation
SecureString
besteht darin, zu vermeiden, dass Geheimnisse als einfacher Text im Prozessspeicher gespeichert werden.SecureString
jedoch kein Betriebssystemkonzept.System.String
- die Lebensdauer des nativen Puffers ist kürzer.Empfehlung
Nicht
SecureString
für neuen Code verwenden. Beachten Sie beim Portieren von Code nach .NET Core, dass der Inhalt des Arrays nicht im Speicher verschlüsselt ist.Der allgemeine Ansatz beim Umgang mit Anmeldeinformationen besteht darin, diese zu vermeiden und sich stattdessen auf andere Mittel zur Authentifizierung zu verlassen, z. B. Zertifikate oder Windows-Authentifizierung.
Ende der Bearbeitung: Originalzusammenfassung unten
Viele gute Antworten; Hier ist eine kurze Zusammenfassung dessen, was besprochen wurde.
Microsoft hat die SecureString-Klasse implementiert, um eine bessere Sicherheit mit vertraulichen Informationen (wie Kreditkarten, Kennwörtern usw.) zu gewährleisten. Es bietet automatisch:
Derzeit ist die Verwendung von SecureString begrenzt, es wird jedoch eine bessere Einführung in der Zukunft erwartet.
Basierend auf diesen Informationen sollte der Konstruktor des SecureString nicht nur eine Zeichenfolge nehmen und in das char-Array aufteilen, da die Schreibweise der Zeichenfolge den Zweck von SecureString zunichte macht.
Zusätzliche Information:
Bearbeiten: Ich fand es schwierig, die beste Antwort zu finden, da es in vielen gute Informationen gibt; Schade, dass es keine unterstützten Antwortoptionen gibt.
quelle
Kurze Antwort
Denn jetzt hast du
password
in Erinnerung; ohne die Möglichkeit, es zu löschen - genau das ist der Punkt von SecureString .Lange Antwort
Der Grund, warum SecureString existiert, ist, dass Sie ZeroMemory nicht zum Löschen vertraulicher Daten verwenden können, wenn Sie damit fertig sind. Es ist vorhanden, um ein Problem zu lösen, das aufgrund der CLR besteht.
In einer regulären nativen Anwendung würden Sie Folgendes aufrufen
SecureZeroMemory
:Hinweis : SecureZeroMemory ist identisch mit
ZeroMemory
, außer dass der Compiler es nicht entfernt.Das Problem ist, dass Sie nicht
ZeroMemory
oderSecureZeroMemory
in .NET anrufen können . Und in .NET sind Zeichenfolgen unveränderlich. Sie können den Inhalt der Zeichenfolge nicht einmal wie in anderen Sprachen überschreiben :Also was kannst du tun? Wie bieten wir in .NET die Möglichkeit, ein Passwort oder eine Kreditkartennummer aus dem Speicher zu löschen, wenn wir damit fertig sind?
Der einzige Weg , es kann getan werden wäre die Zeichenfolge in einigen zu platzieren nativen Speicherblock, in dem Sie können dann rufen
ZeroMemory
. Ein natives Speicherobjekt wie:SecureString gibt die verlorene Fähigkeit zurück
In .NET können Strings nicht gelöscht werden, wenn Sie damit fertig sind:
Dispose
von ihnenSecureString ist eine Möglichkeit, die Sicherheit von Strings zu umgehen und deren Bereinigung bei Bedarf zu gewährleisten.
Sie haben die Frage gestellt:
Denn jetzt hast du
password
in Erinnerung; ohne eine Möglichkeit, es abzuwischen. Es bleibt dort hängen, bis die CLR beschließt, diesen Speicher wiederzuverwenden. Sie haben uns wieder dorthin gebracht, wo wir angefangen haben. Eine laufende Anwendung mit einem Kennwort, das wir nicht entfernen können und bei der ein Speicherauszug (oder Prozessmonitor) das Kennwort sehen kann.SecureString verwendet die Datenschutz-API, um die im Speicher verschlüsselte Zeichenfolge zu speichern. Auf diese Weise ist die Zeichenfolge in Swap-Dateien, Absturzabbildern oder sogar im Fenster für lokale Variablen nicht vorhanden, wenn ein Kollege Ihre Anforderungen überprüft.
Wie lese ich das Passwort?
Dann ist die Frage: Wie interagiere ich mit der Zeichenfolge? Sie wollen absolut keine Methode wie:
denn jetzt bist du wieder da, wo du angefangen hast - ein Passwort, das du nicht loswerden kannst. Sie wollen zwingen Entwickler die empfindliche Saite richtig zu handhaben - so dass es kann aus dem Gedächtnis gewischt werden.
Aus diesem Grund bietet .NET drei praktische Hilfsfunktionen, um einen SecureString in einem nicht verwalteten Speicher zu speichern:
Sie konvertieren die Zeichenfolge in einen nicht verwalteten Speicher-Blob, behandeln ihn und löschen ihn dann erneut.
Einige APIs akzeptieren SecureStrings . Zum Beispiel in ADO.net 4.5 die SqlConnection.Credential nimmt einen Satz SqlCredential :
Sie können das Kennwort auch innerhalb einer Verbindungszeichenfolge ändern:
Und es gibt viele Stellen in .NET, an denen sie aus Kompatibilitätsgründen weiterhin eine einfache Zeichenfolge akzeptieren und diese dann schnell umdrehen und in einen SecureString einfügen.
Wie füge ich Text in den SecureString ein?
Dies lässt immer noch das Problem:
Dies ist die Herausforderung, aber es geht darum, dass Sie über Sicherheit nachdenken.
Manchmal ist die Funktionalität bereits für Sie bereitgestellt. Beispielsweise kann das WPF PasswordBox- Steuerelement das eingegebene Kennwort direkt als SecureString zurückgeben :
Dies ist hilfreich, da Sie überall dort, wo Sie eine Rohzeichenfolge weitergegeben haben, jetzt das Typsystem haben, das sich darüber beschwert, dass SecureString nicht mit Zeichenfolge kompatibel ist. Sie möchten so lange wie möglich arbeiten, bevor Sie Ihren SecureString wieder in eine normale Zeichenfolge konvertieren müssen.
Das Konvertieren eines SecureString ist einfach genug:
wie in:
Sie wollen einfach nicht, dass du es tust.
Aber wie bekomme ich einen String in einen SecureString? Nun, was Sie tun müssen, ist, überhaupt kein Passwort mehr in einem String zu haben. Sie mussten es in etwas anderem haben. Sogar ein
Char[]
Array wäre hilfreich.Dann können Sie jedes Zeichen anhängen und den Klartext löschen, wenn Sie fertig sind:
Sie müssen Ihr Passwort in einem Speicher speichern, den Sie löschen können. Laden Sie es von dort in den SecureString.
tl; dr: SecureString ist vorhanden, um das Äquivalent von ZeroMemory bereitzustellen .
Einige Leute sehen keinen Sinn darin , das Kennwort des Benutzers aus dem Speicher zu löschen, wenn ein Gerät gesperrt ist , oder Tastatureingaben aus dem Speicher zu löschen, nachdem sie authentifiziert wurden . Diese Personen verwenden SecureString nicht.
quelle
Es gibt nur sehr wenige Szenarien, in denen Sie SecureString in der aktuellen Version des Frameworks sinnvoll einsetzen können. Es ist wirklich nur nützlich für die Interaktion mit nicht verwalteten APIs - Sie können es mit Marshal.SecureStringToGlobalAllocUnicode marshallen.
Sobald Sie es in / aus einem System.String konvertieren, haben Sie seinen Zweck besiegt.
Das MSDN- Beispiel generiert aus der Konsoleneingabe jeweils ein SecureString-Zeichen und übergibt die sichere Zeichenfolge an eine nicht verwaltete API. Es ist ziemlich verworren und unrealistisch.
Sie können erwarten, dass zukünftige Versionen von .NET mehr Unterstützung für SecureString bieten, wodurch es nützlicher wird, z.
SecureString Console.ReadLineSecure () oder ähnliches zum Lesen von Konsoleneingaben in einen SecureString ohne den gesamten verschlungenen Code im Beispiel.
WinForms TextBox-Ersatz, in dem die TextBox.Text-Eigenschaft als sichere Zeichenfolge gespeichert wird, damit Kennwörter sicher eingegeben werden können.
Erweiterungen zu sicherheitsrelevanten APIs, damit Kennwörter als SecureString übergeben werden können.
Ohne das oben Genannte ist SecureString von begrenztem Wert.
quelle
Ich glaube, der Grund, warum Sie anstelle einer flachen Instanziierung Zeichen anhängen müssen, liegt darin, dass im Hintergrund die Übergabe von "Kennwort" an den Konstruktor von SecureString diese "Kennwort" -String in den Speicher legt, wodurch der Zweck einer sicheren Zeichenfolge zunichte gemacht wird.
Durch das Anhängen speichern Sie jeweils nur ein Zeichen in einem Speicher, der wahrscheinlich nicht physisch nebeneinander liegt, was die Rekonstruktion der ursprünglichen Zeichenfolge erheblich erschwert. Ich könnte mich hier irren, aber so wurde es mir erklärt.
Der Zweck der Klasse besteht darin, zu verhindern, dass sichere Daten über einen Speicherauszug oder ein ähnliches Tool verfügbar gemacht werden.
quelle
MS stellte fest, dass es in bestimmten Fällen, in denen der Server (Desktop, was auch immer) zum Absturz gebracht wurde, Zeiten gab, in denen die Laufzeitumgebung einen Speicherauszug ausführte, der den Inhalt des Speichers enthüllte. Secure String verschlüsselt es im Speicher, um zu verhindern, dass der Angreifer den Inhalt des Strings abrufen kann.
quelle
Einer der großen Vorteile eines SecureString besteht darin, dass vermieden werden soll, dass Ihre Daten aufgrund von Seiten-Caching auf der Festplatte gespeichert werden. Wenn Sie ein Kennwort im Speicher haben und dann ein großes Programm oder einen großen Datensatz laden, wird Ihr Kennwort möglicherweise in die Auslagerungsdatei geschrieben, wenn Ihr Programm nicht mehr über genügend Arbeitsspeicher verfügt. Mit einem SecureString werden zumindest die Daten nicht unbegrenzt im Klartext auf Ihrer Festplatte gespeichert.
quelle
Ich denke, das liegt daran, dass die Zeichenfolge sicher sein soll, dh ein Hacker sollte sie nicht lesen können. Wenn Sie es mit einer Zeichenfolge initialisieren, kann der Hacker die ursprüngliche Zeichenfolge lesen.
quelle
Nun, wie in der Beschreibung angegeben, wird der Wert verschlüsselt gespeichert, was bedeutet, dass ein Speicherauszug Ihres Prozesses den Wert der Zeichenfolge nicht anzeigt (ohne ziemlich ernsthafte Arbeit).
Der Grund, warum Sie einen SecureString nicht einfach aus einer konstanten Zeichenfolge erstellen können, liegt darin, dass Sie dann eine unverschlüsselte Version der Zeichenfolge im Speicher haben würden. Wenn Sie sich darauf beschränken, die Zeichenfolge in Teilen zu erstellen, verringert sich das Risiko, dass die gesamte Zeichenfolge gleichzeitig gespeichert wird.
quelle
Ein weiterer Anwendungsfall ist, wenn Sie mit Zahlungsanwendungen (POS) arbeiten und einfach keine unveränderlichen Datenstrukturen zum Speichern vertraulicher Daten verwenden können, da Sie ein sorgfältiger Entwickler sind. Beispiel: Wenn ich vertrauliche Kartendaten oder Autorisierungsmetadaten in unveränderlichen Zeichenfolgen speichere, ist es immer dann der Fall, wenn diese Daten nach dem Verwerfen für einen längeren Zeitraum im Speicher verfügbar sind. Ich kann es nicht einfach überschreiben. Ein weiterer großer Vorteil, wenn solche sensiblen Daten verschlüsselt gespeichert werden.
quelle