orion / rpms / dbus

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