Re: Unable to connect to DBus session bus after dropping privileges from a setuid binary
Simon McVittie <simon.mcvittie-ZGY8ohtN/[email protected]>
| Newsgroups | gmane.comp.freedesktop.dbus |
|---|---|
| Organization | Collabora Ltd. |
| Message-ID | <[email protected]> |
On 19/05/16 10:17, Manish wrote: > On Wed, 2016-05-18 at 18:52 +0100, Simon McVittie wrote: >> Have you considered carrying out your root-required actions in a >> separate process that is not the one that connects to the session >> bus? A popular pattern for this is to have a service that runs on >> the system bus (like NetworkManager, ConnMan, udisks, etc.) and have >> ordinary user processes submit requests to it. If required, it can >> use polkit (formerly PolicyKit) to determine whether the request >> should be obeyed or rejected. > > I have considered that, but given my requirements it may not be > feasible. It is still being discussed and not completely off the > table. Another way you can potentially do your root-required actions is to have your main process that connects to the session bus, and then have a single-purpose setuid helper that it runs (via posix_spawn() or equivalent) when it needs to do a privileged action. For example, spice-gtk has spice-client-glib-usb-acl-helper which works like this. Again, please note that this is a privileged process, which needs to be extremely careful (to the point of paranoia) to avoid being part of a security vulnerability. For example, spice-client-glib-usb-acl-helper had a root privilege escalation vulnerability because it used libdbus without clearing the environment (CVE-2012-4425). I would strongly recommend using the approach involving a system bus service, like NetworkManager: it reduces your attack surface considerably, making it less likely that you'll have to issue updates to patch a privilege escalation vulnerability. >> It might also help to read the human-readable message that should have >> accompanied this machine-readable error name (in libdbus they're >> DBusError.message and DBusError.name respectively). > > It's dbus_bus_get as mentioned above. Here's the error that I get. > DBusError.name = org.freedesktop.DBus.Error.NotSupported > DBusError.message = Unable to autolaunch when setuid If you're seeing that, then libdbus is ignoring DBUS_SESSION_BUS_ADDRESS and falling back to the hard-coded default "autolaunch:", then refusing to do that either, in both cases because it thinks you're setuid. This appears to be because you have used setuid() and not setresuid(). The check is a bit less simplistic than I had thought: if the system has a getresuid() function, we assert that the real, effective *and saved* uids are all the same, and also the equivalent for primary groups. To be absolutely sure of what open source software is doing, don't believe the maintainer, read the source code :-) In this case the function to search for is _dbus_check_setuid(). You'll notice that we also use issetuid() if available (that's a *BSD thing, Linux doesn't have that function). >> Note that libdbus deliberately does not trust the environment when it >> detects that it was used in a setuid or similarly privileged binary, to >> mitigate security vulnerabilities caused when setuid binaries do not >> sanitize their (attacker-supplied) environment variables (CVE-2012-3524). > > I've already read about the exploit, and your statement "NOTE: libdbus > maintainers state that this is a vulnerability in the applications that > do not cleanse environment variables, not in libdbus itself: "we do not > support use of libdbus in setuid binaries that do not sanitize their > environment before their first call into libdbus." > This is why I wrote to this mailing list, to try and understand what is > meant by cleansing the environment variables? What we mean by cleansing the environment is: http://www.dwheeler.com/secure-programs/Secure-Programs-HOWTO/environment-variables.html If you are writing setuid or otherwise security-sensitive software, it's a very good idea to read that whole document. The central principle is that you need to think in terms of the worst corner-cases that could possibly happen, because that's what an attacker will set up in order to exploit your software. > If libdbus ignores environment variables in case of a setuid process > then how would one provide the correct $DBUS_SESSION_BUS_ADDRESS > variable to it? One way is to stop using dbus_bus_get(), and instead get the session bus address from a trusted source, then use dbus_connection_open_private() followed by dbus_bus_register() (the combination of those two is essentially equivalent to dbus_bus_get_private()). You are responsible for the security of the code you use to find a trusted session bus address and ensure that it really came from the expected source. Another way is to extract the parts of the environment you need, filter their values using a "whitelist" approach (reject anything not matching a known-good pattern), clearenv(), put the good parts back, and drop privileges irrevocably by using setresuid(). Again, you will have to take responsibility for the code that scrubs the environment, and please note that filtering out known-bad environment variables like LD_LIBRARY_PATH, or known-bad values, is not enough. This is basically what happens if you run something like "sudo -u otheruser dbus-monitor". (Note that if we switch _dbus_check_setuid() to use _secure_getenv() on GNU platforms, which we will probably do in a future release, your process will still be flagged as running in a potentially insecure execution context even after calling setresuid(), so _secure_getenv() still won't trust the environment. You would have to exec() a non-setuid subprocess instead, like what happens when sudo exec()s dbus-monitor in my example above.) In either case, bear in mind that using an attacker-chosen session bus address can result in connecting to a socket that they control (and potentially putting misguided trust in D-Bus services visible via that socket), and can also result in arbitrary code execution (e.g. via the unixexec: transport). So don't do that, and in general, be very careful. -- Simon McVittie Collabora Ltd. <http://www.collabora.com/> _______________________________________________ dbus mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/dbus