Sinn von SecureString/ Sicherheit des .Net Frameworks

  • VB.NET
  • .NET (FX) 4.0

Es gibt 29 Antworten in diesem Thema. Der letzte Beitrag () ist von Gonger96.

    Sinn von SecureString/ Sicherheit des .Net Frameworks

    Wollte mal kurz in die Runde fragen, was die SecureString-Klasse eigentlich bringen soll.
    Hab neulich rausgefunden, dass man nämlich mit diversen Tools einfach so ein eigenes Programm in ein anderes .NET Programm zur Laufzeit injizieren kann.
    Dort teilt man dann den Speicher und kann lustig auf alle Sachen zugreifen wie man möchte. Per Reflection natürlich auch ganz easy auf die privaten Felder.

    Und nein das ganze ist wirklich nicht schwer und auch nicht aufwendig. Das einzige, was aufwendig ist, ist das Injizieren, aber dafür gibts ja schon fertige Tools.

    So wie ich das sehe ist das ne ziemliche Pseudo-Sicherheit, die den .Net-Entwicklern da vorgegaukelt wird. Das betrifft natürlich nicht nur die SecureString-Klasse, sondern das komplette .Net-Framework.

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „markus.obi“ ()

    Vor solchen Injezierungen ist kein Programm sicher, aber das verspricht SecureString ja auch nicht. Wenn du mal nachließt, das steht nur, dass SecureString im Vergleich zu normalen Strings nicht unvorhersehbar lange im Speicher verbleiben, sondern zuverlässig entfernt werden können.
    Hi
    SecureString sorgt dafür, dass die Daten des Strings sicher gespeichert werden und bei einem ToString-Aufruf kurzzeitig in den "ungeschützten" Speicher geladen werden. Der String wird von der GC wieder freigegeben, sobald keine Referenz mehr darauf existiert, wie es halt immer läuft.
    Pseudosicherheit ist im FW eigentlich nicht vorhanden. Man muss - wie bei Allem - halt wissen, was man macht. Public, usw. sind sinnvolle Modifikatoren, mit denen ein sinnvolles Programmieren möglich ist. Wäre ja blöd, wenn du deine Logik nicht sinnvoll kapseln kannst...

    Gruß
    ~blaze~
    Es gibt schon Vorkehrungen dagegen. Normalerweise haben Programme nicht genügend Berechtigungen, um auf andere Speicherbereiche als ihren eigenen zuzugreifen. Wenn es aber durch eine Sicherheitslücke doch gelingt, diese Berechtigungen zu erlangen, dann stehst du halt machtlos da, auch als Entwickler.
    @ErfinderDesRades
    Ich glaube du hast noch gar keine Vorstellung, was alles möglich ist und wie einfach das ist.
    Man kann einfach eine fremde kompilierte .Net Anwendung in ein Visual Studio Projekt einbinden (Verweis hinzufügen).
    Dann hat man Zugriff auf alle Klassen dieser Anwndung. Wenn man die Injektion mal geschafft hat ist es das einzige Problem eine Referenz zu bekommen.
    Über Application.OpenForms bekommt man in den meisten Fällen sofort eine Referenz auf eine Form, die man dann in den richtigen Typ downcasten kann.

    Ab diesem Punkt ist das Auslesen so einfach, als würde man eine ganz normale .NET Application schreiben.
    Sogar Events gehen einwandfrei. Das alles in ein paar Zeilen Code.
    Einer der Hauptgründe für SecureString dürften die Windows-Auslagerungsfunktionen sein.
    Wenn dein Rechner anfängt zu swappen kann es ja passieren, dass der mal dein Passwort auf die Platte schreibt. Freut dann natürlich den Angreifer, der sich (physikalischen) Zugang zu deinem Rechner verschafft hat.

    Aber auch hier gilt wieder: Wer Software ausführen kann und spätestens wer physisch vor dem Computer steht, hat gewonnen. Hat man absolut keine Chance mehr.
    @Gonger96 Ich dachte wirklich, dass es aus .NET-Sicht schwerer wäre, ein natives(oder allgemein ein nicht-DotNet-)Programm zu manipulieren oder auszulesen. Klar, wenn ich von einem Prozess das Handle für beispielsweise das Hauptfenster auslese habe ich den Zeiger dafür. Aber damit an das ausführende Objekt heranzukommen habe ich bei meinen Versuchen bislang nie geschafft(keine Angst, ich habe das nicht für illegale Zwecke versucht - Habe für sowas keine Verwendung). Aber nach meinem Verständnis dürfte das ja auch gar nicht so universell funktionieren, wenn andere Sprachen anders aufgebaut sind(z.B. Nicht-Objektorientierte Sprachen), wo es dann auch kein ordinäres Objekt gäbe, das man mit der (ich sag' jetzt mal so) .Net-Reflection-Funktionalität auslesen könnte. Oder habe ich da etwas nicht so richtig verstanden?
    Ich dachte, dass man über das Handle eines Programmes evtl. an ein riesen Byte-Array kommen könnte, das in dessen "reservierten" Speicher ist. Aber daraus die korrekten Typen auszulesen und evtl. zu manipulieren stelle ich mir als schwieriger vor, als einige hier beschreiben.
    In diese Richtung scheint mir wohl noch einiges an Wissen zu fehlen. Kann mir da jemand evtl. Lektüre empfehlen?(nach Möglichkeit mit Ausrichtung auf .NET-Sprachen)
    Nein, objektorientiert funktioniert da nichts mehr. Zunächst mal liegen bei Fensterhandles keine Klassen dahinter, denn Windows ist in C programmiert und da gibts gar keine Klassen. Aber wäre C++ im Spiel würdest du trotzdem nicht an die Klassen kommen, da das .Net-Typsystem und das C++-Tysystem inkompatibel sind. Du kannst nur Bytes auslesen und dir daraus gewisse Strukturen wie z.B. Strings rekonstruieren. Etwas auszulesen oder manipulieren zu können erfordert also, die Speicherstruktur des Zielprogrammes zu kennen, das ist eine der höheren Künste. Für Cheatengine z.B. gibt es dann Leute, die sowas rausfinden und die jeweiligen Speicheradressen, an denen gesucht werden muss, online stellen, damit es jeder verwenden kann. Um FUnktionen aufzurufen/zu überschreiben ist es dann im PRinzip nichts anderes mehr, nur diesmal wird halt nach dem Funktionspointer statt irgend welchen Daten gesucht.

    Artentus schrieb:

    Etwas auszulesen oder manipulieren zu können erfordert also, die Speicherstruktur des Zielprogrammes zu kennen, das ist eine der höheren Künste. Für Cheatengine z.B. gibt es dann Leute, die sowas rausfinden und die jeweiligen Speicheradressen, an denen gesucht werden muss, online stellen, damit es jeder verwenden kann.

    =O Ja, dass da so eine Komplexität dahintersteckt, habe ich befürchtet. Mit anderen Worten: Wenn man riesen Byte-Arrays nicht richtig zu interpretieren vermag, kann man es eigentlich gleich vergessen, auch nur einfachere Dinge auszulesen(ausser Strings beispielsweise, richtig?).
    Puh, wenn ich daran denke, dass ich den Speicher unseres Artikelverwaltungsprogrämmchen auslesen wollte, um schneller an alle Artikel zu kommen... :rolleyes:

    Higlav schrieb:

    Wenn man riesen Byte-Arrays nicht richtig zu interpretieren vermag, kann man es eigentlich gleich vergessen
    Ja, und es gibt nicht viele Leute, die sowas im großen Maßstab vermögen.
    Der andere Faktor ist dann auch die Zeit. Es gibt bei sowas keine andere Möglichkeit, als das Programm immer und immer wieder laufen zu lassen und dabei den Speicher zu untersuchen, bis man findet, was man sucht. Je nach Komplexität der zu Untersuchenden Strukturen kann das Monate dauern.
    Strings lassen sich tatsächlich relativ einfach finden, das kann mit einer generischen Suche automatisiert werden. Man durchsucht dabei einfach den gesamten Speicher des Zielprogrammes nach folgen von Bytes, die alle druckbare Zeichen ergeben. Das ist ziemlich genau, da in normalem Bytecode normalerweise keine solchen Abfolgen auftreten.

    Artentus schrieb:

    Strings lassen sich tatsächlich relativ einfach finden, das kann mit einer generischen Suche automatisiert werden. Man durchsucht dabei einfach den gesamten Speicher des Zielprogrammes nach folgen von Bytes, die alle druckbare Zeichen ergeben. Das ist ziemlich genau, da in normalem Bytecode normalerweise keine solchen Abfolgen auftreten.

    Aber wenn das auch mit SecureStrign-Objekten funktioniert, bringt einem die Verwendung dessen wirklich sehr wenig. :huh:

    Manawyrm schrieb:

    Man kann aber doch durchaus praktisch mit einem Debugger wie OllyDBG nachhelfen ;)

    Nää. Dann lieber doch nicht. :D

    Also meine Frage bezüglich Lektüre in diese Richtung ziehe ich hiermit zurück: Ich habe wohl kaum Lust/Zeit, mir den Speicher anderer Programme zu besehen, um an ein paar mickrige Werte heranzukommen. :P Obwohl: Interessant wäre es eben doch. Also den Aufbau von verschiedenen Programmen zu verstehen. Gehe ich beispielsweise richtig in der Annahme, dass auch Zahlen(sagen wir mal Integer) in "Klartext" gespeichert werden? Also, dass 56715 im Speicher des Programmes dann irgendwie so vorkommt: {..., 5, 6, 7, 1, 5, ...}