Attacker Value
Very Low
(1 user assessed)
Exploitability
Very Low
(1 user assessed)
User Interaction
Unknown
Privileges Required
Unknown
Attack Vector
Unknown
4

CVE-2022-29799

Add MITRE ATT&CK tactics and techniques that apply to this CVE.

Description

** RESERVED ** This candidate has been reserved by an organization or individual that will use it when announcing a new security problem. When the candidate has been publicized, the details for this candidate will be provided.

Add Assessment

2
Ratings
Technical Analysis

Super underwhelming, IMO – requires a confluence of bad configuration. Microsoft’s claims that they see vulnerable configurations in the wild are dubious – it takes some effort to make yourself vulnerable (I just used sudo to run as the networkd user, but that’s cheating). Definitely not a name-worthy vulnerability!

General Information

Additional Info

Technical Analysis

Description

CVE-2022-29799 and CVE-2022-29800 – collectively referred to as Nimbuspwn – are a pair of vulnerabilities in networkd-dispatcher that Microsoft researchers discovered and reported. Under the right circumstances, these issues can be exploited together to escalate a user to root privileges on an affected Linux machine. We confirmed this attack on a default installation of Ubuntu 22.04 Desktop with no patches, but it did require special configuration that we discuss below.

Note: Due to the circumstances required for this to be exploitable, we believe this to be low-risk and unlikely to see widespread exploitation.

Technical analysis

Before talking about the specifics of the vulnerability, let’s take a quick look at D-Bus. We’ll use ruby-dbus for examples.

D-Bus – or Desktop Bus – is an inter-process communication mechanism that’s used by most modern Linux distributions. It permits a variety of processes to communicate with each other over a shared medium, either directly (1:1) or via broadcast (1:n). D-Bus clients can accept method calls and generate signals for other D-Bus clients. Signals are where the Nimbuspwn vulnerability arises.

When a client connects to a D-Bus bus, it is assigned a unique, numeric name such as :1.146. For client applications, that’s generally sufficient – nothing else needs to find them so discoverability is not necessary. But when a client wants to provide a service, they typically register a well-known name so other clients can find them.

By convention, Linux systems have two different buses: the system bus and session bus. The system bus runs system services, and is semi-privileged – while anybody can typically connect to any bus with a default name, they cannot register a special name without special permission. The session bus, on the other hand, runs in the context of a single user’s session, and, unlike the system bus, any client can register a name (provided it’s not already in use). This is all configured system-wide by /usr/share/dbus-1/system.conf and /usr/share/dbus-1/session.conf (paths may vary):

/usr/share/dbus-1 $ cat system.conf | grep own=
    <deny own="*"/>

/usr/share/dbus-1 $ cat session.conf | grep own=
    <allow own="*"/>

The following example shows how we’d register a name on the system bus (which fails) and the session bus (which succeeds). Due to the asynchronous nature of the library, we call .exists?() to actually make the connection happen:

irb(main):001:0> require 'dbus'
=> true

irb(main):002:0> # Try and use the system bus

irb(main):003:0> DBus.system_bus.request_service('my.test.service').exists?
/var/lib/gems/3.0.0/gems/ruby-dbus-0.17.0/lib/dbus/bus.rb:416:in `block in request_service': Connection ":1.146" is not allowed to own the service "my.test.service" due to security policies in the configuration file; caused by 3 sender=org.freedesktop.DBus -> dest=:1.146 serial=3 reply_serial=3 path=; interface=; member= error_name=org.freedesktop.DBus.Error.AccessDenied (DBus::Error)

irb(main):004:0> # Try and use the session bus

irb(main):005:0> DBus.session_bus.request_service('my.test.service').exists?
=> true

As you can see, we cannot easily create a named service on the system bus. Of course, when a service needs to register a well-known name on the system bus, they can be granted access utilizing a system configuration file. For example, Ubuntu 22.04 Desktop comes with a configuration file that permits the systemd-network user to register the name org.freedesktop.network1:

/usr/share/dbus-1/system.d$ cat org.freedesktop.network1.conf
[...]
<busconfig>

        <policy user="systemd-network">
                <allow own="org.freedesktop.network1"/>
                <allow send_destination="org.freedesktop.network1"/>
                <allow receive_sender="org.freedesktop.network1"/>
        </policy>
[...]
</busconfig>

With that configuration, the specific user (and only that user) can register the name on the system bus:

$ sudo -u systemd-network irb

irb(main):001:0> require 'dbus'
=> true

irb(main):002:0> DBus.system_bus.request_service('org.freedesktop.network1').exists?
=> true

Once the client claims their name on the bus, we can stand signals to any processes listening on that bus for the given name. One such service is networkd-dispatcher:

$ cat /usr/bin/networkd-dispatcher
[...]
    def register(self, bus=None):
        """Register this dispatcher to handle events from the given bus"""
        print("REGISTERING")
        if bus is None:
            bus = dbus.SystemBus()
        bus.add_signal_receiver(self._receive_signal,
                                bus_name='org.freedesktop.network1',
                                signal_name='PropertiesChanged',
                                path_keyword='path')
[...]

What that means is, if a client on the bus claims the name org.freedesktop.network1, it can then send a PropertiesChanged signal to all listeners that networkd-dispatcher wants to know about! And that’s where this vulnerability lies – the handler function in networkd-dispatcher is vulnerable to several issues, including path traversal and time-of-check-time-of-use issues. If exploited, the client running as org.freedesktop.network1 can execute an arbitrary script in the context of networkd-dispatcher – root.

We tested a public proof of concept, and successfully gained root (provided we ran it as the systemd-network user):

$ sudo -u systemd-network python3 /tmp/nimbuspwn.py
[*] Attempt no. 1...
[*] Attempt no. 2...
[!] Root backdoor obtained! Executing...
# whoami
root

Analysis

This vulnerability has several pre-requisites that, in our opinion, make it very unlikely to see widespread exploitation:

  • The user must have permission to register org.freedesktop.network1 on the system bus
  • Nothing else may already be registered as org.freedesktop.network1, since duplicate names are not allowed on a bus

In their disclosure, Microsoft acknowledges this limitation and notes that there are possible situations where this can be overcome:

  • In some environments, the systemd-networkd service that normally owns org.freedesktop.network1 does not start by default, which means it can be claimed (though permissions are still an issue)
  • In some cases, the systemd-networkd user can run arbitrary code from world-writable locations – Microsoft attributes these to a customer misconfiguration, not a default setting

JFrog published a tool that can detect misconfigurations such as this.

In essence, a user would have to try hard to make a system exploitable.

IoC

The public exploit creates and then removes a whole bunch of files in /tmp/nimbuspwn[random], such as:

/tmp/nimbuspwn2761/wipefs
/tmp/nimbuspwn2761/depmod
/tmp/nimbuspwn2761/aptd
/tmp/nimbuspwn2761/fsck.fat
/tmp/nimbuspwn2761/blkid
/tmp/nimbuspwn2761/iwconfig
[...]

The files are created then immediately removed whether or not the exploit succeeds. If the exploit does succeed, a set-uid copy of sh is created in /tmp:

$ ls -alrt /tmp
-rwsrwxrwx  1 root root 125688 May  4 13:45 sh

The sh copy is not removed on exit.

Note that none of these are required for exploitation, this only detects artifacts left by the public exploit.

Guidance

Rapid7 recommends that users update their networkd-dispatcher installations to the latest release provided by their operating systems. Alternatively, apply the author’s patch directly to /usr/bin/networkd-dispatcher.

References