Der freie Webserver Lighttpd arbeitet ressourcenschonend und punktet vor allem bei parallelem Zugriff auf große Dateien gegenüber Apache. Youtube beispielsweise setzt eine modifizierte Lighttpd-Variante ein. Eine kürzlich entdeckte Sicherheitslücke hat zur Folge, dass ein entfernter Angreifer Denial-of-Service-Attacken gegen den Server durchführen kann.
Lighttpd implementiert HTTP-Authentisierung in der Quelltextdatei “src/http_auth.c”. Darin befindet sich auch eine Funktion zur Base64-Dekodierung von Benutzereingaben. Sie wird benötigt, da Base64 beim Übertragen via HTTP zum Einsatz kommt. Der dabei erlaubte Zeichenumfang umfasst auch Nicht-ASCII Zeichen mit einem Code größer als 0x7f=127, was sich beim Dekodieren für eine Buffer-Overflow-Attacke ausnutzen lässt.
Der Programmierfehler befindet sich in der Funktion “base64_decode()” und besteht darin, dass der Base64-String als “char”-Zeichenkette abgespeichert wird. Auf den meisten Plattformen ist “char” allerdings vorzeichenbehaftet und umfasst Werte von -128 bis +127. Dies bedeutet, dass ein Base64-Zeichen größer als 0x7f durch einen arithmetischen Überlauf als negativer Wert interpretiert wird. Das ist zwar nicht korrekt, stellt aber an sich noch keine Sicherheitslücke dar. Die Schwachstelle entsteht erst im Zusammenspiel mit den anderen Anweisungen der Funktion “base64_decode()”:
static const short base64_reverse_table[256] = ...;
static unsigned char * base64_decode(buffer *out, const char *in) { ... int ch, ...; size_t i; ... ch = in[i]; ... ch = base64_reverse_table[ch]; ...
}
Hierbei ist “base64_reverse_table[]” einfach ein Lookup-Array, in dem Base64-Codes nachgesehen werden. Dieses Array hat korrekterweise 255 Einträge, da wie oben erwähnt Base64-Zeichen größer als 127 sein können. Die Funktion “base64_decode()” erhält den Base64-String in “const char *in” übergeben, welches anfällig für den Überlauf ist. Da nun “int ch” aus “in[i]” bestimmt wird, ist es möglich einen negativen Wert für “ch” zu erzeugen, der dann als Index für das Array “base64_reverse_table[]” verwendet wird. Dies führt zu einem ungültigen Speicherzugriff und kann einen Segmentation Fault hervorrufen. Ein entfernter Angreifer kann diese Schwachstelle also ausnutzen, um Denial-of-Service-Attacken gegen den HTTP-Server durchzuführen.
Zu dem Segmentation Fault kommt es allerdings nur, wenn wirklich auf ein ungültiges Segment zugegriffen wird, und das setzt voraus, dass das “.rodata”-Segment nicht genügend Daten vor “base64_reverse_table[]” besitzt. Laut dem oben verlinkten Advisory haben die Debian- und Open-Suse-Binaries des Programms mehr als 256 Bytes Daten davor abgelegt, wodurch eine Denial-of-Service-Attacke nicht möglich ist.
Betroffen sind die Versionen vor 1.4.30 (SVN-Revision 2806).

