Sicherheit: Dynamisch vs. statisch linken



  • Hey,

    würdet ihr sagen, das es unsicherer ist, wenn das Programm z.B. die wxWidgets Libs dynamisch linkt. Als Beispiel könnte das Programm ja ein Passwort an einen Server senden, um sich mit diesem verbinden zu können. Da wxWidgets openSource ist, könnte man sich als Hacker eine wxWidgets Lib zusammen mit Schadcode selber zusammenbauen um das Programm dazu zu zwischen das Hardgecodete Passwort anzuzeigen. Wäre also das Programm sicherer vor so einer Attacke, wenn wxWidgets statisch dazu gelinkt würde? Wie seht ihr das?

    Mfg,
    BluePhaz

    P.S.: wxWidgets ist nur ein Beispiel. Könnte auch Qt oder sonst was sein.



  • Ob ich dir jetzt eine infizierte dynamische Lib unterschiebe, eine voellig Fremde DLL in deinen Prozess injeziere, nen Network-Sniffer (ggf. auf externer Maschine) mitlaufen lasse oder mich gleich als dein Server mittels kuenstlicher ARP ausgebe, dein Programm nach Strings durchsuche oder mittels IDA eine Unscrambling/Decrypt-Routine reverese engineere, falls etwas verschluesselt ist, um an dein Passwort zu kommen, macht nicht wirklich nen Unterschied. Bei hardcodierten Sachen ist sowas unumgaenglich.
    Sobald du sowas wie ein Passwort in dein Programm packst, musst du auch davon ausgehen, dass jemand es knackt. Um statisch/dynamisch gegen etwas Linken wuerde ich mir da die wenigsten Sorgen machen, eher um das Sicherheitskonzept



  • Danke für deine Antwort.

    1. Wie könntest du meinem Prozess denn eine völlig fremde DLL injezieren, wenn das Programm komplett statisch gelinkt wurde?
    2. Den Network-Sniffer könnte ich mit SSL aushebeln.
    3. Deine künstliche ARP kann ich aushebeln, wenn ich das Passwort mit einem weiteren Passwort AES verschlüssele. Ist leider dann auch wieder hardgecodet, wird aber nicht verschickt.
    4. Programm nach Strings durchsuchen => Ist das wirklich so einfach? Hat man da in Null-Komma-Nix das Passwort? Gibt es da irgendwelche Schutzprogramme für C++ exen, die man drüber laufen lassen könnte?

    5. Ok, also ist es nicht der Sicherheitsfaktor, der die Leute dazu treibt ihre Programme statisch zu linken. Was ist es dann? Beispielsweise Qt nimmt tausende von Euros dafür, das man statisch linken darf. Und alles nur dafür, das das Programm etwas schneller läd und "leichter" zu veröffentlichen ist?



  • BluePhaz schrieb:

    5. Ok, also ist es nicht der Sicherheitsfaktor, der die Leute dazu treibt ihre Programme statisch zu linken. Was ist es dann? Beispielsweise Qt nimmt tausende von Euros dafür, das man statisch linken darf. Und alles nur dafür, das das Programm etwas schneller läd und "leichter" zu veröffentlichen ist?

    Man darf mit der kommerziellen Lizenz auch Änderungen an QT selber vornehmen ohne diese veröffentlichen zu müssen.

    Und man darf auch nicht vergessen, dass kommerzielle Lizenzen oftmals mit Support verknüpft wird. Das macht auch einiges vom Preis aus.



  • BluePhaz schrieb:

    5. Ok, also ist es nicht der Sicherheitsfaktor, der die Leute dazu treibt ihre Programme statisch zu linken. Was ist es dann? Beispielsweise Qt nimmt tausende von Euros dafür, das man statisch linken darf. Und alles nur dafür, das das Programm etwas schneller läd und "leichter" zu veröffentlichen ist?

    Schau mal ins GUI Forum wie viele Leute statisch linken wollen, nur weil sie die .dll's nicht mitgeben wollen (oder zu blöd dafür sind die ins Anwendungsvgerzeichnis zu kopieren und zu verstehen welche sie brauchen). Das ist nicht nur bei QT so, sondern auch bei wxWidgets, nur da ist der statische Build kostenlos verfügbar. Daher braucht man da auch keine Workarounds oder große Diskussionen.



  • BluePhaz schrieb:

    1. Wie könntest du meinem Prozess denn eine völlig fremde DLL injezieren, wenn das Programm komplett statisch gelinkt wurde?

    Der einfache Weg ist, sie in die Windows Known DLLs zu packen (geht ganz einfach per Registry), sodass sie in jeden Prozess geladen werden. Alternativ koennte man glaube ich auch Code ueber WriteProcessMemory injezieren und dann CreateRemoteThread benutzen, um ihn zur Ausfuehrung zu bringen. Der koennte dann wohl u.a. LoadLibrary ausfuehren.

    BluePhaz schrieb:

    2. Den Network-Sniffer könnte ich mit SSL aushebeln.

    Gut, da geb ich mich geschlagen.

    BluePhaz schrieb:

    3. Deine künstliche ARP kann ich aushebeln, wenn ich das Passwort mit einem weiteren Passwort AES verschlüssele. Ist leider dann auch wieder hardgecodet, wird aber nicht verschickt.

    Selbes Problem: Ist das Passwort fuers Passwort hardcodiert, ist auch das wieder in deiner Exe. Macht nur etwas mehr Arbeit, im Disassembler zu gucken, wie du die beiden aufeinander anwendest, sodass das eigentlich gesuchte PW rauskommt.

    BluePhaz schrieb:

    4. Programm nach Strings durchsuchen => Ist das wirklich so einfach? Hat man da in Null-Komma-Nix das Passwort? Gibt es da irgendwelche Schutzprogramme für C++ exen, die man drüber laufen lassen könnte?

    Gesetzt dem Fall, dein Passwort ist im Format SuperMegaGegheimTM\0 und es liegt in der .data/.rdata/.rodata-Sektion, dann ists relativ wahrscheinlich, dass ich es mit nem einfachen Stringsuchprogramm gleich raussuche. Laesst dus zur Compiletime irgendwie Scrambeln (gab schon Ansaetze hier, XOR-VerschluesselungScrambling in TMP durchzufuehren), hab ichs vielleicht nicht ganz so einfach. Das Problem ist hier wieder: Der Entscrambling-Code/Schluessel muss auch irgendwo herkommen. Und wenn er in deiner Datei liegt, darf IDA wieder ran.

    5. haben Tobi und Scorcher ja schon beantwortet.

    Uebrigens: Nehmen wir mal an, du sicherst das Passwort auf dem Server so ab, dass ich nicht rankomme, ohne dein Programm zu verwenden. Niemand verhindert, dass ich es mit einem Debugger durch-single-steppe bis an die Stelle, wo das Passwort im Speicher liegt, dann stoppe und das Ding wieder auslese. Gut, es gibt Anti-Debugger-Techniken, genauso gibt es aber Stealth-Moeglichkeiten fuer die Debugger.

    Kurzum: Wenn du was hardcodierst, kannst du nicht sichergehen, dass niemand rankommt.[/Gebetsmuehle]

    Worum geht es eigentlich genau? Ggf. kann man dir eher helfen, wenn du verraetst, was du erreichen willst, nicht wie.



  • Ich schreibe öfters Client/Server-Anwendungen, jedoch möchte ich, das sich auch wirklich nur mein Client mit meinem Server verbinden kann. Deshalb schicke ich immer ein Hardgecodetes Passwort mit. Gibt es bessere Möglichkeiten?

    P.S.: Wie ist das denn möglich ein Programm zu debuggen, was keine Debuggingsymbols enthält?



  • BluePhaz schrieb:

    Ich schreibe öfters Client/Server-Anwendungen, jedoch möchte ich, das sich auch wirklich nur mein Client mit meinem Server verbinden kann. Deshalb schicke ich immer ein Hardgecodetes Passwort mit. Gibt es bessere Möglichkeiten?

    Es gibt (zumindest nach meinem Wissensstand) eigentlich keine Moeglichkeit, das zu erreichen. Alles, was auf dem Rechner des Anwenders liegt, kann er auseinander nehmen. Also auch Passwoerter etc. rausholen. Kann sein, dass hier einer der Netzwerk- oder Verschluesselungsexperten ein Verfahren kennt, mit dem man sowas erreichen kann, aber mir ist da nichts bekannt; allerdings ist das auch nicht unbedingt mein Gebiet.

    BluePhaz schrieb:

    P.S.: Wie ist das denn möglich ein Programm zu debuggen, was keine Debuggingsymbols enthält?

    Debugger auf, Programm laden?
    Debug-Infos sind nur Symbolnamen etc., d.h. du machst es dir damit einfacher. Ich koennte, wenn ich ein Programm von mir Debugge, relativ wenig mit call 0xDEADBEEF anfangen, aber wenn mir ein Debug-Symbol sagt, dass an 0xDEADBEEF die Funktion foo(int a, void* b) beginnt, dann ist das fuer mich verstaendlich und ich kann schnell sehen, dass es z.B. in dieser Funktion zu nem Crash kommt.
    Will ich ein Binary analysieren, was keine Debug-Symbole hat, dann hab ich den Luxus halt nicht. In dem Fall muss ich halt raten, dass

    push ebp
    mov ebp, esp
    mov eax, [ebp + 8]
    add eax, [ebp + 12]
    pop ebp
    ret
    

    mal sowas hiess wie int add(int x, int y) { return x + y; }
    Es macht halt mehr Arbeit, abhalten tut es nicht. So koennte ich mich dann zur Entschluesselungsroutine vorarbeiten und nen Breakpoint setzen, wenn sie mit der Arbeit fertig ist. Und schon hab ich deinen dekodierten Schluessel :p



  • BluePhaz schrieb:

    Ich schreibe öfters Client/Server-Anwendungen, jedoch möchte ich, das sich auch wirklich nur mein Client mit meinem Server verbinden kann. Deshalb schicke ich immer ein Hardgecodetes Passwort mit. Gibt es bessere Möglichkeiten?

    SSL bietet Zertifikate, damit kann sich dein Server authentifizieren und die anderen nicht, sofern sie nicht das richtig Zertifikat haben
    Das Zertifikat musst du dann natürlich clientseitig überprüfen.

    Wenn der Client aber manipuliert wird, dann ist es egal was du machst, dann wird er sich immer auch mit anderen Servern verbinden können, wenn es die Hacker darauf ausgelegt haben.

    P.S.: Wie ist das denn möglich ein Programm zu debuggen, was keine Debuggingsymbols enthält?

    https://www.youtube.com/watch?v=mmRKWyVXl3A


Anmelden zum Antworten