Am 27. Januar meldete Qualys eine Zero-Day-Schwachstelle in der GNU-C-Bibliothek, die GHOST getauft wurden. Durch diese Sicherheitslücke kann ein entfernter Angreifer Befehle mit den Rechten des Clients/Servers in zahlreichen Netzwerkapplikation durchführen. Ursache ist ein Programmierfehler in der __nss_hostname_digits_dots()-Funktion. Dieser hat zur Folge, dass Aufrufe der gethostbyname()- und gethostbyname2()-Funktionen einen Heap-Buffer-Overflow auslösen können. Der Overflow tritt in der Implementierung von __nss_hostname_digits_dots() bei einem strcpy()-Befehl auf:
resbuf->h_name = strcpy (hostname, name);
Dieser Overflow führt dann entweder zu einem Segmentation Fault und einer damit verbundenen Denial-of-Service-Attacke, oder erlaubt dem Angreifer das Ausführen von beliebigem Programmcode. Die »gethostbyname()«- und »gethostbyname2()«-Funktionen werden in Netzwerkapplicationen verwendet, um Hostnamen in IP-Adressen aufzulösen. Eigentlich sollten diese Funktionen gar nicht mehr zum Einsatz kommen, da sie kein IPv6 unterstützen. Entwickler sollten stattdessen die »getaddrinfo()«-Funktion verwenden, die nicht von dem Overflow betroffen sind. Nichtsdestotrotz verwenden noch zahlreiche Netzwerkprogramme die veraltete Version.
Auf den ersten Blick klingt die Schwachstelle recht bedrohlich. Allerdings sind ernsthafte Attacke nur gegen eine kleine Zahl von Anwendungen möglich. Zunächst muss die Anwendung die alten Funktionen verwenden. Weiter muss zum Ausnutzen der Attacke das erste Zeichen des Hostnamens eine Ziffer sein, das letzte Zeichen darf kein Punkt sein, und der gesamte Hostname darf nur aus Ziffern und Punkten bestehen. Nur wenige Anwendungen akzeptieren solche Eingaben, weshalb sich der Schaden durch GHOST in Grenzen hält. Allerdings sind auch einige häufig verwendete Applikationen anfällig für das Problem, z.B. der Exim Mail-Server, procmail, und pppd. Qualys hat einen voll funktionsfähigen Remote-Exploit für Exim entwickelt. Dieser soll als Metasploit-Modul veröffentlich werden.
Folgender Code kann verwendet werden, um zu testen, ob ein System von der Sicherheitslücke betroffen ist:
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#define CANARY "in_the_coal_mine"
struct {
char buffer[1024];
char canary[sizeof(CANARY)];
} temp = { "buffer", CANARY };
int main(void) {
struct hostent resbuf;
struct hostent *result;
int herrno;
int retval;
/*** strlen (name) = size_needed - sizeof (*host_addr) - sizeof (*h_addr_ptrs) - 1; ***/
size_t len = sizeof(temp.buffer) - 16*sizeof(unsigned char) - 2*sizeof(char *) - 1;
char name[sizeof(temp.buffer)];
memset(name, '0', len);
name[len] = '\0';
retval = gethostbyname_r(name, &resbuf, temp.buffer, sizeof(temp.buffer), &result, &herrno);
if (strcmp(temp.canary, CANARY) != 0) {
puts("vulnerable");
exit(EXIT_SUCCESS);
}
if (retval == ERANGE) {
puts("not vulnerable");
exit(EXIT_SUCCESS);
}
puts("should not happen");
exit(EXIT_FAILURE);
}
Dieser Code wird beim Ausführen entweder ‘vulnerable’ oder ‘not vulnerable’ ausgeben. Der Code verwendet einen speziell konstruierten Hostname für die gethostbyname_r-Funktion, um auf die Schwachstelle zu testen.
Ein Patch für diese Sicherheitslücke wurde schon am 21. Mai 2013 veröffentlicht. Allerdings wurde die Schwachstelle damals nicht direkt als kritisch erkennt und floss deshalb nicht in die glibc-Bibliothek ein.
Betroffen sind die Version 2.2 bis 2.7.
