Open Source im professionellen Einsatz

© Julian Fletcher, 123RF

Insecurity Bulletin: Formatstring-Schutz der Glibc ausgehebelt

Verstärkung für C

Die GNU-C-Bibliothek besitzt mit FORTIFY_SOURCE eine eingebaute Armierung, die Formatstring-Exploits verhindert. Doch erst kürzlich haben die Glibc-Entwickler eine mehr als ein Jahr alte Sicherheitslücke geschlossen, über die sich die Schutzeinrichtung umgehen ließ.

Formatstring-Fehler in C-Programmen waren vor mehr als zehn Jahren weit verbreitet. Heute sind sie weitgehend aus den Schwachstellen-Statistiken verschwunden. Das liegt zum einen an der Sorgfalt der Entwickler, zum anderen an Compiler-Optionen, die versuchen mögliche Formatstring-Attacken trotz falscher Programmierung abzuwehren. Eine dieser Sicherheitsmaßnahmen beruht auf der Option »FORTIFY_SOURCE« der Bibliothek Glibc.

Erst im März 2012 hat jedoch der Google-Entwickler Kees Cook eine bereits länger bekannte Schwachstelle [1] in diesem Schutzmechanismus korrigiert. Die Sicherheitslücke erlaubte es, Formatstring-Fehler trotz »FORTIFY_SOURCE« auszunutzen. Ein Fehler beim Einsatz von Formatstrings [2] in C-Code sieht in seiner einfachsten Form wie folgt aus:

printf(userinput);

Dabei ist »userinput« ein vom Benutzer übergebener String. Für diese Zeichenkette darf ein Angreifer einen beliebigen Formatstring angeben, zum Beispiel:

userinput="%08x.%08x.%08x.%08x.%08x"

Mit diesem String würde das Programm Speicher des Stack auslesen und anzeigen. Eine sichere Verwendung sähe dagegen so aus:

printf("%s", userinput);

Zwei Hauptformen von Formatstring-Attacken haben sich etabliert: das Auslesen und das Beschreiben von beliebigem Speicher. Die erste wird häufig mit »%s« realisiert. Das Ziel besteht darin, mit »%s« den Speicher an einer vorgegebenen Adresse auszulesen. Dazu bringt der Angreifer im Formatstring sowohl die Zieladresse als auch »%s« unter. Da der Formatstring selbst auf dem Stack liegt, kann »%s« den Speicher an der angegebenen Adresse lesen.

Das Beschreiben von Speicher haben Hacker oft über den Formatstring-Identifier »%n« realisiert, denn dieser verhält sich anders als alle anderen Identifier: Er gibt nichts aus, sondern sorgt dafür, dass der Rechner die Zahl der geschrieben Bytes an eine bestimmte Adresse schreibt. Ein Angreifer kann dies ausnutzen, um Speicherbereiche zu überschreiben und so Programmcode auszuführen.

Offensichtlich ist die zweite Angriffsform deutlich kritischer, da sie im schlimmsten Fall das Ausführen von Befehlen mit Rootrechten ermöglicht. In der Tat waren um das Jahr 2000 herum zahlreiche Serverapplikation anfällig für vergleichbare Schwachstellen. Ein positiver Aspekt von Formatstring-Fehlern ist, dass sie im Programmcode recht leicht zu finden sind. Das erklärt auch, warum diese Angriffsform heute fast ausgestorben ist.

Zugriff auf Parameter

Nach den ersten veröffentlichten Exploits verfeinerten die Angreifer im Laufe der Zeit ihre Attacken. Sie machten sich weitere Features von Formatstrings zu Nutze. Eine dieser Techniken heißt Direct Parameter Access. Diese Eigenschaft der Formatstrings ermöglicht eine flexiblere Handhabung von Formatstrings, wie Listing 1 zeigt. Der Programmierer hat hierbei mehr Kontrolle darüber, welche Daten sein Code an welcher Stelle im String ausgibt, da er durch die Notation »%Zahl$s« die gewünschte Variable spezifizieren kann.

Listing 1

Direct Parameter Access

01 printf("%1$s  %2$s", "String1", "String2");
02 // gibt "String 1  String 2" aus
03 printf("%2$s  %1$s", "String1", "String2");
04 // gibt "String 2  String 1" aus

Eingebauter Schutz

Unzählige Formatstring-Attacken machten sich Programmierfehler im Zusammenhang mit der Funktion »printf()« und deren Verwandten zu Nutze. Da all diese Funktionen in der Glibc implementiert sind, lag es nahe, einen allgemeinen Schutz in die Bibliothek einzubauen, der auch bei falscher Programmierung Attacken verhindert. Das haben die Entwickler mit dem »FORTIFY_SOURCE« -Patch realisiert, das sowohl Speicherschreib-Attacken via »%n« als auch Angriffe via Direct Parameter Access verhindert. Der Schutz wird aktiv, sobald man ein Programm mit dem GCC-Flag »-D_FORTIFY_SOURCE=2« übersetzt.

Wer sich den Assembler-Code der erzeugten Binärdatei ansieht, stellt fest, dass der Compiler Funktionen wie »printf()« ersetzt hat, beispielsweise durch »printf_chk()« . Diese Funktion ist in »libc/debug/printf_chk.c« implementiert (Listing 2). Beim Aufruf von »printf()« im Benutzerprogramm ist »flag=1« gesetzt und damit wird das Flag »_IO_FLAGS2_FORTIFY« für den »FILE« -Stream-Zeiger (beispielsweise Stdout) aktiviert. Dieses Flag signalisiert für alle weiteren Funktionen, die auf der »FILE« -Struktur arbeiten, dass sie Extrakontrollen durchführen sollen, die Angriffe verhindern.

Listing 2

libc/debug/printf_chk.c

01 /* Write formatted output to stdout from the format string FORMAT.  */
02 int ___printf_chk (int flag, const char *format, ...)
03 {
04   va_list ap;
05   int done;
06
07   _IO_acquire_lock_clear_flags2 (stdout);
08   if (flag > 0)
09     stdout->_flags2 |= _IO_FLAGS2_FORTIFY;
10
11   va_start (ap, format);
12   done = vfprintf (stdout, format, ap);
13   va_end (ap);
14
15   if (flag > 0)
16     stdout->_flags2 &= ~_IO_FLAGS2_FORTIFY;
17   _IO_release_lock (stdout);
18
19   return done;
20 }

Um Schreib-Attacken mit »%n« zu verhindern, sind in »libc/stdio-common/vfprintf.c« mehrere Kontrollmechanismen eingebaut, die das gesetzte Flag »_IO_FLAGS2_FORTIFY« einschaltet. Sie brechen die Ausführung des Programms ab, sobald sie feststellen, dass die »%n« -Adresse in einem beschreibbaren Speicherbereich wie Stack, BSS, Data oder im Heap liegt.

Auch wenn hiermit immer noch Denial-of-Service-Attacken möglich sind (denn das Programm wird ja beendet), so vereitelt es doch gefährliche Speichermanipulationen, die zum Ausführen von Code führen können. Das stellt einen zentralen Schutz gegen schreibende Formatstring-Attacken dar.

Diesen Artikel als PDF kaufen

Express-Kauf als PDF

Umfang: 3 Heftseiten

Preis € 0,99
(inkl. 19% MwSt.)

Als digitales Abo

Als PDF im Abo bestellen

comments powered by Disqus

Ausgabe 07/2013

Preis € 6,40

Insecurity Bulletin

Insecurity Bulletin

Im Insecurity Bulletin widmet sich Mark Vogelsberger aktuellen Sicherheitslücken sowie Hintergründen und Security-Grundlagen. mehr...

Linux-Magazin auf Facebook