Saturday, April 23, 2011

The Linux Security Circus: On GUI isolation

There certainly is one thing that most Linux users don't realize about their Linux systems... this is the lack of GUI-level isolation, and how it essentially nullifies all the desktop security. I wrote about it a few times, I spoke about it a few times, yet I still come across people who don't realize it all the time.

So, let me stress this one more time: if you have two GUI applications, e.g. an OpenOffice Word Processor, and a stupid Tetris game, both of which granted access to your screen (your X server), then there is no isolation between those two apps. Even if they run as different user accounts! Even if they are somehow sandboxed by SELinux or whatever! None, zero, null, nil!

The X server architecture, designed long time ago by some happy hippies who just thought all the people apps are good and non-malicious, simply allows any GUI application to control any other one. No bugs, no exploits, no tricks, are required. This is all by design. One application can sniff or inject keystrokes to another one, can take snapshots of the screen occupied by windows belonging to another one, etc.

If you don't believe me, I suggest you do a simple experiment. Open a terminal window, as normal user, and run xinput list, which is a standard diagnostic program for Xorg (on Fedora you will likely need to install it first: yum install xorg-x11-apps):

$ xinput list

It will show you all the pointer and keyboard devices that your Xorg knows about. Note the ID of the device listed as “AT keyboard” and then run (as normal user!):

$ xinput test id

It should now start displaying the scancodes for all the keys you press on the keyboard. If it doesn't, it means you used a wrong device ID.

Now, for the best, start another terminal window, and switch to root (e.g. using su, or sudo). Notice how the xinput running as user is able to sniff all your keystrokes, including root password (for su), and then all the keystrokes you enter in your root session. Start some GUI app as root, or as different user, again notice how your xinput can sniff all the keystrokes you enter to this other app!

Yes, I can understand what is happening in your mind and heart right now... Don't worry, others have also passed through it. Feel free to hate me, throw out insults at me, etc. I don't mind, really (I just won't moderate them). When you calm down, continue reading.

In Qubes the above problem doesn't exist, because each domain (each AppVM) has it own local, isolated, dummy X server. The main X server, that runs in Dom0 and that handles the real display is never exposed to any of the AppVMs directly (AppVMs cannot connect to it via the X protocol). For details see thistechnical overview.

You can repeat the same experiment in Qubes. You just need to use the ID of the “qubesdev” device, as shown by xinput list (should be 7). Run the xinput in one of your domains, e.g. in the “red” one. Because we actually use the same device for both mouse and keystrokes, you should now see both the key scancodes, as well as all the mouse events. Notice how your xinput is able to sniff all the events that are destined for other apps belonging to the same domain where you run xinput, and how it is unable to sniff anything targeted to other domains, or Dom0.

BTW, Windows is the only one mainstream OS I'm aware of, that actually attempts to implement some form of GUI-level isolation, starting from Windows Vista. See e.g. this ancient article I wrote in the days when I used Vista at my primary laptop. Of course, it's still easy to bypass this isolation, because of the huge interface that is exposed to each GUI client (that also includes GPU API). Nevertheless, they at least attempt to prevent this at the architecture level.

27 comments:

Anonymous
said...

Try this with SELinux sandbox... "sandbox -X xterm" (on F14 or RHEL6... install policycoreutils-sandbox if needed). It does not see keys destined for another window. This is because sandbox -X also uses its own X server (Xephyr).

The primary problem with SELinux sandbox is that it still relies on the big, buggy, bloated Linux kernel to enforce security. In Qubes we rely on Xen to enforce domain isolation (a few orders of magnitude less code, I would say 10^3 less, even including the few daemons/backends we also have in Dom0 and which are reachable from VMs).

Second, SELinux sandbox X server isolation doesn't really eliminate all the attacks coming over the bloated X protocol. As a result it is relatively easy to attack. See, e.g. this paper from Rafal for example of an escape:http://www.invisiblethingslab.com/resources/misc-2010/xorg-large-memory-attacks.pdf

In Qubes the only point of contact to the real server is our GUI daemon -- see the reference quoted in the blog post for details on the protocol we use. Compare this now to the X protocol. It's orders of magnitude simpler!

SELinux sandbox creates an X server instance (Xephyr) per each sandboxed app, which sounds to me like a huge resource waste. In Qubes we have one X server instance per *domain*.

SELinux sandbox doesn't offer any desktop integration, such as secure copy-and-paste operation. We provide secure inter-domain clipboard on Qubes -- again see the above-quoted reference for technical details.

Finally, SELinux sandbox requires the user to setup complex SELinux polices to achieve also filesystem-level and network-level isolation. In Qubes all the domains are automatically isolated on all those levels.

I would be interested to know what you think about capability-based security (as in the Capsicum project), and how it compares to what you do in Qubes.

From what I understand (but I know very little about security), capabilities allow the same level of security as Qubes, or even better, but they need the applications to be modified, which seems unrealistic. Is that correct ?

Anyway, I'm not good enough to beta test, but I can't wait for a stable release, to see what it is like to use a system like Qubes.

@rinaku: Capsicum currently doesn't support GUI-level isolation, but I think they're planning to add it at some point in time. When this happens we would seriously consider using it inside our domains, to bring some isolation into each domain as well (currently there is no isolation between apps running in the same domain, specifically for reasons given in the blog article above).

Capability-based systems, as you pointed out, require application modifications. This also means they cannot protect against intentionally malicious apps. Thus I see them as complementing Qubes, but never replacing it. Also, note that capsicum works only on app-level, but cannot protect against e.g. network subsystem compromises (cannot isolate the networking subsystem or other drivers). In Qubes we can easily do that e.g. via NetVM. Another reason to think about it as something to complement Qubes (and to run it inside a domain).

How old/young has somebody to be to write "....designed long time ago by some happy hippies who just thought all the people apps are good and non-malicious..." ?

The problem is the other way around. These guys created some awesome software tailored to their problems and means. Using it 20 years later in a different environment/world is the fault, not their initial design.

Very interesting indeed. I didn't know about this threat and doesn't seem to be fixable. Nevertheless I wanted to know if this is the case for wayland. It would be interesting to run your experiment in it and post the findings on the wayland-devel mailing list.

@Ashish: the security mechanisms you mention have been designed for a totally different security model than the "desktop GUI security" that is prevalent today.

The point is, as correctly made by some other commenter, that X have been designed long, long, time ago, in different realities, for solving different problems, but the Linux community has blindly adopted it to current conditions, failing to see that it really doesn't fit today. Why do you think the title of this post is "*Linux* Security Circus" instead of "X Security Circus"? (Yes, I know, the problem also affects other OSes, such as e.g. *BSD, etc).

@fliebel: In Qubes all the keystrokes are first processed byt he *trusted* window manger running in Dom0 (the trusted partition). Then, they might be consumed by Qubes (e.g. if this is a global clipboard management sequence, or perhaps the "Expose" sequence), or passed down to the *active* domain's local X server.

VNC is just a regular app running in one of the domains. No special VNC for Qubes is needed.

So I will when I have some free time.But as it is your research topic, I expected you had already done that or even contacted the developers to inform them.As it is still under heavy development, I guess it is a good timing to implement good stuff and for expert like you to advise them.

@phocean: Don't kid me, kid! What I did here was not a "research" (you might want to check some real research we did at ITL on our website). That was just a Saturday morning blog post with an aim to save some lost souls, like yours... And I really don't have time to go and test all the software in the development that is out there. I do have real job, that among other things includes doing *real* research...

About gksudo: perhaps it somehow owns the input only to itself for the period of displying its prompt window? I bet you cannot use other apps until the window is present?

But that's probably irrelevant, because I bet that once you switch to a different user and start some apps as this new user, then xinput will be able to sniff all those keystrokes without any problem (and you could also easily write a program that could be injecting keystrokes to those apps).

I don't ask you to waste time on an explanation; you could as well just direct me to a source of information. What I wonder is: what's the real danger of the current sloppy model?

My question is based on the fact that all network connected systems can be remotely compromised, with or without a window system. What priority does this in theory sane improvement get in relation to established precautions?

I understand it's difficult to objectively answer that, while you at the same time invest time in a project addressing described issue.

Correction: I was wrong about Xace being dead -- it has been apparently merged into the mainstream Xorg. Its just that... apparently nobody uses it, because it just not suited to solve the problems we talk about here. See e.g. this presentation from Dan Walsh (SELinux maintainer), slide #12: