Thursday, October 13, 2011
The X Window System
Hi all reader Now I`ll try present The X Window System,Up to this point we've been immersed with Netcat and the command line. Some users view command-line tools as cryptic and less functional than a graphical-based counterpart, while others viewcommand-line tools as efficient
and less cumbersome. Either way, command-line tools can't accomplish every task as easily as you might hope.
Graphical tools can help visualize data and put it into a form a user can interpret. Microsoft's windowing subsystem has become the core of its operating systems. You can't install a Windows operating system and just interact with it using the command line; the windowing subsystem is too integrated. The windowing subsystem for Unix-based systems, the X Window System (X), is an optional, albeit highly useful, install.
You're going to need X for many of the tools covered in this book, so a brief description of this system is provided here to demonstrate how it works and how to secure it. The installation and configuration options are extensive and beyond the scope of this book, but we'll aim to give you a general understanding of what's going on in X. We'll also touch on some inherent security concerns with X that you'll want to keep in mind.
CHOOSING A WINDOW MANAGER
A trivial but important detail about X is that it doesn't come with a window manager or Desktop by default. X handles your keyboard, mouse, and output screen. It comes with a basic system that lets you "place" windows in locations on the screen and then terminate those windows. The fancy menus and toolbars are left to the window managers that run on top of X. Several window managers are available, including the popular Gnome, KDE, and Window Maker applications. Microsoft X Window System emulators like ReflectionX and Exceed also have their own built-in custom window managers. It's important for you to remember that X is only the underlying architecture for the windowing system; it has nothing to do with the look and feel of that graphical environment.
A CLIENT/SERVER MODEL
X uses a client/server model. The actual windowing system acts as the server, and the graphical programs act as the clients. When you're on a box running an X server and are starting graphical applications like xterm or xemacs on that same box, the client/server interaction is rather transparent. The server portion of X listens on a socket (an IP address and port combination), much like other services. The client, for example xterm, connects to the server in order to display the appropriate window. In the case of xterm, the window is merely a command-line terminal displayed in X. Scroll bars, contextual menus, and the mouse pointer are all handled by the window manager. So, in this scenario your graphical desktop appears to work just as it would if you were using a Microsoft Windows system.
But what if you're running an X server on HOST1, you're in a secure shell session on HOST2, and you want to run xemacs on HOST2? You need a way to tell the xemacs client on HOST2 to use the X server on HOST1 to display itself. If you think about it, this is backward from most client/server thinking. Usually, if you are on a system and need access to a remote resource, you use a local client application to connect to a remote server that provides the resource. With X, however, you have to run the server on your local system and then have the remote resource (the client) connect to you. In other words, you send the remote client from HOST2 to your local server on HOST1 in order to interact with the client as if you were physically using HOST2.
HOW REMOTE X SERVERS AND CLIENTS COMMUNICATE
Suppose that you are physically in front of HOST1 and using this system as your primary desktop. Then, you remotely log in to a command-line shell (bash or tcsh) on HOST2 using secure shell (hopefully not the less secure telnet!). You can tell HOST2 to use HOST1 for graphical application display by specifying it on the command line of the X application you're running:
HOST2% xemacs --display HOST1:0.0
You can force all X applications to use HOST1 for display by setting a DISPLAY environment variable within the shell. So in your HOST2 shell you'd use the following commands for a Bourne shell (typically the default on Linux and BSD systems),
HOST2% DISPLAY=HOST1:0.0; export DISPLAY
or use this command for C shells (the default for Mac OS X):
HOST2% setenv DISPLAY HOST1:0.0
Normally, you expect a command to execute on the system on which it was run. In the case of a remote X-based application, you still want the application to execute within the context of the remote server, HOST2, but you want to see the output on your localhost, HOST1. Once you have changed the DISPLAY variable, xemacs will attempt to display itself on HOST1. Without the modified DISPLAY variable, the X client would have popped up on the screen of HOST2—much to the surprise of anyone currently using it! The flow of the X client/server model is illustrated here.
where hostname indicates the name or IP address of the host running the X server, displaynumber indicates which X server the X clients should use, with 0 being the first, and screennumber indicates which screen on the X server should be used, with 0 being the first.
Unless you're using an interesting X server configuration, your DISPLAY will almost always be :0.0. In fact, you can leave off the.0 part because it assumes screen 0 by default.
X servers listen on TCP port 6000 by default. If a second X server (a display) was run on the same box, it would listen on TCP port 6001. The display number that the X server is using can always be mapped to the corresponding TCP port by adding 6000 to the display number.
Tip Secure Shell actually handles the DISPLAY variable for you, but it's important to understand how X clients and servers interact. Check out the next section for information on further securing X.
You may see a bit of a security problem in this client/server model. Setting the environment variable let us tell the client on HOST2 to display on HOST1. But what's stopping you from sending the display of the application elsewhere? One of the most popular "hacks" in security training classes is setting your DISPLAY variable to your neighbor's X server and watching with amusement as you run numerous instances of xeyes all over his Desktop while he's trying to do work. A more frightening abuse would be to run a program that captures your neighbor's keystrokes from the X server and sends them, passwords and all, to you. Obviously, X servers must have some kind of access control so that only authorized clients are able to display themselves.
SECURING X HOSTS WITH XHOST AND XAUTH
Because X interacts with your keyboard, mouse, and screen, leaving an X server unrestricted is a dangerous thing to do. Not only can it allow someone to pop up windows on your screen, but someone could run an "invisible" application that could capture keystrokes and mouse movement, or even silently observe the victim's entire display. You can use two built-in methods for locking down your X server: xhost and xauth.
Xhost gives you hostname/IP-based control of who can connect to your X server. The syntax is extremely simple. To allow HOST2 to use HOST1 as a display, you need to make sure that HOST1's X server is running and issue the following command on HOST1 (from an X terminal window, for example):
bash% xhost +HOST2
If you want to explicitly deny access to HOST2, try this:
bash% xhost -HOST2
Fortunately, xhost denies all by default. You can use xhost to add specific hosts to your "allowed" list. You can also allow access on a global basis (disabling access control) by simply running xhost +. This is not recommended, as anyone with unfiltered network access to your machine will be able to run applications on your X server. xhost - will re-enable access control, allowing access only to the hosts in your "allowed" list. To see the machines that are currently allowed to use your X server, run xhost without any options.
Note xhost – commands only deny future access; they do not terminate current connections.
Xhost isn't a terribly secure method of access control, however, because it doesn't require a user-based password or token authentication, and there's no encryption. All you're really doing is allowing anyone on a particular system to access your X server. It's the same reason that IP-based access control on firewalls isn't a good solution for a Virtual Private Network (VPN); you're relying solely on hostnames or IP addresses to trust identity rather than asking the user at a particular IP address for identification. As we will see in the upcoming chapters, hostnames and IP addresses can be forged. For users familiar with TCP wrappers and rservices (rsh, rlogin, and so on), it's like putting all your faith in hosts.allow, hosts.deny, and hosts.equiv files to protect your X sessions.
Note Using xhost + will override any and all of the security measures discussed in the next few sections. You should hardly ever run this command without specifying a hostname.
Xauth is not actually an access control program, but rather a front end to the Xauthority file that the X server can use for security. Xauth allows you to add, remove, list, merge, and extract X authorization entries. X authorization entries consist of the X server hostname and display number, an authorization protocol, and secret data. X servers should have their Xauthority entries generated on server startup (xdm does this), and clients wishing to use the X server need to have these authorization entries in their local Xauthority file to gain access to the server. X authorization supports several different protocols. Only two are within the scope of this book:
MIT-MAGIC-COOKIE-1 This is the most popular protocol because it's the easiest to use and doesn't require using xdm (which we'll talk about shortly). The secret is simply a 128-bit key that can be copied from the server's Xauthority file to the client's Xauthority file using xauth. When the server challenges the client, the secret is sent in clear text.
XDM-AUTHORIZATION-1 Similar to the preceding protocol but uses Data Encryption Standard (DES) so that the secret isn't passed in clear text over the network. Here, the secret consists of a 56-bit encryption key and a 64-bit authenticator. When a client connects, the server will challenge it to provide a 192-bit data packet (consisting of date, time, and identification information) that has been encrypted with the shared secret. If the client has the correct encryption key and the server can decrypt and interpret the information, the client is granted access.
Note In this discussion, xauth keys, xauth cookies, and Xauthority entries are synonymous.
The concept is rather simple. After starting up an X server, you'll need to generate an Xauthority entry depending on what type of protocol you're using. If you're using xdm, an entry will be generated automatically. Many systems will automatically generate an entry when you manually start an X server as well. Let's take a look at how to generate an Xauthority entry manually so we can see the actual commands that are used in the process. We'll use MIT-MAGIC-COOKIE-1 as an example.
On the X server box, start up an xterm. Type in the following commands:
xauth: creating new authority file /home/jdoe/.Xauthority
Using authority file /home/jdoe/.Xauthority
xauth> generate myxserver:0 .
authorization id is 41
HOST1:0 MIT-MAGIC-COOKIE-1 121812483b0b3f19367c1541062b472b
Note The period at the end of the generate command is where you would normally specify the authentication protocol you want xauth to use. It uses the MIT-MAGIC-COOKIE-1 protocol when you use only a period. Generating entries for other protocols usually requires extra data that needs to be provided at the end of the command. It generally can't be done by hand and is instead done by an external program or script.
You now have an authorization entry (that shouldn't be readable by anyone else on the system) for your X server. Now let's say you want to run graphical applications from HOST2 on your X server. You'll have to tell HOST2 about the key. You can do this by manually adding to your ~/.Xauthority file on HOST2 and copying and pasting the entry from above.
jdoe@HOST2$ xauth add HOST1:0 MIT-MAGIC-COOKIE-1 \
Or, you can automate the process a bit more. From myxserver, try this:
jdoe@HOST1$ xauth extract - $DISPLAY | ssh HOST2 "xauth merge --"
The xauth extract command retrieves the key for the host named in $DISPLAY and sends it to standard output. We pipe that output through to HOST2 over SSH and feed it to the command xauth merge. This effectively transfers HOST1's xauth key to HOST2's Xauthority file. You can confirm this by running xauth list on HOST2 and examining the HOST1 entry. HOST2 can now freely send X clients to HOST1's X server because HOST1 only accepts clients with the correct xauth key.
Note The previous command assumes that your DISPLAY variable has the fully qualified hostname or address. Keep in mind that DISPLAY variables can refer to other address families than "Inet" addresses. If your DISPLAY variable is set to :0 and you run that command, you might find that the entry in remotebox's Xauthority file refers to myxserver by a name known only to it (a name not in DNS), or worse, by a different address family (like a local Unix domain socket instead of TCP/IP). It's best to specify a complete, unambiguous address when setting the DISPLAY variable (such as 192.168.1.50:0).
Transferring Xauthority entries from server to client is similar no matter what authorization protocol you use. Some of the more advanced protocols include SUN-DES-1, which uses Sun's Secure RPC system, and MIT-KERBEROS-5, which uses secure Kerberos user authentication. These authorization methods are much more secure, but they are also much more complicated to set up initially. See the man pages on xauth, xdm, and Xsecurity for more details.
SECURING X COMMUNICATIONS WITH SECURE SHELL
Now you've got better access control over your X server, but you still have all of your X data passing in the clear over the network. Even though X traffic is very hard to reconstruct (considering graphics and mouse movements among other things), you might want to add encryption to the equation.
The Secure Shell (SSH) protocol allows for the forwarding of TCP connections through an SSH tunnel. If you have an implementation of a secure shell client that supports X11 forwarding, you can encrypt your X client connections back to the X server.
Let's go back to the HOST1 and HOST2 example from earlier. Assume that the X server is on HOST1, and you want to run X client applications on HOST2 and display them on HOST1. First, both SSH implementations on HOST1 and HOST2 need to be built with X11 forwarding support (they are by default). Next, you'll want to make sure that the SSH server on HOST2 has X11 forwarding enabled and that the SSH client on HOST1 has X11 forwarding enabled. You can check this by looking in the ssh_config and sshd_config files in your SSH configuration directories (location varies with installations but it's typically /etc/ssh). Check for lines that say X11Forwarding or ForwardX11 and set them to "yes" if you want this to work.
Note X11 forwarding on SSH servers is usually turned off by default in the sshd_config file. Check this file on the server first when tracking down display problems.
Use the –X option for SSH to explicitly request X11 forwarding:
[HOST1:~] mike% echo $DISPLAY
[HOST1:~] mike% ssh -X HOST2
[mike@HOST2 /]$ echo $DISPLAY
Wait a minute! The display number is 10 and the display host is localhost (which is now HOST2), but you wanted X applications to display on HOST1. SSH automatically sets the DISPLAY variable when you connect using the –X option. The display number 10 on HOST2 is mapped to a local "proxy" X server that tunnels X client traffic through your current SSH connection to the X server on HOST1. Run an application like xclock on HOST2 and you should see a clock pop up on your screen on HOST1. There's also the added benefit that your interaction with xclock is encrypted because it's passing over the SSH connection. Encryption is not terribly necessary for an application like xclock, but it might be more crucial if you were running a remote xemacs application.
Tip It's important that you remember not to use the –display option with any X commands you run through the SSH tunnel; otherwise, the X clients will not gain the benefit of encryption.
The SSH X11 forwarding even takes care of X authentication. In addition to setting up your display for its "proxy" X server automatically, the SSH client sets up "junk" xauth cookies and sends them to the SSH server. The server, in turn, puts the xauth cookies in your Xauthority file on the remote system, automatically giving you access to your X server. In other words, if you started the X server on HOST1, the SSH client would tell the "proxy" X server on HOST2 to create the following Xauthority entry:
HOST2:10 MIT-MAGIC-COOKIE-1 121812483b0b3f19367c1541062b472b
One nice thing about this behavior is that it keeps any real xauth cookies from ever being sent over the network. Only the junk cookie is passed back and forth (and it's even encrypted). Connections that go back through the proxy will map the junk xauth cookie for HOST2:10 to a real xauth cookie for HOST1:0. This mapping takes place on the SSH client side. This allows only the authorized user who started the X server and SSH client on HOST1 to forward X clients back to the X server through the SSH tunnel.
Confused? This can get pretty complicated—so here's a diagram that shows what's going on.
THE OTHER IMPORTANT PLAYERS
We've covered most of the underlying basics with X connections and keeping those connections relatively secure. Now let's briefly review some of the other important players in the workings of the X Window System.
Xdm is the X Display Manager. It can manage a number of different X displays on the localhost or other remote X servers. Unix systems that automatically boot up into X are usually running xdm to handle starting X servers and sessions. It asks you for a username and password, and in turn, it provides you with a session—just as a terminal login might do. It handles much of the previously mentioned X authentication details of generating Xauthority entries transparently as you log in.
Xdm uses X Display Manager Control Protocol (XDMCP), which runs on UDP port 177. It listens for queries from X servers that are looking for a display manager. This can allow remote X servers (specifically X terminals that have X server software and nothing more) to query for hosts running xdm that can manage X sessions for them. This basically means that a box running xdm is telling other X servers, "Hey, you can start an X login session on me and use all of my X clients and software and display them back to yourself." It's kind of like using telnet to log into a box, except with graphics.
Running XDMCP on your network is inherently insecure and isn't suggested unless you're on a trusted LAN. If you like the ability of having an X login to your local server, it's still okay to use xdm. Just make sure you're not listening for XDMCP queries and offering up your xdm services for other X servers unless you intend to do so. See the xdm man pages for more details on configuring xdm securely.
Note Since XDMCP uses UDP, XDMCP traffic cannot be tunneled through SSH.
Xinit and Startx
Xinit initializes the X Window System and starts the initial clients. The behavior of this program is extremely configurable and is usually run from a front-end script called startx. By default, xinit brings up the windowing system (with the basic functionality mentioned at the beginning of this chapter) and runs the programs listed in the user's ~/.xinitrc file. Failing that, it simply runs xterm.
Xinit can be configured so that it runs your favorite window manager (KDE, Gnome, and so on) by default. Xinit also lets you configure things like window geometry, screen colors, and more.
Startx is a front end to xinit that hides some of the more gruesome details in starting up and shutting down an X Window session. It handles searching through all the different server and client configuration files (xinitrc and xserverrc) in all the usual locations and constructs the xinit command line for you.
Whereas xdm is an automatic way to start up and manage X sessions at system boot, xinit and startx are manual ways of starting up X sessions on demand.
Xserver is the actual program started by xdm when someone logs in or by xinit when someone issues the startx command. Xserver receives its configuration options as arguments from the program that starts it. Other than managing the actual X communication, the Xserver itself handles the network connections, authentication, screen management, font management, XDMCP queries, and many other things. See the Xserver man pages for more details.
Using X on Windows and Mac OS X
Microsoft Windows systems do not support the X Window System without third-party software. The easiest way to obtain X compatibility is to use Cygwin, which is covered in Chapter 3.
Mac OS X supports the X Window System (OS X refers to its version, 10, not an X server). You will need the X11.app from the installation CD or from Apple's web site. Running an X server on OS X is much like any other Unix-based system. Applications won't be as tightly integrated with the core OS X interface so command-key shortcuts likely won't work. X11 forwarding over SSH is possible and many of the graphical tools described in this book, like Ethereal in Chapter 16, run without problem under Mac OS X's system.
You have all of the normal X commands like xhost and xauth under Mac OS X; however, the system terminal will not have the correct path to these commands in its default PATH environment variable. By default, the X11.app launches an xterm with the correct path settings so all you need to do is type xhost or xauth to access these commands. Otherwise, add /usr/X11R6/bin to your path:
[Paris:~] mike% set path=($path /usr/X11R6/bin)
NOW YOU KNOW…
This chapter has laid out the basics of the X Window System architecture and has given you an idea of some of the potential security risks you take when running X-based applications. The power to run graphical applications remotely comes at a price.
There are several X-related utilities available that can exploit some of these security risks. We mentioned xkey, which lets you monitor the keystrokes on an X server to which you have access (either legitimately or from a lack of authorization and access control). Another program, xwatchwin, will let you view the actual contents of the X server's window, again assuming you have access. You can use a program called xscan to search networks for X servers that would be vulnerable to these kinds of attacks. All of these utilities are available for download at http://www.packetstormsecurity.nl/.
Have we scared you away from running X yet? Don't be. You just need to remember three basic points when you're running an X server to keep it as secure as possible:
Avoid xhost access control if possible. It's the least secure option you have. Use xauth variations instead.
Run all your remote X applications back to your X server through an SSH tunnel.
Turn off XDMCP unless you're positive your network is private and trusted.