eead94
From 47b1a4c41004bf494b87370987b222c934b19016 Mon Sep 17 00:00:00 2001
eead94
From: Simon McVittie <smcv@collabora.com>
eead94
Date: Thu, 30 May 2019 12:53:03 +0100
eead94
Subject: [PATCH] auth: Reject DBUS_COOKIE_SHA1 for users other than the server
eead94
 owner
eead94
eead94
The DBUS_COOKIE_SHA1 authentication mechanism aims to prove ownership
eead94
of a shared home directory by having the server write a secret "cookie"
eead94
into a .dbus-keyrings subdirectory of the desired identity's home
eead94
directory with 0700 permissions, and having the client prove that it can
eead94
read the cookie. This never actually worked for non-malicious clients in
eead94
the case where server uid != client uid (unless the server and client
eead94
both have privileges, such as Linux CAP_DAC_OVERRIDE or traditional
eead94
Unix uid 0) because an unprivileged server would fail to write out the
eead94
cookie, and an unprivileged client would be unable to read the resulting
eead94
file owned by the server.
eead94
eead94
Additionally, since dbus 1.7.10 we have checked that ~/.dbus-keyrings
eead94
is owned by the uid of the server (a side-effect of a check added to
eead94
harden our use of XDG_RUNTIME_DIR), further ruling out successful use
eead94
by a non-malicious client with a uid differing from the server's.
eead94
eead94
Joe Vennix of Apple Information Security discovered that the
eead94
implementation of DBUS_COOKIE_SHA1 was susceptible to a symbolic link
eead94
attack: a malicious client with write access to its own home directory
eead94
could manipulate a ~/.dbus-keyrings symlink to cause the DBusServer to
eead94
read and write in unintended locations. In the worst case this could
eead94
result in the DBusServer reusing a cookie that is known to the
eead94
malicious client, and treating that cookie as evidence that a subsequent
eead94
client connection came from an attacker-chosen uid, allowing
eead94
authentication bypass.
eead94
eead94
This is mitigated by the fact that by default, the well-known system
eead94
dbus-daemon (since 2003) and the well-known session dbus-daemon (in
eead94
stable releases since dbus 1.10.0 in 2015) only accept the EXTERNAL
eead94
authentication mechanism, and as a result will reject DBUS_COOKIE_SHA1
eead94
at an early stage, before manipulating cookies. As a result, this
eead94
vulnerability only applies to:
eead94
eead94
* system or session dbus-daemons with non-standard configuration
eead94
* third-party dbus-daemon invocations such as at-spi2-core (although
eead94
  in practice at-spi2-core also only accepts EXTERNAL by default)
eead94
* third-party uses of DBusServer such as the one in Upstart
eead94
eead94
Avoiding symlink attacks in a portable way is difficult, because APIs
eead94
like openat() and Linux /proc/self/fd are not universally available.
eead94
However, because DBUS_COOKIE_SHA1 already doesn't work in practice for
eead94
a non-matching uid, we can solve this vulnerability in an easier way
eead94
without regressions, by rejecting it early (before looking at
eead94
~/.dbus-keyrings) whenever the requested identity doesn't match the
eead94
identity of the process hosting the DBusServer.
eead94
eead94
Signed-off-by: Simon McVittie <smcv@collabora.com>
eead94
Closes: https://gitlab.freedesktop.org/dbus/dbus/issues/269
eead94
Closes: CVE-2019-12749
eead94
---
eead94
 dbus/dbus-auth.c | 32 ++++++++++++++++++++++++++++++++
eead94
 1 file changed, 32 insertions(+)
eead94
eead94
diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c
eead94
index 37d8d4c9..7390a9d5 100644
eead94
--- a/dbus/dbus-auth.c
eead94
+++ b/dbus/dbus-auth.c
eead94
@@ -529,6 +529,7 @@ sha1_handle_first_client_response (DBusAuth         *auth,
eead94
   DBusString tmp2;
eead94
   dbus_bool_t retval = FALSE;
eead94
   DBusError error = DBUS_ERROR_INIT;
eead94
+  DBusCredentials *myself = NULL;
eead94
 
eead94
   _dbus_string_set_length (&auth->challenge, 0);
eead94
   
eead94
@@ -565,6 +566,34 @@ sha1_handle_first_client_response (DBusAuth         *auth,
eead94
       return FALSE;
eead94
     }
eead94
 
eead94
+  myself = _dbus_credentials_new_from_current_process ();
eead94
+
eead94
+  if (myself == NULL)
eead94
+    goto out;
eead94
+
eead94
+  if (!_dbus_credentials_same_user (myself, auth->desired_identity))
eead94
+    {
eead94
+      /*
eead94
+       * DBUS_COOKIE_SHA1 is not suitable for authenticating that the
eead94
+       * client is anyone other than the user owning the process
eead94
+       * containing the DBusServer: we probably aren't allowed to write
eead94
+       * to other users' home directories. Even if we can (for example
eead94
+       * uid 0 on traditional Unix or CAP_DAC_OVERRIDE on Linux), we
eead94
+       * must not, because the other user controls their home directory,
eead94
+       * and could carry out symlink attacks to make us read from or
eead94
+       * write to unintended locations. It's difficult to avoid symlink
eead94
+       * attacks in a portable way, so we just don't try. This isn't a
eead94
+       * regression, because DBUS_COOKIE_SHA1 never worked for other
eead94
+       * users anyway.
eead94
+       */
eead94
+      _dbus_verbose ("%s: client tried to authenticate as \"%s\", "
eead94
+                     "but that doesn't match this process",
eead94
+                     DBUS_AUTH_NAME (auth),
eead94
+                     _dbus_string_get_const_data (data));
eead94
+      retval = send_rejected (auth);
eead94
+      goto out;
eead94
+    }
eead94
+
eead94
   /* we cache the keyring for speed, so here we drop it if it's the
eead94
    * wrong one. FIXME caching the keyring here is useless since we use
eead94
    * a different DBusAuth for every connection.
eead94
@@ -679,6 +708,9 @@ sha1_handle_first_client_response (DBusAuth         *auth,
eead94
   _dbus_string_zero (&tmp2);
eead94
   _dbus_string_free (&tmp2);
eead94
 
eead94
+  if (myself != NULL)
eead94
+    _dbus_credentials_unref (myself);
eead94
+
eead94
   return retval;
eead94
 }
eead94
 
eead94
-- 
eead94
2.21.0
eead94