Quick and Easy Linux Hacking and How to Avoid It
Unlike Chapter 2, "Quick Fixes for Common Problems," which is concerned with configuration errors and old insecure versions of software that can be fixed quickly, this chapter talks about specific techniques of crackers that do not depend on configuration errors or inherently insecure software. The techniques discussed here are frequently starting points for a cracker breaking into your system, and your understanding of them and protection against them is critical to system security.
The topics covered in this chapter include:
"X Marks the Hole"
Law of the JunglePhysical Security"
"Physical Actions"
"Selected Short Subjects"
"Terminal Device Attacks"
"Disk Sniffing"
3.1 X Marks the Hole
DANGER LEVEL
X security is one of those things that many people ignore, and hope does not come back to infect them. On the systems that use it, which is most systems, the X subsystem has access to every keystroke of every user and screen output and X runs set-UID to root. A rogue X process can connect to a user's X display and capture keystrokes while that user is entering her password. Without adequate X security this is very hard to guard against.
For some of the highest security situations, it might be appropriate to not use X and to remove it from the system. However, most people cannot live without X, so let us examine how to make X more secure. As most SysAdmins know, the lowest level of X security is via host name validation. You enable a particular remote host to connect to your X display by requesting that xhost add it to the list of approved hosts. To add pentacorp.com the following command would be issued by any user that presently has access to the X server:
xhost +pentacorp.com
Security involving host names and IP addresses, such as this level of X security, can be broken easily by a variety of well-known methods; these are discussed in "The rsh, rcp, rexec, and rlogin Services" on page 198 as these insecure services share this method of authentication.
To list the present access, issue the xhost command without arguments:
xhost
To turn off specified access change the "+" to a "-".
Many users get lazy, so instead of issuing an xhost command for each of several systems, they enable all systems in the world access via
xhost +
This lets any cracker on the Internet scan for systems having port 6000 accessible and take over that user's access. If this happens to root, the cracker "owns" that system. This is a really good reason for you to have your firewall block all X access via the following. The example assumes that you have the Class A local network 10.0.0.0, that you want to allow unrestricted access for. If you want more security, you can limit access to the local machine.
ipchains -A input -p tcp -j ACCEPT -s 10.0.0.0/8 -d 0.0.0.0/0 6000:60631 ipchains -A input -p tcp -j DENY -s 0.0.0.0/0 -d 0.0.0.0/0 6000:6063
An excellent and generally accepted solution is to run X sessions over SSH. It is important to read "Wrapping SSH Around X" on page 417 in Part II carefully, as there are some gotchas2 if this is not done correctly that will result in unprotected X sessions.
The most important gotcha is if a user accidentally sets her $DISPLAY environment variable, usually in a shell startup file. This would bypass SSH's encryption and establish an unsecured X session over a 6000 series port. SSH will set it to the local machine but with a session greater than 0, and sshd will be serving that session and route it over its encrypted channel. The following is typical. Note that the host name is that of the server system, rather than that of the client system that the user is seated at.
$ echo $DISPLAY pentacorp.com:10.0
Note that a $DISPLAY value of, say,
pentacorp.com:10.0
on a system means nothing more than "connect to TCP port 10+6000, or 6010, on pentacorp.com." This is illustrated in Figure 3.1, where Joe, the SysAdmin, is on his home system. Its host name is corbomite.homesys.com. He has used SSH to connect into the Pentacorp system pentacorp.com.
Figure 3.1 SSH-wrapped X session.
As you can see in Figure 3.1, all data traveling over the network is encrypted. The unencrypted data within a properly configured system may be sniffed only by root. Because SSH-wrapped X sessions will operate between the two systems over the SSH channel operating on TCP port 22, there is no need to allow ports starting at 6000 access from other systems. Thus, it is recommended that IP Chains block X's ports that start with TCP port 6000.
IP Chains has the added advantage of preventing those gotchas from happening. If a user makes a mistake that would allow unprotected X sessions, the IP Chains blocking of the 6000 series ports will prevent the unprotected X session from happening.
The ports program (discussed in "Turn Off Unneeded Services" on page 86) or netstat may be used to see what ports are active. A good test is to start up a simple X application such as xclock and see whether port 6000 develops an active connection. If so, there is an error in configuration. Instead, you should see port 6010 in use by sshd (for the first session).
For those that do not want to use SSH-wrapped X (and that is going against advice) the following man pages cover X security. They are not particularly clear and that increases the chance of making a mistake resulting in less security.
Xsecurity xauth xdm xhost
One possibility might be to allow finer-grained control over which users on a remote system may access the X session of a particular local user.
X does offer the Secure Keyboard option while typing confidential data. This option prevents keystrokes from being intercepted by malevolent X programs that ordinarily can intercept keystrokes from any X server that grants them access.
Another solution for most "desktop" Linux systems is simply to disable X from listing on TCP port 6000 at all. To do this, supply the argument -nolisten tcp to X. An easy way to do this is to add the following line to $HOME/.xserverrc:
X -nolisten tcp :0
You will want to use ports or netstat to verify that this causes TCP port 6000 not to be opened any more. This will prevent any other systems from displaying X-generated images on your system or reading your keyboard but will not prevent local processes from using X via the X unix socket.
But wait! There's more. The X server has a nasty DoS that can be generated remotely.3 A malformed packet can cause the X server to run a busy loop for two billion iterations due to this packet being able to specify a count of 1 (when a legitimate packet specifies a small positive number), that then is decremented repeatedly until 0 is reached.
The following buggy code in the AuthCheckSitePolicy() function of Xserver/os/secauth.c is the culprit.
// dataP is user supplied data from the network char *policy = *dataP; int nPolicies; ... // Oh dear, we can set nPolicies to -1 nPolicies = *policy++; while (nPolicies) { // Do some stuff in a loop ... nPolicies--; }
To fix this code, change
while (nPolicies) { to while (nPolicies > 0) {
This illustrates an important programming technique that should be common but is not. Specifically, this technique applies when testing for boundary conditions, such as when to end a loop or follow an if statement. Instead of testing for an exact match, such as the buggy code's test for nPolicies exactly matching 0, test for meeting or exceeding the boundary condition. Thus, if a bug causes the value to skip past the boundary, the condition will be detected. Over 25 years of C programming, following this technique has prevented a number of small bugs in the author's code from being big bugs.
Although the code could be fixed as discussed above, recompiling X is painful. An alternative is to use any of the techniques discussed earlier to prevent the wrong kind of machines from getting close to X. This problem is known to affect XFree86 versions 3.3.5, 3.3.6, and 4.0. It causes X to lock up for roughly a few minutes, depending on processor speed. On 4.0 you can wiggle the mouse but X still is frozen until the loop completes or X is killed.