-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Running the xrdp process as non root
This information applies to version 0.9.13 of XRDP in a standard configuration with xrdp
and xrdp-sesman
daemons.
A default build and install of XRDP will run the xrdp-sesman(8)
and xrdp(8)
daemons as root. xrdp-sesman
needs to run as root, as it is responsible for user session management. However, it is possible for the xrdp
process to be run as a non-privileged user if the XRDP software is packaged appropriately. This reduces the damage which could be caused by an exploitable security flaw in xrdp
at the expense of increased installation complexity.
Care needs to be taken in testing that the xrdp
daemon is functioning correctly after reducing its privileges. For example, if the TLS certificate is not readable by the daemon, you could well be operating with standard RDP security, which is arguable less secure than running the xrdp
daemon as root.
The Debian package xrdp
implements this functionality.
The xrdp
daemon needs to be able to do the following of note:-
Function | Comment | Debian implementation |
---|---|---|
Listen on the TCP port configured in /etc/rdp/xrdp.ini (normally 3389) |
This does not normally need special privilege | |
Read the server TLS certificate and private key | see below | see below |
Write to the log file | see below | see below |
(if not run in the foreground) Create the PID file | see below | see below |
Connect to xrdp-sesman to authenticate the user |
Normally xrdp-sesman listens on a local TCP port and no special permissions are required to connect to it |
|
(following user authentication) Connect to the xrdp-chansrv(8) process running inside the user session. |
see below | see below |
(following user authentication) Connect to the X server (Xvnc or Xorg) process | see below | see below |
By default the TLS certificate and private key are read from /etc/xrdp/cert.pem
and /etc/xrdp/key.pem
respectively, although other locations can be configured in /etc/xrdp/xrdp.ini
.
Read access to the TLS certificate doesn't need to be restricted - the certificate is freely provided to any connecting client which asks for it.
However, it is important that the private key is only readable by the xrdp
daemon. When xrdp
is run as root, this file is normally owned by root, and the permissions mask is set to 0600.
The log file is configured in /etc/rdp/xrdp.ini
. A path can be specified for this, but if one is not, the path defaults to ${localstatedir}/log
, where ${localstatedir}
is configured at compile time.
The PID file is normally written to the directory ${localstatedir}/run
, where ${localstatedir}
is configured at compile time.
The xrdp-chansrv
process creates listening sockets in the socksdir directory. The xrdp
daemon needs read-write access to these to create a connection with xrdp-chansrv
.
If Xvnc
is used the connection is made over a standard socket. No special permissions are required for this. Xvnc
will be run with the UID and GID of the session user.
If Xorg
is used, the Xorg
server creates a listening socket in the socksdir directory. The xrdp
daemon needs read-write access to this socket.
This section describes how xrdp-0.9.9-1 is packaged for Debian 10 to allow xrdp
to be run as a non-root user.
The postinst
dpkg script creates a user xrdp
using the following command:-
adduser \
--quiet --system --group --no-create-home \
--disabled-password --disabled-login \
--home /run/xrdp xrdp
On Debian 10, /var/run
is symlinked to /run
. So, the home directory given for the xrdp
user /run/xrdp
is equivalent to /var/run/xrdp
where the PID of the xrdp
process is stored (see below).
These directives are used to start the xrdp
daemon as the unprivileged user.
This directive is used to create and remove /var/run/xrdp
. The directory is created when the daemon starts, and deleted when it exits.
An ExecStartPre
script is also configured. This runs as root
before the xrdp
daemon is run as the xrdp
user.
This Bourne shell script takes the following actions:-
- Ensures the directory
/var/run/xrdp
is present, is owned byroot:xrdp
and has a protection mask of 2775. - Ensures the directory
/var/run/xrdp/sockdir
(the sockdir) is present, is owned byroot:xrdp
and has a protection mask of 3777.
Interestingly, immediately after this script runs, the RuntimeDirectory
script systemd directive (see systemd.exec(5)) changes the following:-
- ownership of
/var/run/xrdp
toxrdp:xrdp
- protection mask of
/var/run/xrdp
to 0775. - ownership of
/var/run/xrdp/sockdir
toxrdp:xrdp
.
This does not affect the operation of the XRDP sub-system. Some tidying up could possibly be done here.
The Debian xrdp
package has a dependency on the ssl-cert
package. The installation of ssl-cert
creates a self-signed TLS certificate and private key for the host. Soft-links are created from /etc/xrdp/cert.pemand
/etc/xrdp/key.pem` to point to these files.
The private key created by ssl-cert
is owned by root:ssl-cert
with a protection mask of 0640. This allows members of the ssl-cert
group to access the private key.
The Debian packagers have taken the choice to not automate adding the xrdp
user to the ssl-cert
group - see Debian bug #860890. So in order for xrdp
to use the ssl-cert
self-signed TLS certificate, the following command needs to be entered manually by an administrator:-
sudo adduser xrdp ssl-cert
The file /var/log/xrdp.log
is pre-created in the dpkg postinst script with an ownership of xrdp:adm
and a protection mask of 0640. This allows the xrdp
daemon to write directly to the log file.
At package build time the Makefiles generated by the configure script are modified by the Debian package rules file. The modification sets the compile-time macro XRDP_PID_PATH
to /var/run/xrdp
rather than the package default of /var/run
. This causes the PID files for the xrdp
and xrdp-sesman
daemons to be deposited in /var/run/xrdp
. This directory is made group-writeable by the ExecStartPre
script, and so the daemon is able to create the PID file.
At package build time, the Debian package rules file configures the socksdir directory to be at /var/run/xrdp/sockdir
.
This directory is set to be owned by :xrdp
with a protection mask of 03777 by the ExecStartPre
script. The extra bit in the protection mask is the set-GID bit. This ensures that files created in the socksdir inherit a group ownership of xrdp
, and so the xrdp
daemon is able to access the sockets in this directory.
A patch is made to common/os_calls.c:g_mk_socket_path()
when the package is built to change the protection mask on a created socksdir to 03777. This patch is needed to avoid a possible race condition between the xrdp-sesman
and xrdp
daemons when the sub-system is started. Without the patch, it is possible for the xrdp-sesman
daemon to set the permissions on the socksdir to 01777.
On Debian, Xorg
is not run as set-uid root. The same considerations apply to the X server socket as apply to the xrdp-chansrv
sockets described above.