Wie kann eine Format-String-Schwachstelle ausgenutzt werden?

Lesezeit: 10 Minuten

Ich habe über Sicherheitslücken im Code gelesen und bin darauf gestoßen Format-String-Schwachstelle.

Wikipedia sagt:

Format-String-Fehler treten am häufigsten auf, wenn ein Programmierer einen String drucken möchte, der vom Benutzer bereitgestellte Daten enthält. Der Programmierer könnte fälschlicherweise printf(buffer) anstelle von printf(“%s”, buffer) schreiben. Die erste Version interpretiert den Puffer als Formatzeichenfolge und analysiert alle darin enthaltenen Formatierungsanweisungen. Die zweite Version gibt einfach eine Zeichenfolge auf dem Bildschirm aus, wie es der Programmierer beabsichtigt hat.

Ich habe das Problem mit der printf(buffer)-Version, aber ich habe immer noch nicht verstanden, wie diese Schwachstelle von einem Angreifer verwendet werden kann, um schädlichen Code auszuführen. Kann mir bitte jemand sagen, wie diese Schwachstelle sein kann ausgebeutet an einem beispiel?

  • Als Referenz finden Sie hier die Frage zum Pufferüberlaufangriff: stackoverflow.com/questions/7344226/buffer-overflow-attack

    – Mystisch

    18. September 2011 um 5:31 Uhr

  • möglicherweise verwandt: stackoverflow.com/questions/5672996/…

    – Eran Zimmermann Gonen

    18. September 2011 um 5:33 Uhr

  • @Mehrdad: Warum sollte printf etwas vom Stack holen? Es ist nicht so, dass es weiß (oder sich darum kümmert), wie viele Argumente (oder sogar wie groß) ursprünglich gepusht wurden …

    – Benutzer541686

    18. September 2011 um 5:33 Uhr


  • @Mehrdad: Tut es nicht Pop irgendetwas vom Stack, aber. Es liest sie einfach. Beachten Sie, dass der Anrufer möglicherweise sogar gedrückt hat mehr Argumente, als der Angerufene erwartet, und doch die Anrufer macht das Aufräumen. Der Angerufene weiß es nicht oder kümmert sich nicht darum – alles, was er tut, ist, die Daten zu lesen. Aus diesem Grund können Sie in C keine Callee-Bereinigung mit varargs haben.

    – Benutzer541686

    18. September 2011 um 5:35 Uhr


  • @Mehrdad Jetzt hast du mich zum Nachdenken gebracht … anscheinend hast du Recht. Es liest definitiv mehr Daten vom Stack, aber das bedeutet nicht unbedingt, dass es beim Lesen auftaucht.

    – mmx

    18. September 2011 um 5:37 Uhr


Benutzeravatar von Michael Foukarakis
Michael Foukarakis

Sie können eine Formatstring-Schwachstelle auf viele Arten direkt oder indirekt ausnutzen. Nehmen wir das Folgende als Beispiel (unter der Annahme, dass keine relevanten Betriebssystemschutzmaßnahmen vorhanden sind, was ohnehin sehr selten vorkommt):

int main(int argc, char **argv)
{
    char text[1024];
    static int some_value = -72;

    strcpy(text, argv[1]); /* ignore the buffer overflow here */

    printf("This is how you print correctly:\n");
    printf("%s", text);
    printf("This is how not to print:\n");
    printf(text);

    printf("some_value @ 0x%08x = %d [0x%08x]", &some_value, some_value, some_value);
    return(0);
}

Grundlage dieser Schwachstelle ist das Verhalten von Funktionen mit variablen Argumenten. Eine Funktion, die die Behandlung einer variablen Anzahl von Parametern implementiert, muss diese im Wesentlichen vom Stack lesen. Wenn wir eine Formatzeichenfolge angeben, die erstellt wird printf() Erwarten Sie zwei Ganzzahlen auf dem Stack, und wir geben nur einen Parameter an, der zweite muss etwas anderes auf dem Stack sein. Als Erweiterung, und wenn wir die Kontrolle über die Formatzeichenfolge haben, können wir die zwei grundlegendsten Primitive haben:


Lesen von beliebigen Speicheradressen

[EDIT] WICHTIG: Ich mache hier einige Annahmen über das Stack-Frame-Layout. Sie können sie ignorieren, wenn Sie die grundlegende Prämisse hinter der Schwachstelle verstehen, und sie variieren ohnehin je nach Betriebssystem, Plattform, Programm und Konfiguration.

Es ist möglich, die zu verwenden %s format-Parameter zum Lesen von Daten. Sie können die Daten des ursprünglichen Formatstrings einlesen printf(text)daher können Sie damit alles aus dem Stapel lesen:

./vulnerable AAAA%08x.%08x.%08x.%08x
This is how you print correctly:
AAAA%08x.%08x.%08x.%08x
This is how not to print:
AAAA.XXXXXXXX.XXXXXXXX.XXXXXXXX.41414141
some_value @ 0x08049794 = -72 [0xffffffb8]

Schreiben auf beliebige Speicheradressen

Du kannst den … benutzen %n Formatbezeichner zum Schreiben an eine (fast) beliebige Adresse. Nehmen wir wieder unser verwundbares Programm oben an und versuchen wir, den Wert von zu ändern some_valuedie sich befindet bei 0x08049794wie oben zu sehen:

./vulnerable $(printf "\x94\x97\x04\x08")%08x.%08x.%08x.%n
This is how you print correctly:
??%08x.%08x.%08x.%n
This is how not to print:
??XXXXXXXX.XXXXXXXX.XXXXXXXX.
some_value @ 0x08049794 = 31 [0x0000001f]

Wir haben überschrieben some_value mit der Anzahl der vor dem geschriebenen Bytes %n Spezifizierer wurde gefunden (man printf). Wir können die Formatzeichenfolge selbst oder die Feldbreite verwenden, um diesen Wert zu steuern:

./vulnerable $(printf "\x94\x97\x04\x08")%x%x%x%n
This is how you print correctly:
??%x%x%x%n
This is how not to print:
??XXXXXXXXXXXXXXXXXXXXXXXX
some_value @ 0x08049794 = 21 [0x00000015]

Es gibt viele Möglichkeiten und Tricks zum Ausprobieren (direkter Parameterzugriff, große Feldbreite, die Wrap-Around möglich macht, Erstellen eigener Primitiven), und dies berührt nur die Spitze des Eisbergs. Ich würde vorschlagen, mehr Artikel über fmt-String-Schwachstellen zu lesen (Phrack hat einige meist ausgezeichnete, obwohl sie ein wenig fortgeschritten sein können) oder ein Buch, das sich mit dem Thema befasst.


Haftungsausschluss: Die Beispiele sind entnommen [although not verbatim] von dem Buch Hacking: Die Kunst der Ausbeutung (2. Aufl.) von Jon Erickson.

  • Hallo, ich frage mich wie $(printf "\x94\x97\x04\x08")%08x.%08x.%08x.%n funktioniert? warum ist “??” für das ganze Los vorne ausgedruckt? Wie hat es die Speicheradresse 0x09049794 erreicht? Danke vielmals

    – Einheri

    9. Januar 2014 um 9:25 Uhr


  • Das ?? wird ausgegeben, da $(printf “\x94\x97\x04\x08”) versucht, diese Werte in Zeichen umzuwandeln. Da diese Werte keine druckbaren Zeichen sind, druckt Ihr Terminal ein ? stattdessen. (versuchen Sie printf “\x41\x42\x43\x44”, was ABCD druckt, da dies gültige ASCII-Werte sind)

    – Freek Kalter

    24. Januar 2014 um 19:56 Uhr


Benutzeravatar von Jonathan Leffler
Jonathan Leffler

Es ist interessant, dass niemand das erwähnt hat n$ von POSIX unterstützte Notation. Wenn Sie als Angreifer den Formatstring kontrollieren können, können Sie Notationen verwenden wie:

"%200$p"

200 zu lesenth Gegenstand auf dem Stapel (falls vorhanden). Die Absicht ist, dass Sie alle auflisten sollten n$ Zahlen von 1 bis zum Maximum, und es bietet eine Möglichkeit, die Reihenfolge der Parameter in einer Formatzeichenfolge neu zu ordnen, was beim Umgang mit I18N (L10N, G11N, M18N*).

Einige (wahrscheinlich die meisten) Systeme sind jedoch etwas nachlässig, wenn es darum geht, wie sie die validieren n$ Werte und dies kann zu Missbrauch durch Angreifer führen, die die Formatzeichenfolge kontrollieren können. Kombiniert mit der %n Formatbezeichner, kann dies dazu führen, dass an Zeigerstellen geschrieben wird.


* Die Akronyme I18N, L10N, G11N und M18N stehen für Internationalisierung, Lokalisierung, Globalisierung bzw. Multinationalisierung. Die Zahl steht für die Anzahl der weggelassenen Buchstaben.

  • Danke für die Erwähnung! Ich habe nach einer Erklärung gesucht.

    – Mikefox2k

    30. Juli 2021 um 21:18 Uhr

Benutzeravatar von user541686
Benutzer541686

Ah, die Antwort steht im Artikel!

Unkontrollierte Formatzeichenfolgen sind eine Art von Software-Schwachstelle, die um 1999 entdeckt wurde und für Sicherheits-Exploits verwendet werden kann. Bisher als harmlos geltende Format-String-Exploits können ausgenutzt werden ein Programm zum Absturz bringen oder zu schädlichen Code ausführen.

Ein typischer Exploit verwendet eine Kombination dieser Techniken, um ein Programm zu zwingen, die Adresse einer Bibliotheksfunktion oder die Rückgabeadresse auf dem Stack mit einem Zeiger auf bösartigen Shellcode zu überschreiben. Die Padding-Parameter für Formatbezeichner werden verwendet, um die Anzahl der ausgegebenen Bytes und die zu steuern %x token wird verwendet, um Bytes aus dem Stapel zu entfernen, bis der Anfang der Formatzeichenfolge selbst erreicht ist. Der Anfang des Formatstrings ist so gestaltet, dass er die Adresse enthält, die das %n Format-Token kann dann mit der Adresse des auszuführenden bösartigen Codes überschrieben werden.

Das ist weil %n verursacht printf zu schreiben Daten in eine Variable, die sich auf dem Stack befindet. Aber das bedeutet, dass es willkürlich etwas schreiben könnte. Alles, was Sie brauchen, ist, dass jemand diese Variable verwendet (es ist relativ einfach, wenn es sich um einen Funktionszeiger handelt, dessen Wert Sie gerade herausgefunden haben, wie Sie ihn steuern können), und er kann Sie dazu bringen, alles willkürlich auszuführen.

Schauen Sie sich die Links im Artikel an; sie sehen interessant aus.

Ich würde die Lektüre empfehlen Dies Vorlesungsnotiz über Format-String-Sicherheitsanfälligkeit. Es beschreibt detailliert, was passiert und wie, und enthält einige Bilder, die Ihnen helfen könnten, das Thema zu verstehen.

Benutzeravatar von user541686
Benutzer541686

AFAIK liegt es hauptsächlich daran, dass es Ihr Programm zum Absturz bringen kann, was als Denial-of-Service-Angriff angesehen wird. Sie müssen lediglich eine ungültige Adresse angeben (praktisch irgendetwas mit ein paar %s‘s funktioniert garantiert) und es wird zu einem einfachen Denial-of-Service (DoS)-Angriff.

Nun, es ist theoretisch möglich damit im Falle eines Ausnahme-/Signal-/Interrupt-Handlers irgendetwas ausgelöst wird, aber herauszufinden, wie das geht, ist mir ein Rätsel – Sie müssen herausfinden, wie es geht schreiben auch beliebige Daten in den Speicher.

Aber warum kümmert es jemanden, wenn das Programm abstürzt, fragen Sie sich vielleicht? Ist das nicht nur für den Benutzer unangenehm (der es sowieso verdient hat)?

Das Problem ist, dass auf einige Programme von mehreren Benutzern zugegriffen wird, sodass deren Absturz nicht zu vernachlässigende Kosten verursacht. Oder sie sind manchmal entscheidend für den Betrieb des Systems (oder vielleicht sind sie gerade dabei, etwas sehr Wichtiges zu tun), in diesem Fall kann dies Ihre Daten beschädigen. Natürlich, wenn Sie Notepad zum Absturz bringen, könnte es niemanden interessieren, aber wenn Sie CSRSS zum Absturz bringen (von dem ich glaube, dass es tatsächlich eine ähnliche Art von Fehler hatte – speziell einen Double-Free-Fehler), dann ja, das gesamte System geht mit Ihnen unter .


Aktualisieren:

Sehen dieser Link für den CSRSS-Bug, auf den ich mich bezog.


Bearbeiten:

Beachten Sie das Das Lesen beliebiger Daten kann genauso gefährlich sein als Ausführen von beliebigem Code! Wenn Sie ein Passwort, ein Cookie usw. lesen, ist dies genauso schwerwiegend wie die Ausführung eines willkürlichen Codes – und das ist es trivial wenn Sie gerade genug Zeit haben, um genügend Formatzeichenfolgen auszuprobieren.

  • Danke Mehrdad, ich denke, ein Programm zum Absturz zu bringen, wäre im Allgemeinen immer noch einfacher, als in der Lage zu sein, Ihren eigenen Code auszuführen. Also suche ich speziell nach einer Antwort auf die Ausführung des Codes des Angreifers. Aber trotzdem muss ich für eine gute Antwort stimmen 🙂

    – Atul Goyal

    18. September 2011 um 5:37 Uhr

  • @Atul: Haha danke. 🙂 Ja, wenn jemand ein Beispiel für die Ausführung eines beliebigen Codes finden kann, dann würde ich es DEFINITIV sehen wollen!

    – Benutzer541686

    18. September 2011 um 5:38 Uhr

  • @Atul: Ich habe eine andere Antwort aus dem Artikel selbst gepostet. Wenn ich es schaffe, den Code zu schreiben, werde ich das auch tun — aber das ist ein direkter Angriff der Art, nach der Sie suchen.

    – Benutzer541686

    18. September 2011 um 5:41 Uhr

  • Diese Antwort ist Unsinn. Sie sollten es in Anbetracht Ihrer löschen Korrekt Antworten.

    – Gabe

    18. September 2011 um 5:48 Uhr

  • Der OP wollte wissen wie printf kann ausgenutzt werden, um schädlichen Code auszuführen. Sie haben von einem DoS-Angriff geschrieben. Das mag ein Exploit sein, aber es erklärt nicht, wie schädlicher Code ausgeführt wird. Das CSRSS wird nicht verwendet printfalso beantwortet es auch nicht die Frage des OP.

    – Gabe

    18. September 2011 um 5:59 Uhr

  • Danke Mehrdad, ich denke, ein Programm zum Absturz zu bringen, wäre im Allgemeinen immer noch einfacher, als in der Lage zu sein, Ihren eigenen Code auszuführen. Also suche ich speziell nach einer Antwort auf die Ausführung des Codes des Angreifers. Aber trotzdem muss ich für eine gute Antwort stimmen 🙂

    – Atul Goyal

    18. September 2011 um 5:37 Uhr

  • @Atul: Haha danke. 🙂 Ja, wenn jemand ein Beispiel für die Ausführung eines beliebigen Codes finden kann, dann würde ich es DEFINITIV sehen wollen!

    – Benutzer541686

    18. September 2011 um 5:38 Uhr

  • @Atul: Ich habe eine andere Antwort aus dem Artikel selbst gepostet. Wenn ich es schaffe, den Code zu schreiben, werde ich das auch tun — aber das ist ein direkter Angriff der Art, nach der Sie suchen.

    – Benutzer541686

    18. September 2011 um 5:41 Uhr

  • Diese Antwort ist Unsinn. Sie sollten es in Anbetracht Ihrer löschen Korrekt Antworten.

    – Gabe

    18. September 2011 um 5:48 Uhr

  • Der OP wollte wissen wie printf kann ausgenutzt werden, um schädlichen Code auszuführen. Sie haben von einem DoS-Angriff geschrieben. Das mag ein Exploit sein, aber es erklärt nicht, wie schädlicher Code ausgeführt wird. Das CSRSS wird nicht verwendet printfalso beantwortet es auch nicht die Frage des OP.

    – Gabe

    18. September 2011 um 5:59 Uhr

1415730cookie-checkWie kann eine Format-String-Schwachstelle ausgenutzt werden?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy