Home Page

Rationale for the X Supervisor Extension


An Analysis of the Common Pitfalls in the Use of OpenSSH

So, you say that OpenSSH is not secure...

No. I am not going to talk of what I believe to be OpenSSH security bugs or design flaws. Rather, I believe that OpenSSH is very good in these aspects. I am going to talk about its use. In fact, most security tools (including OpenSSH) ensure security as long as the user uses them correctly and understands what he/she is doing along with all the consequences of his/her actions.

For example, would you type this?

user@good$ scp -r ~/.ssh evil:foo/

If in ~/.ssh you have some private keys, this copies them to evil. This also means that user@evil and anyone who can impersonate him/her can read the keys: this includes the system administrator of evil and, if evil has some security problems, every cracker that breaks into that system.

Obviously, paranoia suggests that this is a bad thing, unless you really trust root@evil (pun intended) and the security of evil. Generally, it is better to avoid trusting remote hosts and to be more paranoic about security.

What a silly example! I would never copy my private keys on another host!

Good. But what about this?

user@good$ ssh evil
user@evil$ echo this is executed on evil
this is executed on evil
user@evil$ exit
Connection to evil closed.
user@good$ su
Password: (you type your root password)

This may look good, but are you really sure you have not given your root password to root@evil? Are you sure that you exited from ssh? What if the remote bash (or sshd) is malicious? What if exit is interpreted as "print Connection to evil closed. and change the prompt to user@good$"? What if even su is malicious?

Ok, I see your point. However, I work with the X Windowing System and terminal emulators and I always close my terminal after using OpenSSH.

Fine. Did you, perchance, enable the ForwardX11 option in your ~/.ssh/config?

Yes, of course! X forwarding is one of the coolest features of OpenSSH! Why did you ask that?

Because there is a reason for it being disabled by default.

Enabling X forwarding is OpenSSH, you allow remote clients to connect to the local X sever. Thus, root@evil can easily connect his/her clients to your X server too.

Mmmmh... But why should that be dangerous? I do not care if he/she makes some windows pop up. Yes, it is annoying, but I would notice it immediately and it does not do any harm, does it?

An X client does not need to open a new window. Rather, it has full unrestricted access to all the X resources, including the windows created by other clients. For instance, it could take a screenshot of the screen. This allows root@evil to spy what you are doing, reading your mail, etc. This is not good.

Alas, there is worse. Consider the following scenario with two X terminals in two separate windows:

user@good$ ssh evil
user@evil$ echo hi
user@good$ passwd
Changing password for user
(current) UNIX password:

A malicious client from evil could ask to the X server the list of all the windows, and find the window ID of the other terminal easily. Then, it could ask the server to listen to the keyboard events (such as key presses) for that window, thus reading your password as you type it. The other terminal will still work, since it is receiving the keyboard events too and you will hardly notice that something nasty is happening.

This attack will work in most real-life cases and with most terminal emulators (AFAIK). Actually, some X terminal emulators provide a "Secure Keyboard" mode that prevents this attack by taking exclusive access to the keyboard. Since this mode is, IMHO, very inconvenient, most people (even who is aware of that mode) never use it.

Oh! That sounds quite bad. Are there any other concerns?

Unfortunately, yes. The malicious client could:

The last example is the most serious concern. Some clients (notably xterm) refuse keyboard events if they are sent by another client. However, many clients do not do any check. For example, in the following screenshot, a malicious client injects a command into a terminal emulator (gnome-terminal).

command injection attack

In the example above, 0x28000c6 is the window ID of the other terminal. The malicious command is executed by user@evil, but it could be executed by root@evil as well. In the user@good window, the user did not type anything: the command echo hi was "typed" by the malicious client on host evil.

(Gulp!) Why the X server allows this to happen? Why the clients do not do any check?

Why should the server block it by default? Why the clients should?

This and similar features can be useful under a huge number of circumstances, both for the user and the programmer. Some applications must be able to take screenshots, for instance. Window managers deal with windows they do not own. Some applications "swallow" other windows into their own. And so on.

To block these operations by default would be too restrictive.

Ok, but what can I do to fix those security problems? I do not want to disable X forwarding over ssh!

If your X server support the X Security extension, there is something you can do. (Nowadays, most X servers do support it. For example, the popular XFree86 X server, has supported it since a long time)

The X Security extension can be used to run some X clients in a kind of a sandbox, so that they have a restricted access to X resources they do not own. This can be done using untrusted cookies and xauth. If you do not know how xauth cookies work, please read the man page. In most setups, when you start the X server a random number (the cookie) is generated and stored in the file ~/.Xauthority. That file is read by both the server and the clients: when clients connect to the server they send the cookie so that the server can check it and decide whether to allow or to reject access.

However, there are different types of cookies. The one which is stored in the ~/.Xauthority file is (usually) a trusted cookie. Using xauth, you can create untrusted cookies as well: clients that send to the server that cookie will be granted a restricted access and will run in a sandbox. Here is how to use it with ssh:

user@good$ xauth -f ~/.Xauthority.untrusted generate $DISPLAY . timeout 0 untrusted
user@good$ XAUTHORITY=~/.Xauthority.untrusted ssh evil

The last ssh command forwards X connections, but uses the untrusted cookie. Thus, the clients that connect from evil will use the untrusted coookie and will run in a sandbox.

The command-injection attack does not work anymore.

command injection attack blocked

As soon the malicious client sends a X_SendEvent request, the request is rejected by the server with a BadWindow error. In fact, all "dangerous" requests are rejected with some X error (the most common being BadAccess) or, in some cases, ignored and/or restricted.

So, using the X Security extension, I can run remote clients within a sandbox. Well-behaving clients will still run smoothly and malicious clients will be stopped. Am I right?

Almost. It depends on the definition of "well-behaved". If you define "well-behaved" client as a client that is never blocked by the Security extension, then currently most X clients are not well-behaved. This is because a client usually needs to interact with other clients for certain operations (as copy&paste, for instance), thus triggering some security constraint and receiving some unexpected error. Moreover clients are usually not prepared to deal with X errors and often die unexpectedly.

In the following example there are three terminals. The topmost is a local client that runs OpenSSH and is connected to evil. As you can see, I launched an xterm from it. The remote xterm is the middle window. The bottom window is just another local terminal. I selected some words in the middle xterm.

before copy&paste from an untrusted xterm

If I try to paste the "text to copy" in the bottom terminal, this is the result.

after copy&paste from an untrusted xterm

The xterm window suddenly closed. In the top terminal we can see it received a BadAtom error. This is because the xterm was going to send the selected text to the other window with a X_ChangeProperty request, and the X server stopped it.

A lot of currently used X clients conflict with the sandbox: for instance, GNU emacs dies if you try to select some text, netscape dies immediately when starting and every GTK+ 1.2 application dies when a menu is opened.

Therefore, if you use the X Security sandbox, do not be too surprised if X clients die unexpectedly.

The security policy seems too restrictive... Can I configure the security policy to suit my needs?

Unfortunately, the X Security extension policy is rather fixed. Actually, there is a SecurityPolicy file that allows to configure some aspects of the policy, but it mainly deals only with window properties and that can be not enough in many cases.

Argh! If I choose the safe way, I break compatibility with currently existing X applications. If I instead want compatibility I must give up security. What can I do?

<plug mode="shameless">
You could use the X Supervisor extension instead.

The X Supervisor extension is heavily based on the X Security extension and the sandbox it provides. In fact, it can be seen as an extension to the X Security extension.

Using it, you can run your untrusted clients in the sandbox provided by the X security extension. However, when a potentially dangerous request is received by the server from an untrusted client an X error is not sent to the client. Instead, a message is sent to a special client (the supervisor) and the untrusted client is put on hold. The supervisor examines the request and, according to its policy, tells the server to accept or refuse the request.

This approach has the following advantages:

Is that extension implemented in my X server?

No. This project is developing the final specification of the X Supervisor extension and its implementation for the XFree86 X server. It is still in development stage. However, a prototype has been completed.

Can you show to me that prototype "in action"? For example, what does it do in the above example with xterm and the copy&paste?

Sure! Under the same situation (copying text from the middle xterm to the bottom local terminal), here is what happens when using the current prototype:

after copy&paste from an untrusted xterm, with the supervisor

A dialog appeared with some cryptic information and two Yes/No buttons. Since this is a prototype, the dialog is quite ugly and full of debug stuff useful only to its programmer, who is probably the only one that knows what the buttons do (but it is easy to guess).

However, cosmetic aspects aside, you can guess that the dialog is telling us that some client asked the server to do something potentially dangerous. The dialog actually shows the identity of that client (the subject): it owns a window with ID 0xa0000e and with name "user@evil - xterm". It is obviously our xterm. The dialog also shows what the xterm was going to do: a ChangeWindowAttributes operation on the object with ID 0x80002c. Alas, the prototype is not smart enough to show that the object is nothing but the bottom terminal. This will hopefully be implemented soon. The buttons are (you guessed it, didn't you?) for accepting or rejecting the client request. If "No" is pressed, an error will be sent to the xterm, which will likely die. If instead we accept the request by pressing "Yes", the xterm continues the copy&paste operation. Actually, we must press "Yes" some more times for the copy&paste to be completed, but after doing that, the string "another text to copy" appears on the bottom terminal.

This is indeed a prototype: in the current form it is useful only to people who know the X core protocol to some extent. While the experienced X programmer can easily see that dialog and think "the xterm is setting the event mask on the bottom terminal to 0x00400000, thus listening for the PropertyChange events", the random Joe user can be really confused at that sight.

There is still much work to do, both in the supervisor client (design a better and more useful user interface, implement a better policy, etc.) and in the server.

SourceForge Logo Valid CSS! Valid XHTML 1.0! Last update: 24 Jul 2002 by zunrob