SSH introduces a very nice feature to users, which is X11 forwarding. With the use of a simple switch when connecting to the remote server, the X11 connection is automatically set up; no need for xhost and export DISPLAY commands anymore. Apart from the obvious benefit in usability, the real advantage is the added security: unlike with the usualy "xhost" method, other users on the target system will not be able to hijack your X11 session aqnd, say, run an xkey to sniff your keyboard strokes.
However, if you use su or sudo to start a command or shell as another user, you will loose this X11 connection, and will have to set it up manually again. I have seen a lot of admins fall back to the old xhost+export DISPLAY way, thus giving up advantages of X11 forwarding, and introducing real security concerns in the datacenter.
Typical uses and why security is needed
Typically in datacenters, policies (usually linked with refulations) dictate that users and administrators log in to the servers using their own personnal account, in order to be able to guarantee accountability of all actions performed.
On the other hand, a lot of actions need to be performed using shared, technical users, such as root, tomcat, ... Hence, after people have logged in with their personal account, they user su or sudo (or any other means) to then run commands as these shared users. Sometimes these commands are inteneded to start an administrative GUI which requiresX11 support.
Often, the concerned servers can be logged onto by many users or administrators. Thus, the typical host-based access control for X11 (the xhost command) are unsifficient, in that any user logged on the same server as us will then be able to "hijack" our X11 session. That's why more secure authentication mechanisms (see xauth) exist, so that only the user has access to his own session.
Manually forwarding the X11 connection through sudo
Suppose you have connected to a server through SSH, with X11 forwarding enabled; in fact, the same would apply for any connection with X11 support (although if you are using hostname-based access control, this whole discussion will not apply). You can take a look at the DISPLAY settings, as well as your X11 credentials:
osa@ubuntu:~$ echo $DISPLAY
osa@ubuntu:~$ xauth list
ubuntu/unix:10 MIT-MAGIC-COOKIE-1 c95369ebdce45f8a14e1c883d08f949e
Now, run a sudo command involving running something as another, unprivileged user; for example, open a shell:
$ sudo -u tomcat -s
Because you have not re-initialized the environment in the same way as a login does (equivalent to
sudo -i or
su - tomcat, you have kept the DISPLAY environment variable; however, you don't have the X11 credentials anymore, since you cannot read the xauthority file of the original user:
tomcat@ubuntu:~$ echo $DISPLAY
tomcat@ubuntu:~$ xauth list
xauth: /tmp/ssh-xauth-JqaWGN/xauthfile not writable, changes will be ignored (This is an ugly error message because that file cannot even be read)
The trick is simply to manually add the credentials displayed above, using the xauth command; they will be added to the
.Xauthority file in the homedir of the current user:
tomcat@ubuntu:~$ export XAUTHORITY=/home/tomcat/.Xauthority
tomcat@ubuntu:~$ xauth add ubuntu/unix:10 MIT-MAGIC-COOKIE-1 c95369ebdce45f8a14e1c883d08f949e
xauth: creating new authority file /home/tomcat/.Xauthority
Now verify that you can run a program requiring a X11 connection:
This is all fine, but there are two drawbacks:
- You need to run a shell with sudo, in order to run the
- If another user has the same sudo rights as you, he will be able to read the
.Xauthorityfile, and thus steal your credentials and hijack your session
Another way is to prepare an alternate
.Xauthority file, and use it by pointing the XAUTHORITY variable to it, in the context of the target user. A simple way is to add the
XAUTHORITY=myxauthfile assignment as an argument on the sudo command-line; this way, it will even work with
$ echo $DISPLAY
$ xauth list
ubuntu/unix:10 MIT-MAGIC-COOKIE-1 c95369ebdce45f8a14e1c883d08f949e
$ xauth extract /tmp/mynewxauthfile ubuntu/unix:10
$ chmod 644 /tmp/mynewxauthfile
$ sudo XAUTHORITY=/tmp/mynewxauthfile -u tomcat xclock
Of course, with this setup, everybody will be able to read the Xauthority file, and the security of your X11 session will be compromized. The trick is to hide this xauthority file, so that if you don't know the exact name of the file, you won't be able to read it.
Doing this way has two benefits:
- You can now run any command with sudo, without having to open a shell first to add the xauth credentials before launching the desired command
- Security is improved, because only people having access to the environment of the started process will be able to determine the content of the XAUTHORITY variable (and thus the location of the xauth file) and thus hijack your X11 session.
xsudo is a wrapper around sudo, which performs the necessary steps to properly create an appropriate xauth file, as well as set up the DISPLAY and XAUTHORITY variables. It can simply be used as is in lieu of sudo; after setting up the new xauth file, it will simply call sudo with the arguments it was given.
It is important to note that xsudo runs with the identity and privileges of the calling users; it is not a set-uid root program, nor does it need to be called with sudo. As such, it does not need to be trusted in any way: it simply runs commands that the calling user would be able to run manually. From a security point of view, it means that the tool does not introduce new potential vulnerabilities.
Another big benefit of the tool is that it creates an authority file in a way that it is hidden from any user but the caller. In other words, nobody will be able to use the file without knowing its full name.
How xsudo works
Xsudo basically prepares a new Xauthority file (as shown above), by extracting the proper token from the current environment, based on the value of the DISPLAY variable. After having properly created the file, it simply calls sudo with the arguments it was given, prepending variable assignments for XAUTHORITY (pointing to the newly created file) and DISPLAY (with the current value). It is necessary to add the DISPLAY variable in case the
-i option of sudo is used, which would otherwise simply clear this variable.
The core work of xsudo is to hide this new xauthority file, so that without knowing the path to the file, one will not be able to read it. In a way, the content of the XAUTHORITY variable becomes the security token which will permit the use of the X11 connection: if you know the content of the variable, you are able to read the file and its token; if not, then you don't know which file to read, and thus you cannot access the token.
To hide the file, xsudo first creates a directory in the form "
xsudo_<hostname>.<pid>" (in a configurable location, usually in /tmp), and assigns permissions 711 (read for owner, but only execute for rest of world); these permissions do not allow other users to list the content of the directory, but still allow them to access files in it.
Then, a file with a random name is created within this directory. The random name is built using the hex representation of a 128-bit cryptographically secure random number, taken from /dev/random or /dev/urandom (configurable); because there is no birthday attack on the filename, using a 128-bit number gives a 128-bit security, which is by far enough for almost any application (note that the size of the random number is configurable). Because the random number is cryptographically secure (we assume this, as the definition from /dev/random and /dev/urandom), there is no way for any other user to guess or predict what this number is.
It is interesting to think about what would happen when calling xsudo from a shell opened with xsudo (that is, xsudo within xsudo). For example, assume the following scenario:
osa@ubuntu:~$ xsudo -u admrole -i
admrole@ubuntu:~$ xsudo -u swx -i ebs_adm swx1
That would be for a company where system administrators have access to an "admrole" user, intended for performing administrative actions, with enhanced rights (but still not root); this user itself can run any command as technical users, for instance tomcat. We will not debate here whether that is the best technical choice to implement the corresponding role-based access controls.
The first call to xsudo will create an xauthority file which is hidden from the admrole user; hence, other sys admins having the same rights will not be able to see this xauthority file, so that without the value of the XAUTHORITY variable, they will not be able to read it.
The second call to xsudo would then create a new xauthority file, which would not ne hidden from the admrome user; that means that any system administrator with the same rights will be able to find and read the file, without access to the XAUTHORITY variable. That means that the second call to xsudo has weakened the security of our X11 session.
The workaround in such cases is simple: when XAUTHORITY already points to an xauthority file generated by xsudo (hence with a pre-defined pattern in the filename), xsudo, when called, will simply re-use this xauthority file as is (and thus keep the XAUTHORITY value), instead of creating a new one. Hence, security of the session is not impacted be re-intrant calls to xsudo. Another way to look at this approach is that the first xauth file created by xsudo is tied to the session or the terminal. This makes sense, as the X11 connection is usually bound to the X11 session.
The drawback to this approach is that the user is expected not to change his X11 environment (DISPLAY variable or xauthority) after the first call to xsudo. In practice, there should not be such a need: once the X11 session is set up (for example simply by using X11 forwarding with SSH), you don't change it for the duration of your SSH session.
As was stated above, the tool is run will the caller's privileges, so that it does not have to be a trusted component of your system: it only performs operations that the caller is already allowed to. This means that it will not introduce new vulnerabilities on your system. However, it provides a functionaility, that of forwarding the X11 connection through sudo; it is worth analyzing security of that particular functionality and how it is implemented.
First, it must be noted that, like for any type of X11 connection, the target host (X11 client) has to be trusted: any process or user with root privileges will be able to inspect all your processes, your credentials, and use your connection. Hence, xsudo will not protect you against root.
The concept of xsudo is to have the XAUTHORITY variable become the security token: you can access the connection if and only if you know the proper value to use for that variable.
- Hence, a process or user which is able to inspect the environment of the process you started with xsudo will be able to read the XAUTHORITY variable and thus access your session.
- Similarly, any process or user which is able to inspect the behaviour of the process started with xsudo will be able to determine the path to the xauthority file or the X11 secret token itself. For example, if you are allowed to trace the system calls of the started process (truss on Solaris or strace on Linux), you will intercept the system call to open the xauthority file.
- In a same way, any process which is able to inspect the behaviour of xsudo itself (when the new xauthority file is created or when sudo is called) will be able to get the session token and access your session.
As a result, in general, your session is not protected against processes running as the calling or target users, or people beeing able to run any command as one of those users. Note that finding out your X11 token might not be a trivial task nontheless and requires a bit of technical knowledge.
It must be noted that this weakness (vulnerability to processes of the calling or target users) is probably true for any means of forwarding the X11 connection. In fact, as soon as you are using an X11 connection, if somebody is able to observe your X11 processes (and especially during the authentication phase), then he well be able to access your session; that is true even without using sudo, as soon as you have an X11 connection, without considering how this X11 session was set up.
Another interesting factor is the vulnerability window. Suppose that you consider the target user as untrusted, so that you can expect your session to have been accessed as soon as you use xsudo to run an X11 process as the target user. Once an attacker has been able to read your X11 authentication token, he will be able to access your X11 session even after you xsudo session has stoped; indeed, the token remains valid after xsudo has ended (after all, xsudo only provides a means to automatically transport the token to the target command).
What this means is that once your session has been possibly compromised, it will remain so until you invalidate all tokens; with an SSH-forwarded X11 session, that means until the SSH connection is closed.
Any process running as the calling user will be allowed to trivialy access the X11 token, as the secret file will not be hidden to that user. Xsudo provides an ehnacement in case you need to protect yourself against processes running as the calling user: the holding directory itself can be created in a hidden way, so that nobody but root will be able to locate the secret file (not even the calling user). This requires preparing a directory owned by root (for example /var/run/xsudo), with access rights similar to /tmp, except that read access is denied to everybody (translates to chmod 1733). You could also put this directory on an NFS server, with a configuration such that even root is not allowed to access the file (no root access on the NFS share). However, even with such a setup, you remain vulnerable to observability (truss, strace, ...) attacks, which are however not trivial to perform.
Xsudo introduces a security benefit, mainly by promoting use of SSH X11 forwarding, by releiving users from the task of setting up the X11 connection after a sudo. Thus, when using SSH forwarding together with xsudo, users do not have to take care of setting up anything related to X11 anymore; this makes their life very easy, and by automatically using technical means which guarantee a good level of security. When users do not need to mess with X11 session details anymore, they will stop using host-based access control, which is less secure.
Xsudo, however, does not solve inherent issues with X11 session security, mainly that three users have to be trusted: the root account, the calling user and the target user. Mitigating these risks (if needed) require other, more intrusive means, such as preventing process observation (xsudo will then be very useful, because of the way it hides the xauthority file), or using session recordings and audit.