Bibliothek Gdk-pixbuf: Fehlerhafter GIF-Loader bringt Anwendungen zum Absturz

Die Gnome-Bibliothek Gdk-pixbuf bietet verschiedene Funktionen zum Laden und Verarbeiten von Bilddateien. Eine kürzlich darin entdeckte Sicherheitslücke hat zur Folge, dass ein entfernter Angreifer Denial-of-Service-Attacken durchführen kann.

Der Programmierfehler befindet sich in der Funktion “gdk_pixbuf__gif_image_load()” (in der Datei “gdk-pixbuf/io-gif.c”), wo einige Rückgabe-Werte nicht korrekt behandelt werden. Dadurch ist ein entfernter Angreifer in der Lage Denial-of-Service-Attacke gegen Applikation durchzuführen, die die Bibliothek verwenden.

Entdeckt wurde dieses Problem zuerst im Zusammenhang mit einem Problem im Instant-Messenger Pidgin beim Verarbeiten von bestimmten Buddy-Icons. Daraufhin wurden einige Sicherheitsmaßnahmen im Pidgin-Code ergriffen, um derartige Probleme zukünftig zu vermeiden. Die Wurzel des Problems war allerdings die Schwachstelle in der Gdk-pixbuf-Bibliothek, die dann ebenfalls korrigiert wurde.

Die Funktion “gdk_pixbuf__gif_image_load()” ist für das Laden von GIF-Animationen zuständig. Die fehlherhafte Version hiervon sieht folgendermaßen aus:

static GdkPixbuf *
gdk_pixbuf__gif_image_load (FILE *file, GError **error)
{ GifContext *context; GdkPixbuf *pixbuf; g_return_val_if_fail (file != NULL, NULL); context = new_context (); if (context == NULL) { g_set_error_literal (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, _("Not enough memory to load GIF file")); return NULL; } context->file = file; context->error = error; context->stop_after_first_frame = TRUE; if (gif_main_loop (context) == -1 || context->animation->frames == NULL) { if (context->error && *(context->error) == NULL) g_set_error_literal (context->error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, _("GIF file was missing some data (perhaps it was truncated somehow?)")); } pixbuf = gdk_pixbuf_animation_get_static_image (GDK_PIXBUF_ANIMATION (context->animation)); if (pixbuf) g_object_ref (pixbuf); g_object_unref (context->animation); g_free (context->buf); g_free (context); return pixbuf;
}

Die Struktur “GifContext” speichert verschiedene Bildinformationen, wobei einige Einträge in “new_context()” initialisiert werden. Dort wird auch “context->state” auf “GIF_START” gesetzt. Anschließend ruft der Code die Funktion “gif_main_loop()” auf. Je nach “context->state” extrahiert diese Funktion verschiedene GIF-Dateiinformationen. Im Falle von “GIF_START” wird die Funktion “gif_init()” aufgerufen.

static gint
gif_main_loop (GifContext *context)
{ gint retval = 0; do { switch (context->state) { case GIF_START: LOG("start\n"); retval = gif_init (context); break;
... default: retval = 0; goto done; }; } while ((retval == 0) || (retval == -3)); done: return retval;
} 

Am Ende wird so eine “GdkPixbuf-Struktur” erzeugt, die die eigentlichen Pixeldaten und zusätzliche Bildinformationen enthält. Die Funktion “gif_main_loop()” kann allerdings verschiedene Fehlercodes zurückliefern:

 0 -> success
-1 -> more bytes needed
-2 -> failure; abort the load
-3 -> control needs to be passed back to the main loop

Dabei hangelt sich die While-Schleife mit Hilfe des Wertes von “context->state” von einem Case zum nächsten und arbeitet dabei die komplette GIF-Datei ab. Einige der dabei aufgerufenen Funktionen können -2 als Fehlercode zurückliefern. Beispielsweise liefert “gif_init()” -2, falls es sich nicht um eine korrekte GIF-Datei handelt. Normalerweise sollte dann der gesamte Ladevorgang abgebrochen werden, und “gdk_pixbuf__gif_image_load()” NULL zurückliefern. Allerdings wird nirgends in dieser Funktion explizit auf den Fehlercode -2 geprüft, und so kann es zu Situationen kommen, in denen die Routine einen Pixel-Puffer zurückliefert, obwohl “gif_main_loop()” nicht korrekt durchlief.

Bastelt ein Angreifer nun eine geschickt aufgebaute GIF-Datei, die einige der Tests in “if_main_loop()” nicht passiert und -2 zurückliefert, so terminiert die While-Schleife, und -2 wird an “gdk_pixbuf__gif_image_load()” zurückgeliefert. Da der Loop aber in diesem Fall nicht über alle Cases lief, kann es vorkommen, dass einige Felder der Struktur “GdkPixbuf” nicht initialisiert sind, wenn diese “via gdk_pixbuf_animation_get_static_image()” konstruiert wird.

Laut Problembericht ist es damit möglich Pixel-Puffer mit nicht initialisierten Werten für Breite und Höhe zu erzeugen, was praktisch zu Zufallswerten für diese Variablen führt. Wird dieser Puffer dann später weiter verwendet, wie es bei den Pidgin-Icons der Fall war, kann es zu dem Absturz der Applikation kommen.

Nach oben