# Protecting HOME, Xorg keylog/screencap and vulnerable apps

## devPenguin

Aka GUI Isolation and a bit more.

Presuming your Internet browser/IM client/torrent client/PDF viewer/flash plugin is exploited, what is stopping it from accessing all your files, keylogging and making screenshots in Xorg? Unless you're heavy on selinux/apparmor, absolutely nothing.

This will be about achieving a reasonably secure web browsing/im experience by using GUI isolation with nested X servers and using a different user account for each application that accesses the internet. The isolated programs cannot do trivial X keylogging and screenshots (they can, but only in their own little nested X server, not in the main server), they only have access to the files in the user account they belong to. 'Reasonably secure' is always highly subjective.

This setup has to be easy to use and as transparent as possible to the desktop user.

I am not using selinux or other such patches and I'm also not chrooting, that should be investigated. 

I am aware that I might be creating a problem out of thin air just to have something to fix, but my logic states the following:

1)I have important / sensitive files in my home dir: emails, private keys, passwords, porn, financial data, calendars, confidential company information, source code. Many of us do. I cannot keep them somewhere else because I'm working with them.

2)All applications that run under my user account connecting to the internet might have vulnerabilities, and it just takes a peek on the firefox/chrome/flash/adobe reader vulnerability list to see why this might be a problem.

3)All those applications (2) have by default UNLIMITED access to all the files at (1) and could, if exploited/misused abuse that access.

4)All those applications (2) have unlimited access to the keyboard/mouse/screenshots in the one X server they all use and could, if exploited/misused abuse that access.

To sum it up: they all have full access to all my files, they have free access to the internet and they can be fairly vulnerable due to the very nature of the web.

Complicated fixes: selinux/XACE & apparmor, I'm sure there are others.

Software needed: 2 window managers - I'm testing this with awesome/openbox, feel free to use whatever you like, Xorg compiled with kdrive use flag (this fetches Xephyr) and a certain patch I found on a couple of mailing lists, a small wrapper program for Xephyr, evdev support, a user account for the browser, another for the IM program and so on.

Recommended reading / credits go out to: 

Fedora/RHEL with their sandbox-x project http://people.fedoraproject.org/~dwalsh/SELinux/Presentations/sandbox.pdf

The Xephyr resize patch (Thomas Liu/Vic Lee) / testcase.c http://bugs.freedesktop.org/show_bug.cgi?id=25804

BIG thumbs down to Xorg for not handling this...

The Invisible Things Lab's Blog: http://theinvisiblethings.blogspot.com/2011/04/linux-security-circus-on-gui-isolation.html

Qubes OS http://qubes-os.org  and their architecture PDF http://qubes-os.org/files/doc/arch-spec-0.3.pdf

I needed to do something similar to the above but without using selinux, without using another operating system and keeping things usable for me as a desktop user. My first thought was using virtualbox/qemu and installing another os inside to run the browser. What a waste of resources...

--use flags

Add the kdrive use flag. Make sure you're using evdev at the INPUT_DEVICES (and kernel of course).

--xephyr patch

One might wonder why the following patch (see above for link to bugs.freedesktop.org) is needed. Xephyr is an embedded X server with really good performance. But its window/contents do not resize when the parent window does. I can't live without that, makes things a lot less usable from my perspective, if you think you can do without then please skip this and continue from testcase.c

Xorg version number may be different, I tested both 1.10 and 1.9 and it worked.

ebuild /usr/portage/x11-base/xorg-server/xorg-server-1.10.1.902.ebuild unpack

cd /var/tmp/portage/x11-base/xorg-server-1.10.1.902/work/xorg-server-1.10.1.902/

patch -p1 < !!INSERT THE ABOVE MENTIONED Xephyr PATCH HERE!!

ebuild /usr/portage/x11-base/xorg-server/xorg-server-1.10.1.902.ebuild compile

ebuild /usr/portage/x11-base/xorg-server/xorg-server-1.10.1.902.ebuild qmerge

A xorg restart might be in order.

--testcase.c

The testcase creates a simple parent window for Xephyr to use.  It outputs the X window id so Xephyr will use that as the parameter. Running Xephyr without this parent window and resizing it can and will lead to chaos, it enters some sort of resizing loop/race condition.

Download testcase.c (from the same place as the patch) and modify it to only output %i , the gtk_socket_get_id and not the additional text  (there's only one  g_print line, find that).

gcc -o testxephyr testxephyr.c -Wall `pkg-config --cflags --libs gtk+-2.0`

--starting servers

First of all start your regular X session. I am testing this with awesome as the 'host' window manager on the :0 host xorg server.

I am obviously no bash wizard, but I am running this on X startup to automatically start 2 guest Xephyr sessions inside 2 parent windows inside awesome inside host xorg. testxephyr outputs the window id in nohup.out, that gets parsed and one Xephyr process starts in each of the windows. Run this as your regular user (the one that did startx).

killall testxephyr -KILL

rm nohup.out

nohup ./testxephyr &

nohup ./testxephyr &

sleep 1;

((a=1)); 

for i in `cat nohup.out`; do   ((a++)); (Xephyr -keybd ephyr,,,xkbmodel=evdev,xkblayout=us,xkbrules=evdev +extension RANDR +extension DAMAGE +extension Composite +extension RENDER +extension X-Resource +extension XVideo +extension XINERAMA -dpi 96 -parent $i :$a & ); done

That script could certainly be improved but works as-is.

The -keyb switch is probably the most important of them all. Again, make sure you're using evdev for this and you do NOT specify an exact device ID or any keylogger protection this provides is nullified. When you do not specify and exact device, some magic goes on and Xephyr makes its own virtual keyboard device. If you do specify a device, it gets its data from the host Xorg on :0. Xephyr has a bug (default behavior/feature?). If not done right, your keyboard will either not work at all, or your arrow keys will get messed up. If there is a problem regarding this, please read the xmodmap part.

The '+extension' flags are up to you,  run 'Xephyr +extention asdfg'  (non-existent random extension name) to display all the available extensions. Performance varies depending on flags, but I got real time performance on youtube with flash on this so I'd say it's at least decent.

What you should have at this point are embedded X servers running on :2 and :3 displaying as windows on your :0 host server.

--adding users

Add one user for firefox, one for pidgin and so on, you would need a Xephyr process for each user so keep that in mind. Make sure the /home permissions are right so they cannot read the home dir of your main user.

--starting guest sessions

You could probably just log in as the dedicated browser user and execute  DISPLAY=:2 firefox, however I recommend using an openbox session inside xephyr first, so you can maximize the browser window. This is nice because as you resize the xephyr parent window on your main Xorg on :0, the guest Xephyr server on :2 senses that, signals openbox to resize and firefox gets resized to what it should be (if maximized). Makes my head spin, but it works and provides seamless resizing.

To recap, assuming the main user is 'gentoouser' and your firefox user is 'firefoxuser',  you would have  

firefox (firefoxuser)  -> openbox (firefoxuser) -> Xephyr :2 (gentoouser) ->testcase (gentoouser) -> awesome (gentoouser) -> Xorg :0 (root, unless specified)

--troubleshooting: openbox fonts are REALLY small sometimes

I get this sometimes, something wrong with the dpi, just run  DISPLAY=:2 openbox-session & DISPLAY=:2 firefox and you'll be fine, since the firefox fonts are 100% normal, just the window decorations are affected by this.

--troubleshooting: xmodmap, keyboard is messed up, the arrow keys don't work, page up/page down behaves wrong, and so on

This should not happen if evdev is used right (try NOT using "keyboard mouse" in INPUT DEVICES in make.conf). One way to fix this is with xmodmap:

From your regular host user run: xmodmap -pke > ~/xmodmapfile  , copy that file to the user home of the guest users. Every time you run openbox, load that file with xmodmap ~/xmodmapfile. That should fix it.

--troubleshooting: Copy paste is broken!!!

Yes, it is. Fix it and please let me know.

--troubleshooting: If I have 2 xephyr guest servers and have user1 connecting to :2 and user2 connecting to :3, what is stopping user1 from connecting to :3 and user2 from connecting to :2

Absolutely nothing. This setup does not protect the 'guest' programs from eachother, it protects the host from the guests.

--troubleshooting: But can't guest user1 connect to :0.0 Xorg started by host user and keylog/screenshot that?

It can't on my box, depends on setup.

--troubleshooting: But this does not stop any of the guest users from accessing the rest of the system!

You can use chroot for that, it's well documented. Also good permissions and group management should prevent a lot of bad things.

--troubleshooting: But still, this does not prevent 'insert evil thing here'

No it doesn't. This is a simple and convenient (for me) userland setup, if you want more, you need some sort of kernel enforced protection and you have a lot of reading to do. This protects your home dir files, xorg keylogging and screenshots. That's about it. It's also a convenient way to run several isolated browser instances for testing, running wine and forcing some xorg settings, testing window managers.

----------

