Rsyslog: Denial-of-Service-Attacke mit 2 Byte Buffer Overflow
Rsyslog implementiert und erweitert das unter Linux/Unix verbreitete Syslog-Protokoll zum Überwachen von Systemereignissen. Vor allem die Filterfunktionen erlauben ein effizienteres Verarbeiten großer Syslog-Daten. Ein kürzlich entdeckter Buffer Overflow in Rsyslog führt dazu, dass ein Angreifer das Programm zum Absturz bringen kann.
Syslog erlaubt es dem Admin, jeder Nachricht ein Tag zuzuordnen, wodurch sich die Log-Datei später einfach mit Grep durchsuchen lässt. Für das Verarbeiten dieser Tags ist die Funktion "parseLegacySyslogMsg()" in der Datei "tools/syslogd.c" zuständig:
...
int i; /* general index for parsing */
uchar bufParseTAG[CONF_TAG_MAXSIZE];
uchar bufParseHOSTNAME[CONF_HOSTNAME_MAXSIZE];
...
while(lenMsg > 0 && *p2parse != ':' && *p2parse != ' ' && i < CONF_TAG_MAXSIZE) {
bufParseTAG[i++] = *p2parse++;
--lenMsg;
}
if(lenMsg > 0 && *p2parse == ':') {
++p2parse;
--lenMsg;
bufParseTAG[i++] = ':';
}
...
bufParseTAG[i] = '\0'; /* terminate string */
Diese Zeilen lesen das Tag ein und legen es im "bufParseTAG"-Puffer ab, wobei dafür eine Maximallänge von "CONF_TAG_MAXSIZE" Zeichen vorgesehen ist. Obiger Code wird für alle Nachrichten aufgerufen, die nicht im RFC-5424-Format vorliegen, also auch für solche im RFC-3164-Format. Der Programmierfehler tritt in der While-Schleife auf. Dort wird der Puffer "bufParseTAG" sukzessive gefüllt, und die Variable "i" überwacht dabei die aktuelle Position im Puffer. Diese wird kurz darauf benötigt, um an das Ende des "bufParseTAG"-Strings ein oder zwei zusätzliche Zeichen anzuhängen: ":\0" oder nur "\0".
Das Problem besteht nun darin, dass die While-Schleife bei langen Tag-Strings erst bei "i==CONF_TAG_MAXSIZE" abbricht, obwohl dem Puffer später noch ein oder zwei Zeichen hinzugefügt werden. Das heißt, es ist für einen Angreifer möglich, mit einem Tag, das länger ist als in "CONF_TAG_MAXSIZE" festgelegt, den "bufParseTAG"-Puffer um ein oder zwei Zeichen überlaufen zu lassen.
Die Auswirkungen eines solchen Überlaufs sind plattform-/systemspezifisch, da es auf die Reihenfolge der Funktions-Variablen auf dem Stack ankommt - und darauf, ob es sich um ein Little- oder Big-Endian System handelt. Die Variable "i" kann überschrieben werden, falls sie im Speicher nach der "bufParseTAG"-Variable abgelegt ist.
Auf Systemen mit einem Buffer-Overflow-Schutz wie Stack Guard kann es vorkommen, dass die Canary-Variable direkt nach "bufParseTAG" im Speicher angesiedelt ist. In diesem Fall führt der Overflow zum Beenden von Rsyslog, weil Stack Guard bemerkt, dass die Canary-Variable modifziert wurde.
Betroffen sind die Rsyslog-Versionen 4.6.0 bis 4.6.7 und 5.2.0 bis 5.8.4.
Stack-Buffer-Overflow-Schutzmechanismen
Stack Overflows sind sehr verbreitet und stellen grundsätzlich ein Sicherheitsrisiko dar. Aus diesem Grund existieren dagegen mehrere Schutzmechanismen, beispielsweise Stack Guard, das den GCC um die entsprechende Schutzfunktion erweitert. Diese Mechanismen arbeiten alle nach einem ähnlichen Prinzip: Sie sortieren die Daten auf dem Stack-Frame von Funktionsaufrufen um und erweitern sie um Schutzvariablen (so gennante Canary-Variablen). Diese Modifikationen haben typischerweise keinen Performance-Verlust zur Folge und kommen deshalb häufig zum Einsatz.
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 ungefähr so aus:
c: .... b: ..... a: . ... return address
Wird nun "c" oder "b" überlaufen, lässt sich "a" verändern, ja sogar der Kontrollfluss des Programms, wenn die Return-Adresse auf einen vom Angreifer erzeugten Code gelenkt wird, was üblicherweise Assembler-Shellcode ist. Stack Guard und andere Buffer-Overflow-Schutzprogramme wie Pro Police oder Stack Ghost verwenden Canary-Variablen, um Stack-Overflows zu erkennen: Zusätzlich werden Overflow-gefährdete Variablen auch oftmals umsortiert, so dass beispielsweise beim obigen Funktionscode der Stack mit Schutzmaßnahmen so aussähe:
a: . c: .... b: ..... Canary Variable ... return address
Zunächst einmal wurde die "a"-Variable verschoben, so dass sie von einem möglichen "c"- oder "b"-Überlauf nicht betroffen ist. Außerdem wurde die Canary-Variable an das Ende des Variablen-Blocks auf dem Stack gesetzt. Wird nun beispielsweise die Variable "b" überlaufen, so verändert das auch die Canary-Variable. Der Overflow lässt sich somit entdecken.
Alle Rezensionen aus dem Linux-Magazin
- Buecher/07 Bücher über 3-D-Programmierung sowie die Sprache Dart
- Buecher/06 Bücher über Map-Reduce und über die Sprache Erlang
- Buecher/05 Bücher über Scala und über Suchmaschinen-Optimierung
- Buecher/04 Bücher über Metasploit sowie über Erlang/OTP
- Buecher/03 Bücher über die LPI-Level-2-Zertifizierung
- Buecher/02 Bücher über Node.js und über nebenläufige Programmierung
- Buecher/01 Bücher über Linux-HA sowie über PHP-Webprogrammierung
- Buecher/12 Bücher über HTML-5-Apps sowie Computer Vision mit Python
- Buecher/11 Bücher über Statistik sowie über C++-Metaprogrammierung
- Buecher/10 Bücher zu PHP-Webbots sowie zur Emacs-Programmierung
Insecurity Bulletin
Im Insecurity Bulletin widmet sich Mark Vogelsberger aktuellen Sicherheitslücken sowie Hintergründen und Security-Grundlagen. mehr...


