D-Bus: Byte-Order-Durcheinander bringt Programme zum Absturz
D-Bus dient der Inter-Prozess-Kommunikation (IPC) zwischen Desktopanwendungen und ist der Nachfolger von DCOP (Desktop Communication Protocol) für KDE und CORBA (Common Object Request Broker Architecture) für Gnome. D-Bus-Nachrichten sind gewöhnlich binär in nativer Byte-Order kodiert, also little-endian auf einem x86-Rechner. Ein Programmierfehler beim Verarbeiten von Daten in anderer Byte-Reihenfolge hat zur Folge, dass ein Angreifer Programme zum Absturz bringen kann.
Es gibt viele verschiedene IPC-Mechanismen, darunter die aus alten Zeiten bekannten Pipes und Fifos, aber auch SOAP und XML-RPC, die speziell auf HTTP-basierte Webdienste zugeschnitten sind. Auch Desktop-Anwendungen setzen auf IPC: ein Dateibrowser beispielsweise sollte erkennen, wenn ein USB-Stick eingesteckt wurde. Hier hat sich mittlerweile durch das Engagement des Freedesktop.org-Projekts D-Bus als Standard-IPC für den Desktop-Bereich etabliert.
D-Bus besteht prinzipiell aus drei Komponenten: einer API-Bibliothek (Libdbus), einem Daemon (stellt den Bus bereit), und der Protokoll-Spezifikation. Der Bus dient der eigentlichen Kommunikation zwischen den verschiedenen Anwendungen, die mit Libdbus darauf zugreifen. Meist kommen mehrere Busse auf einem System zum Einsatz, so zum Beispiel ein System- und ein Session-Bus, die mit "dbus-launch" gestartet werden. XML-basierte Konfigurationsdateien finden sich unter "/etc/dbus-1/system.conf" und "/etc/dbus-1/session.conf". D-Bus verwendet ein detailliertes Adressierungschema um verschiedene Verbindungen, Objekte und Methoden zu erreichen.
Ein einfaches C-Beispiel für D-Bus-Kommunikation sieht so aus:
#include <stdio.h>
#include <dbus/dbus.h>
static void send_dbus_message (DBusConnection *connection, const char *msg)
{
DBusMessage *message;
message = dbus_message_new_signal ("/org/example/event", "testevent", msg);
dbus_connection_send (connection, message, NULL);
dbus_message_unref (message);
}
int main (int argc, char **argv)
{
DBusConnection *connection;
DBusError error;
dbus_error_init (&error);
connection = dbus_bus_get (DBUS_BUS_SESSION, &error);
if (!connection)
{
printf ("D-BUS daemon connection failed: %s", error.message);
dbus_error_free (&error);
return 1;
}
send_dbus_message (connection, "TestMsg");
return 0;
}
Dies lässt sich mit "gcc `pkg-config --cflags --libs dbus-1` -o dbus dbus.c" übersetzen und sendet eine simple Nachricht über den Session-Bus. Wer vorher "dbus-monitor" startet, kann den Vorgang beobachten.
Alternativ kann man die Python-Bindings verwenden und dann einfach mit folgenden Zeilen auf den Session-Bus zugreifen:
import dbus session_bus = dbus.SessionBus()
D-Bus verpackt Nachrichten/Objekte via Marshalling (Serialisierung) in ein effizientes Binärformat, wobei die Struktur der Nachrichten so aussieht:
byte byte order byte message type ID byte flags byte protocol version uint32 body length uint32 serial array of struct (byte,variant) (field name, value)
Der erste Eintrag zeigt das allgemeine Problem mit Binärdaten: Wie ist die Byte-Reihenfolge gewählt? Hierzu gibt es mehrere Möglichkeiten, wie little-endian (LSB) oder big-endian (MSB), die sich dadurch unterscheiden, wie die Bytes in einem Wort (=4 Bytes) angeordnet sind. Es ist also wichtig, dass D-Bus genau weiß, in welchem Byte-Format die binären Nachrichten gespeichert sind. Um dies zu markieren wird das erste Byte der Nachricht verwendet.
Kommt eine Nachricht in nicht-nativem Byte-Format an, so muss sie zunächst via Swapping umgewandelt werden, bevor sie dem Un-Marshalling unterzogen wird. Die Funktion "_dbus_header_byteswap()" in der Datei "dbus/dbus-marshal-header.c" ist hierfür verantwortlich. Und dort hat sich ein Programmierfehler im D-Bus-Code über mehrere Jahre hinweg versteckt. Zwar wird das Swapping der Bytes korrekt durchgeführt, doch haben die Programmierer vergessen, das Byte-Order-Flag am Anfang der Nachricht auch entsprechend zu ändern. Wird eine so modifzierte Nachricht nun weiterverarbeitet, kann es zum Absturz der entsprechenden Applikation kommen, da die Daten im falschen Byte-Format interpretiert werden. Ein Angreifer kann auf diese Weise Denial-of-Service-Attacken durchführen.
Der Fehler lässt sich leicht korrigieren, und die entsprechende Diff-Datei sieht so aus:
_dbus_header_byteswap (DBusHeader *header,
int new_order)
{
+ unsigned char byte_order;
+
if (header->byte_order == new_order)
return;
+ byte_order = _dbus_string_get_byte (&header->data, BYTE_ORDER_OFFSET);
+ _dbus_assert (header->byte_order == byte_order);
+
_dbus_marshal_byteswap (&_dbus_header_signature_str,
0, header->byte_order,
new_order,
&header->data, 0);
+ _dbus_string_set_byte (&header->data, BYTE_ORDER_OFFSET, new_order);
header->byte_order = new_order;
}
Entscheidend ist hier vor allem der hinzugefügte Aufruf "_dbus_string_set_byte()", der sicherstellt, dass in der neuen Nachricht die Byte-Order korrekt gesetzt wird.
Betroffen sind die Versionen 1.4.10 und älter.
Interessanterweise wurde diese D-Bus-Schwachstelle das erste Mal im März 2007 erwähnt. Allerdings ist daraufhin nichts passiert, und erst als der Fehler vor kurzem wieder auftauchte, wurde das oben genannte Patch in D-Bus eingebaut.
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...


