Aus Linux-Magazin 12/2011

Insecurity Bulletin – Buffer Overflows

© complize, photocase.com

Die neue Reihe “Insecurity Bulletin” widmet sich Sicherheitslücken in Linux und Open-Source-Software. Dabei dienen aktuelle Schwachstellen als Anschauungsmaterial für typische Programmierfehler. Die erste Folge behandelt zwei Fälle von Buffer Overflow.

Der Buffer Overflow ist eine Sicherheitslücke, vor der sich der C-Programmierer stets in Acht nehmen muss. Zu den jüngsten Opfern dieser Schwäche gehören zwei Linux-/Unix-Daemons.

Rsyslog

Das GPLv3-lizenzierte Rsyslog implementiert und erweitert das unter Linux und Unix verbreitete Syslog-Protokoll zum Überwachen von Systemereignissen. Die Filterfunktionen der Software helfen umfangreiche Protokolldaten effizient zu verarbeiten. Ein im September entdeckter Buffer Overflow [1] führte dazu, dass ein Angreifer das Programm zum Absturz bringen konnte.

Rsyslog erlaubt es dem Admin, jeder Nachricht ein Tag zuzuordnen, sodass sich die Logdatei später einfach mit Grep durchsuchen lässt. Für das Verarbeiten dieser Tags ist »parseLegacySyslogMsg()« in der Datei »tools/syslogd.c« zuständig (Listing 1). Die Funktion liest das Tag ein und legt es im Puffer »bufParseTAG« ab, wobei sie dafür eine Maximallänge von »CONF_TAG_MAXSIZE« Zeichen vorsieht. Der Code in Listing 1 bearbeitet alle Nachrichten, die nicht im RFC-5424-Format vorliegen, also auch solche im RFC-3164-Format.

Listing 1

tools/syslogd.c

01 [...]
02 int i; /* general index for parsing */
03 uchar bufParseTAG[CONF_TAG_MAXSIZE];
04 uchar bufParseHOSTNAME[CONF_HOSTNAME_MAXSIZE];
05 [...]
06 while(lenMsg > 0 && *p2parse != ':' && *p2parse != ' ' && i < CONF_TAG_MAXSIZE) {
07 bufParseTAG[i++] = *p2parse++;
08 --lenMsg;
09 }
10 if(lenMsg > 0 && *p2parse == ':') {
11 ++p2parse;
12 --lenMsg;
13 bufParseTAG[i++] = ':';
14 }
15 [...]
16 bufParseTAG[i] = '\0'; /* terminate string */

Der Programmierfehler tritt in der While-Schleife ab Zeile 6 auf. Die dortigen Anweisungen füllen sukzessive den Puffer »bufParseTAG« , die Variable »i« überwacht dabei die aktuelle Position im Puffer. Sie kommt kurz darauf ins Spiel, um an das Ende der Zeichenkette ein oder zwei zusätzliche Zeichen anzuhängen: »:\0« oder nur »\0« .

Zwei zu viel

Die Schwäche besteht darin, dass die While-Schleife bei langen Tag-Strings erst abbricht, wenn »i« so groß wie »CONF_TAG_MAXSIZE« ist (Zeile 6). Der Puffer bekommt später aber noch ein oder zwei Zeichen hinzugefügt (Zeilen 13 und 16). Einem Angreifer wäre es also möglich, mit einem Tag, das länger ist als in »CONF_TAG_MAXSIZE« festgelegt, den Puffer um ein oder zwei Zeichen überlaufen zu lassen.

Die Auswirkungen eines Überlaufs sind plattform- und systemspezifisch: Entscheidend ist die Reihenfolge der Funktionsvariablen auf dem Stack und ob es sich um ein Little- oder Big-Endian System handelt. Beispielsweise kann es zum Überschreiben der Variablen »i« kommen, falls sie im Speicher nach »bufParseTAG« abgelegt ist.

Diese Sicherheitslücke betrifft die Rsyslog-Versionen 4.6.0 bis 4.6.7 sowie 5.2.0 bis 5.8.4. Auf Systemen mit einem Buffer-Overflow-Schutz wie Stack Guard kann es passieren, dass die Schutzvariable (siehe Kasten “Schutzmechanismen”) direkt nach der Variablen »bufParseTAG« im Speicher angesiedelt ist. In diesem Fall führt der Overflow zum Beenden von Rsyslog, weil Stack Guard merkt, dass diese Variable modifiziert wurde.

Schutzmechanismen

Es gibt Schutzmechanismen, um Overflows wie im Fall von Rsyslog zu verhindern. Dazu gehört die Software Stack Guard [2], die GCC um die entsprechende Schutzfunktion erweitert. Diese Mechanismen sortieren die Daten auf dem Stack Frame von Funktionsaufrufen um und erweitern sie um Schutzvariablen.

Bei einer Funktion wie der folgenden legt der Compiler die Variablen in einer bestimmten Reihenfolge auf dem Stack ab:

int function()
{ int a; char b[5]; char c[4]; [...]
}

Der Stack sieht dann folgendermaßen aus:

c
b
a
[...]
Return-Adresse

Lässt ein Angreifer nun »c« oder »b« überlaufen, kann er »a« verändern – unter Umständen sogar den Kontrollfluss des Programms, wenn er die Return-Adresse auf von ihm erzeugten Code lenkt.

Stack Guard und andere Buffer-Overflow-Schutzprogramme wie Pro Police oder Stack Ghost sortieren die gefährdeten Variablen um, sodass beispielsweise beim angegebenen Funktionscode der Stack mit Schutzmaßnahmen wie folgt aussähe:

a
c
b
Canary-Variable
[...]
Return-Adresse

Hier ist zum einen die Variable »a« verschoben, sodass sie von einem möglichen Überlauf der anderen Puffer nicht betroffen ist. Zum anderen hat der Schutzmechanismus am Ende des Variablenblocks auf dem Stack eine Schutzvariable hinzugefügt, die so genannte Canary-Variable. Läuft beispielsweise die Variable »b« über, so verändert das auch die benachbarte Canary-Variable. Sie warnt vor dem Overflow – wie der Kanarienvogel den Bergmann vor Grubengas, daher der Name.

Cyrus IMAP

Auch der IMAP-Server Cyrus wurde im September Opfer eines Stack Buffer Overflow [3]. Verantwortlich ist eine Schwachstelle im NNTP-Code, die es einem entfernten Angreifer unter Umständen erlaubt, Befehle auf dem System auszuführen. Der Fehler steckt in der Funktion »split_wildmats()« in der Datei »imap/nntpd.c« und tritt beim Verarbeiten von NNTP-Wildmat-Daten auf. Wildmat ist ein Pattern-Matching-Format, das in RFC 3977 für NNTP definiert ist.

Der Fehler besteht darin, dass Cyrus die Funktion »strcpy()« zum Behandeln der Wildmat-Daten verwendet. Schon die Manpage zu »strcpy()« macht aber klar, warum das keine gute Idee ist: Die Funktion kopiert eine Zeichenkette bis zum Terminierungszeichen von einem String, auf den das erste Argument zeigt, in den Puffer, auf den das zweite zeigt.

Ob diese Daten auch wirklich in den für das Ziel allozierten Speicher passen, prüft »strcpy()« aber nicht. Diese Funktion ist daher für unzählige Buffer-Overflow-Schwachstellen verantwortlich – ja, es ist schlechte Programmierpraxis, sie überhaupt zu verwenden. Grundsätzlich sollte statt »strcpy()« die Funktion »strncpy()« zum Einsatz kommen, die als drittes Argument die Anzahl der zu kopierenden Zeichen annimmt. Wenn sichergestellt ist, dass diese Zeichenzahl in den allozierten Speicher passt, ist die Gefahr gebannt.

Wie die Schwachstelle in der Funktion »split_wildmats()« aussieht, zeigt Listing 2. In dieser Schleife kopiert »strcpy()« die Zeichenkette (Zeile 14), was bei bestimmten Eingaben zum Überlauf führen kann. Zuvor wird nämlich in derselben Funktion Folgendes gesetzt:

char pattern[MAX_MAILBOX_BUFFER] =? "", *p, *c;
p = pattern + strlen(pattern);

Listing 2

imap/nntpd.c

01 do {
02 if ((c = strrchr(str, ',')))
03 *c++ = '\0';
04 else
05 c = str;
06
07 if (!(n % 10)) /* alloc some more */
08 wild = xrealloc(wild, (n + 11) * sizeof(struct wildmat));
09
10 if (*c == '!') wild[n].not = 1; /* not */
11 else if (*c == '@') wild[n].not = -1; /* absolute not (feeding) */
12 else wild[n].not = 0;
13
14 strcpy(p, wild[n].not ? c + 1 : c);
15 wild[n++].pat = xstrdup(pattern);
16 } while (c != str);

Der Puffer »pattern« besitzt damit nur eine feste Größe von »MAX_MAILBOX_BUFFER« . Diese Schwachstelle lässt sich einfach beheben, indem man die »strcpy()« -Funktion durch die sichere Alternative »strncpy()« samt der korrekt berechneten Zeichenzahl ersetzt:

strncpy(p, wild[n].not ? c + 1 :? c, pattern+sizeof(pattern) - p);
pattern[sizeof(pattern)-1] = '\0';

Sollte die Option »allowanonymouslogin« in »imap.conf« gesetzt sein, lässt sich diese Sicherheitslücke sogar ohne Authentifikation ausnutzen.

Falsche Entwarnung

Kurz nach Bekanntwerden des Fehlers hieß es, dass Systeme, die mit der »FORTIFY_SOURCE« -Option kompiliert wurden, nicht betroffen seien, also beispielsweise RHEL 5 und 6 sowie Fedora. Diese Meldung ist jedoch nicht korrekt, allenfalls lässt sich ein Angriff detektieren, falls Cyrus IMAP mit einem Buffer-Overflow-Schutz wie Stack Smashing Protector (SSP) übersetzt wird. Betroffen sind die Cyrus-IMAP-Versionen 2.3 vor 2.3.17 und 2.4 vor 2.4.11. (mhu)

Infos

  1. “Potential DoS with malformed tag” (CVE-2011-3200): http://www.rsyslog.com/potential-dos-with-malformed-tag/
  2. Stack Guard: http://immunix.org/stackguard.html
  3. “Latest Updates” zu Cyrus IMAP (CVE-2011-3208): http://www.cyrusimap.org/mediawiki/index.php/Latest_Updates

Der Autor

Mark Vogelsberger ist derzeit wissenschaftlicher Mitarbeiter am Institute for Theory and Computation der Harvard University, wo er sich mit Simulationen zur Strukturbildung im Universum beschäftigt. Er war von 1999 bis 2010 Autor der “Insecurity News” des Linux-Magazins und schreibt nun auf https://www.linux-magazin.de die Online-Ausgabe des “Insecurity Bulletin”.

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDFUmfang: 2 HeftseitenPreis €0,99
(inkl. 19% MwSt.)
LINUX-MAGAZIN KAUFEN
EINZELNE AUSGABE Print-Ausgaben Digitale Ausgaben
ABONNEMENTS Print-Abos Digitales Abo
TABLET & SMARTPHONE APPS Readly Logo
E-Mail Benachrichtigung
Benachrichtige mich zu:
0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben