none
Schützen einer Variable RRS feed

  • Frage

  • Ich habe mal wieder eine Frage.

    Wie kann ich eine Variable (konkret ein String Objekt und ein byte Array) schützen. D.h. es heißt wie kann ich erreichen, dass diese Variablen nach Benutzung sofort gelöscht werden und wie kann ich verhindern, dass diese Variablen in die Auslagerungsdatei geschrieben werden?

    Und kann ich dies in irgendeiner Form nachvollziehen bzw. überprüfen?

    Ich hoffe ihr könnt mir in diesen Punkte weiterhelfen und vielen Dank schon einmal in vor raus.

    Sonntag, 7. April 2013 09:16

Antworten

  • Hallo Simon,

    Die Stärke und Schwäche von SecureString ist, dass es die Methoden SystemFunction040 (d.h. CryptProtectMemory [DPAPI/Crypt32.dll], auf Vor-Vista Systemen RtlEncryptMemory [Advapi32.dll]) und SystemFunction041 (d.h. CryptUnprotectMemory bzw. RtlDecryptMemory) bei jeder Erweiterung des gespeicherten Inhalts zur Laufzeit verwendet. Diese Funktionen werden in der mscorlib mit dem Option-Flag 0 aufgerufen, was die Verschlüsselung außerhalb des laufenden Prozesses bis auf weiteres unmöglich macht. Landet der Speicherinhalt in die Auslagerungsdatei (wüßte nicht gleich wie, da nicht-verwalteter und nicht auslagerbarer Speicher verwendet wird) würde das keinen realen Wert für den Angreifer haben, da außerhalb des Prozesses nicht entschlüsselbar. Crasht der Rechner während der Verschlüsselung jedoch, dann könnte der Klartext den man gerade verschlüsselt u.U. in einer Speicherabbilddatei (dump) landen, was ich eher für ein reales und ernstzunehmendes Risiko-Szenario halte. Zusammengefaßt: Die Verwendung von verwalteten Byte-Arrays für die Speicherung von sehr sensitiven Informationen kann man sich abschminken. Das sicherste, was z.Z. verfügbar ist, ist SecureString. Es gibt Tools, die zwar in den Prozessraum der Anwendung injiziert werden können und so jeden SecureString zur Laufzeit auslesen können, aber außerhalb des Prozesses ist der Inhalt eines verschlüsselten SecureStrings wertlos. Verwende ein modernes Windows-Betriebsystem mit dem letzten .NET-Framework und Du bist so sicher, wie man z.Z. sein kann.

    Gruß
    Marcel

    • Als Antwort markiert Simon Rühle Freitag, 12. April 2013 11:54
    Mittwoch, 10. April 2013 11:27
    Moderator

Alle Antworten

  • Hallo, ich nehme mal an das du die Variablen gegen das lesen im Arbeitsspeicher schützen möchtest. Schau dir mal folgende Klasse an:
    http://msdn.microsoft.com/de-de/library/system.security.securestring.aspx

    Verhindern das eine Variable in der Auslagerungsdatei landet kann man nicht, da dieser wie RAM behandelt wird. Mit der GC-Klasse kann man etwas einfluss darauf nehmen wann eine Variable gelöscht werden soll.


    <Code:13/> - Koopakiller [kuːpakɪllɐ]
    Webseite | Code Beispiele | Facebook | Snippets
    Wenn die Frage beantwortet ist, dann markiert die hilfreichsten Beiträge als Antwort und bewertet die Beiträge. Danke.
    Einen Konverter zwischen C# und VB.NET Code gibt es hier.

    Sonntag, 7. April 2013 09:32
    Moderator
  • Nun ja, da es in an einer Kryptographie Anwendung arbeite, sollte der Key nicht in der Auslagerungsdatei landen. Gibt es zumindest eine Möglichkeit dies Festzustellen und die Variable anschließend zu überschreiben. Oder gibt es eine Möglichkeit zu Erzwingen, dass die Variable wenn sie einmal gesetzt wurde, immer im gleichen Speicherbereich liegt, dann könnte ich sie nämlich einfach mehrfach überschreiben.
    Sonntag, 7. April 2013 10:43
  • Hi Simon,

    ich weiß jetzt nicht genau was du machen möchtest. Aber für Kryptographie Anwendungen hat das Frameworke eigene Klassen.

    MFG

    Björn

    Sonntag, 7. April 2013 11:42
  • Ist jetzt nicht c#. Aber soweit ich weiß, gibt es schon non-paged User-Mode-Speicher (AllocateUserPhysicalPages).
    Habe aber keine Ahnung, ob das in deinem Szenario praktikabel ist.

    Mit freundlichen Gruessen

    Sonntag, 7. April 2013 12:32
  • Hallo Simon,

    vorab: Ich bin kein Sicherheitsexperte (wie die wohl meisten hier); die könnten dazu mehr sagen. (Trotzdem) einige Überlegungen meinerseits:

    Ein "gleicher Speicherbereich" ist nicht von Vorteil, da er es einem Angreifer leichter macht, einen kritischen Bereich zu ermitteln. Und der Speicher eines Prozesses lässt sich - ggf. auf Umwegen wie Dll Injection - auslesen.

    Eine Ablage im Nonpaged Pool Memory vermeidet zwar die Ablage in der Auslagerungsdatei macht es aber umgekehrt leichter, da der Adressbereich deutlich kleiner ist. Mehr zu den Möglichkeiten der Speicherallokierung siehe VirtualAlloc[Ex].

    Ein ungeschützter Wert sollte nur so kurz wie möglich existieren. Den Weg beschreitet das bereits erwähnte SecureString, in dem es den Wert verschlüsselt speichert (RtlEncryptMemory) und für den Zugriff entschlüsselt (RtlDecryptMemory).

    Die "unhandlichen" Zugriffsmethoden sind dabei Absicht. Denn nur so vermeidet man, dass Zeichenketten im Speicher verbleiben (vorausgesetzt die Klasse wird richtig eingesetzt). Ebenso muss man sich im klaren sein, dass durch die Verschlüsselung der Zugriff nicht schnellste ist - was aber für kleinere Mengen kein Problem darstellen sollte. Eine Möglichkeit wäre evtl. die ProtectedData Class - wenn man nicht gleich unmanaged anfangen will.

    Gruß Elmar

    Sonntag, 7. April 2013 15:24
    Beantworter
  • Die SecureString Klasse wurde schon mehrfach angesprochen. Wie verschlüsselt diese den gespeicherten String? Die Dokumentation ist da mit Informationen zu diesem Aspekt etwas zurückhaltend. Eine weitere Frage ist, ob SecureString sich vor dem Schreiben in die Auslagerungsdatei schützt?
    Dienstag, 9. April 2013 15:52
  • Hallo Simon,

    das Verhalten hatte ich in meiner Antwort angedeutet:

    Die Daten werden intern bei jedem Zugriff entschlüsselt, die Operation ausgeführt und sofort wieder verschlüsselt.

    AppendChar sieht gekürzt so aus:

        this.UnProtectMemory();
        this.m_buffer.Write<char>((ulong)(this.m_length * 2), c);
        this.m_length++;
        this.ProtectMemory()

    wobei <Un>ProtectMemory die oben verlinkten API-Methoden verwenden. m_buffer basiert auf der SafeBuffer Klasse.

    Entsprechend gehen die anderen Methoden vor.

    Gruß Elmar


    Dienstag, 9. April 2013 16:54
    Beantworter
  • Hallo Simon,

    Eine weitere Frage ist, ob SecureString sich vor dem Schreiben in die Auslagerungsdatei schützt?
    SecureString ist zu keinem Zeitpunkt unverschlüsselt im Speicher. Deswegen würde ich mir keine Sorgen wegen der Auslagerung machen. Allerdings ist ein eventueller vor- bzw. nachgeschalteter Klartext, so dieser nicht über die SecureString-Methoden hinzugefügt wird, eine leichte Beute. Der beste Schutz besteht - wie auch in anderen Sachen - "es nicht zu tun", d.h. man darf den Schlüssel einfach nie aus der Hand geben. Das geht z.B. indem Du den Schlüssel und die ganze Verschlüsselung hinter einem WCF-Dienst verbirgst. Alles andere Methoden, inklusive DPAPI-Verschlüsselung leiden darunter, dass ein Angreifer mit administrativem Zugriff auf das System nur noch das einschlägige Wissen und einen guten Debugger braucht. Aber wer Zugriff auf das System hat, der braucht die kryptografische Schicht gar nicht zu durchbrechen! Er kann sich ja ganz bequem über einen Wrapper zwischen Aufrufer und der kryptografischen Schicht schalten, warum sollte er sich all die Mühe machen. Sicherheit muss man sich immer wie eine Kette vorstellen, die so schwach wie das schwächste Glied ist. Glaub mir bitte, es macht gar keinen Sinn sich solche Fragen zu stellen, wie Du das hier tust, wenn man davon ausgeht, dass der Angreifer Zugriff auf die Auslagerungsdatei hat. Dann ist alles verloren.

    Gruß
    Marcel

    Dienstag, 9. April 2013 18:12
    Moderator
  • Hallo Marcel,

    es geht mir nicht darum einen Angriff zur Laufzeit abzuwehren, da dies, wie du korrekt ausgeführt hast nicht möglich ist, wenn man z.B. einen Trojaner auf dem System hat.

    Der Punkt ist vielmehr, dass wenn die Verschlüsselung erfolgt ist, und jemand Zugriff auf die Festplatte hat, keine Möglichkeit besteht an den Key mehr heranzukommen, wie es ja bei einer Auslagerung in die Auslagerungsdatei der Fall ist.

    D.h. ich muss dafür sorgen, dass der Key nur während bzw. auch kurz vor der Verschlüsselung vorhanden und somit angreifbar ist.

    Die Frage die ich bezüglich der Verschlüsselung des SecureString Objekt hatte, ist die, wenn dieses Objekt in der Auslagerungsdatei landet, ist es nach Abschluss der Benutzung, noch möglich diesen SecureString zu entschlüsseln? Und wie wird es überhaupt verschlüsselt (was wird als Key genommen und welches Verschlüsselungsverfahren wird genutzt)?

    Mittwoch, 10. April 2013 08:18
  • Hallo Simon,

    wenn ich das richtig sehe, wird in die Auslagerungsdatei auch nur das geschrieben, was im Hauptspeicher liegen würde. Da der SecureString immer nur für einen minimalen Zeitraum entschlüsselt vorliegt, dürfte das Risiko gering sein, dass er unverschlüsselt dort landet. Eine 100%ige Sicherheit gibt es allerdings weder hier noch sonstwo.

    Um deine weiteren Fragen beantworten zu können, muss man den Code der entsprechenden Klasse detailliert analysieren, eine Doku hierzu gibt es AFAICS nicht. Daher würde ich dir empfehlen, mit einem Decompiler wie bspw. JustDecompile, .NET Reflector, ... in den Code zu schauen. Damit solltest Du deine Fragen evtl. beantworten können. (Allerdings ist das IMHO keine leichte Kost, wenn man da komplett durchsteigen will :)


    Gruß, Stefan
    Microsoft MVP - Visual Developer ASP/ASP.NET
    http://www.asp-solutions.de/ - Consulting, Development
    http://www.aspnetzone.de/ - ASP.NET Zone, die ASP.NET Community

    Mittwoch, 10. April 2013 10:15
    Moderator
  • Hallo Simon,

    Die Stärke und Schwäche von SecureString ist, dass es die Methoden SystemFunction040 (d.h. CryptProtectMemory [DPAPI/Crypt32.dll], auf Vor-Vista Systemen RtlEncryptMemory [Advapi32.dll]) und SystemFunction041 (d.h. CryptUnprotectMemory bzw. RtlDecryptMemory) bei jeder Erweiterung des gespeicherten Inhalts zur Laufzeit verwendet. Diese Funktionen werden in der mscorlib mit dem Option-Flag 0 aufgerufen, was die Verschlüsselung außerhalb des laufenden Prozesses bis auf weiteres unmöglich macht. Landet der Speicherinhalt in die Auslagerungsdatei (wüßte nicht gleich wie, da nicht-verwalteter und nicht auslagerbarer Speicher verwendet wird) würde das keinen realen Wert für den Angreifer haben, da außerhalb des Prozesses nicht entschlüsselbar. Crasht der Rechner während der Verschlüsselung jedoch, dann könnte der Klartext den man gerade verschlüsselt u.U. in einer Speicherabbilddatei (dump) landen, was ich eher für ein reales und ernstzunehmendes Risiko-Szenario halte. Zusammengefaßt: Die Verwendung von verwalteten Byte-Arrays für die Speicherung von sehr sensitiven Informationen kann man sich abschminken. Das sicherste, was z.Z. verfügbar ist, ist SecureString. Es gibt Tools, die zwar in den Prozessraum der Anwendung injiziert werden können und so jeden SecureString zur Laufzeit auslesen können, aber außerhalb des Prozesses ist der Inhalt eines verschlüsselten SecureStrings wertlos. Verwende ein modernes Windows-Betriebsystem mit dem letzten .NET-Framework und Du bist so sicher, wie man z.Z. sein kann.

    Gruß
    Marcel

    • Als Antwort markiert Simon Rühle Freitag, 12. April 2013 11:54
    Mittwoch, 10. April 2013 11:27
    Moderator