Table of Contents

Introduction

gnome-remote-desktop offers access to the graphics system either via the VNC or the RDP (Microsoft remote desktop) network protocol. Before version 46, gnome-remote-desktop was only used in the context of existing graphical user sessions. Starting with version 46, one can also configure a system daemon, that allows to connect to the GNOME display manager (GDM), allowing to create graphical sessions remotely.

The system daemon runs as a dedicated “gnome-remote-desktop” user. It provides a D-Bus interface on the D-Bus system bus. The daemon also interacts with a newly introduced D-Bus interface provided by GDM, to create remote displays.

While reviewing the new system service I found a number of local security issues and areas for security improvement. The more relevant issues are discussed in this report, while an upstream Gitlab issue contains a more detailed report and discussions also covering less severe aspects found during the review.

This report relates to gnome-remote-desktop release 46.0. Bugfixes for the issues described are found in release 46.2, except for item C) for which no fix is available yet.

Review Motivation and Scope

D-Bus system services require a review by the SUSE security team, before they can be added to openSUSE distributions and derived products. With the addition of the system daemon, a review of gnome-remote-desktop became necessary, before adding it to openSUSE Tumbleweed in the context of the larger GNOME 46 release.

The review was mainly concerned with the newly introduced system level gnome-remote-desktop daemon. The focus was furthermore on code paths related to the RDP protocol, which is the default and preferred over the VNC protocol.

Since the codebase of gnome-remote-desktop is rather large, I focused the review on the security of the D-Bus methods, the Polkit authentication and parts of the network processing. I also did not look closely into the FreeRDP library, which is used by gnome-remote-desktop for processing the majority of the RDP protocol.

A) Unauthenticated Handover D-Bus Interface (CVE-2024-5148)

Only the “org.gnome.RemoteDesktop.Rdp.Server” D-Bus interface is protected by Polkit. auth_admin authorization is required on this interface for all methods. The other two interfaces “Dispatcher” and “Handover” are not authorized and are accessible to all local users in the system. This leads to a number of local security issues described in the following subsections.

Local Private Key Leak

The system daemon keeps public SSL certificates and their corresponding private keys in “/var/lib/gnome-remote-desktop/.local/share/gnome-remote-desktop/certificates”. Access to the service’s home directory in “/var/lib/gnome-remote-desktop” is restricted to the service user “gnome-remote-desktop”, mode 0700.

Through the “org.gnome.RemoteDesktop.Rdp.Handover” D-Bus interface any local user can intercept the private SSL key, though. The private key is returned from the StartHandover D-Bus function. When a remote desktop client connects to the system daemon, then there is a rather long time window, during which any local user (even nobody) can call this method on the created session object. This is an example call to achieve this:

gdbus call -y -d org.gnome.RemoteDesktop -o /org/gnome/RemoteDesktop/Rdp/Handovers/sessionc11 \
    -m org.gnome.RemoteDesktop.Rdp.Handover.StartHandover someuser somepass

The username and password parameters are not important here, they will only be forwarded to the connecting client. Doing this, as another effect, also results in a denial-of-service, because the proper connection handover will be prevented.

A local attacker does not necessarily have to wait for somebody to connect to the system daemon, it can connect on its own via localhost, to achieve the same result. Valid credentials for RDP authentication are necessary to get to the handover stage, however.

The impact of this problem is a local information leak and local DoS. The information leak means that the integrity and privacy of RDP connections on the system are compromised. This simple Python script allows to reproduce the issue.

System Credentials Leak

If an RDP connection uses shared system credentials (see struct member GrdRemoteClient.use_system_credentials), then a local attacker with low privileges can obtain these credentials in cleartext in a similar fashion to the private key leak, by calling the unauthenticated GetSystemCredentials() D-Bus method of the Handover interface.

Using these system credentials, the attacker will be able to connect to the display manager via RDP. This should not directly grant access to a session, since a login on display manager level still has to happen. An exception would be if things like automatic login are enabled (I don’t know whether they apply to remote connections).

The Socket Connection can be Obtained via TakeClient()

The equally unauthenticated D-Bus method Handover.TakeClient() allows any local user in the system to obtain the file descriptor pertaining to the RDP client that is in handover state. This could allow a local user to perform a denial-of-service of the RDP connection or to setup a crafted RDP session.

Obtaining the socket via this call only works in certain system daemon states, most notably it seems the StartHandover() needs to have been performed for this to succeed. I did not fully investigate what the exact preconditions are.

Bugfix and Affectedness

This CVE only affects gnome-remote-desktop releases 46.0 and 46.1, since the system daemon was only introduced in these versions. The bugfix is available starting from version 46.2 and is found in commit 9fbaae1a.

With the bugfix applied, only the user for whom a new session has been created will be able to call the handover interface anymore. This still means that all users with RDP access share the same private key, which, according to upstream, is by protocol design.

B) find_cr_lf() Suffers from a one Byte Overread

This function processes untrusted pre-authentication RDP protocol network data (the routing token) and looks for a terminating \r\n sequence. The size calculation in the function’s for loop is wrong: if the final byte of the buffer is 0x0D, then the logic will access the next byte out of bounds. This buffer is not null terminated.

The impact should be negligible in most cases. This is the output of Valgrind I obtained after sending a crafted packet to the daemon:

==31119== Invalid read of size 1
==31119==    at 0x15A1EF: UnknownInlinedFun (grd-rdp-routing-token.c:65)
==31119==    by 0x15A1EF: UnknownInlinedFun (grd-rdp-routing-token.c:159)
==31119==    by 0x15A1EF: UnknownInlinedFun (grd-rdp-routing-token.c:239)
==31119==    by 0x15A1EF: peek_routing_token_in_thread (grd-rdp-routing-token.c:281)
<snip>

Bugfix

The bugfix is found starting in release 46.2 in commit 663ad63172.

C) grdctl Utility Accepts Cleartext Password on the Command Line

The text-based grdctl configuration utility, which is used for both, system and session context RDP setups, accepts cleartext passwords in the following invocation styles:

grdctl [--system] rdp set-credentials <username> <password>
grdctl [--system] vnc set-password <username> <password>

This means that the cleartext password will leak via the /proc file system and will be visible in the process task list via ps, when configured this way. Other users can thus get access to the authentication data.

Bugfix

Upstream declined assignment of a CVE for this issue. They consider the shared credentials to be of rather low sensitivity and state that other ways exist for users to set the credentials, that don’t leak information to other users (GNOME Control Center, the D-Bus API, writing the credentials file directly). A feature request to allow reading the password via stdin has been added to an existing Gitlab issue.

Timeline

2024-04-19 I reported the issues and other recommendations and remarks via a private issue in the upstream Gitlab, offering coordinated disclosure.
2024-04-22 Upstream decided to handle all findings except for the unauthenticated Handover D-Bus methods publicly. No formal coordinated release date was established for the remaining private issue.
2024-04-26 I requested a CVE from Mitre to track the unauthenticated Handover D-Bus methods issue described in section A).
2024-05-13 After Mitre did not assign a CVE for weeks, it was agreed that upstream would request a CVE from RedHat instead.
2024-05-20 Upstream received CVE-2024-5148 to track the unauthenticated Handover D-Bus methods issue.
2024-05-21 After asking for the expected time frame for publication of the remaining private issue, upstream decided to publish right away.

References