Purchase  Copyright © 2002 Paul Sheer. Click here for copying permissions.  Home 

next up previous contents
Next: A. Lecture Schedule Up: rute Previous: 43. The X Window   Contents

Subsections

44. UNIX Security

This is probably the most important chapter of this book.(footnote follows) [Thanks to Ryan Rubin for reviewing this chapter.]

LINUX has been touted as both the most secure and insecure of all operating systems. The truth is both. Take no heed of advice from the LINUX community, and your server will be hacked eventually. Follow a few simple precautions, and it will be safe for years without much maintenance.

The attitude of most novice administrators is ``Since the UNIX system is so large and complex and since there are so many millions of them on the Internet, it is unlikely that my machine will get hacked.'' Of course, it won't necessarily be a person targeting your organization that is the problem. It could be a person who has written an automatic scanner that tries to hack every computer in your city. It could also be a person who is not an expert in hacking at all, but who has merely downloaded a small utility to do it for him. Many seasoned experts write such utilities for public distribution, while so-called script kiddies (because the means to execute a script is all the expertise needed) use these to do real damage. [The word hack means gaining unauthorized access to a computer. However, programmers sometimes use the term to refer to enthusiastic work of any kind. Here we refer to the malicious definition.]

In this chapter you will get an idea of the kinds of ways a UNIX system gets hacked. Then you will know what to be wary of, and how you can minimize risk.

44.1 Common Attacks

I personally divide attacks into two types: attacks that can be attempted by a user on the system, and network attacks that come from outside of a system. If a server is, say, only used for mail and web, shell logins may not be allowed at all; hence, the former type of security breach is of less concern. Here are some of the ways security is compromised, just to give an idea of what UNIX security is about. In some cases, I indicate when it is of more concern to multiuser systems.

Note also that attacks from users become an issue when a remote attack succeeds and a hacker gains user privileges to your system (even as a nobody user). This is an issue even if you do not host logins.

44.1.1 Buffer overflow attacks

Consider the following C program. If you don't understand C that well, it doesn't matter--it's the concept that is important. (Before trying this example, you should unplug your computer from the network.)

 
 
 
 
5 
 
 
 
 
10 
 
 
 
 
15 
 
#include <stdio.h>
 
void do_echo (void)
{
    char buf[256];
    gets (buf);
    printf ("%s", buf);
    fflush (stdout);
}
 
int main (int argc, char **argv)
{
    for (;;) {
        do_echo ();
    }
}

You can compile this program with gcc -o /usr/local/sbin/myechod myechod.c. Then, make a system service out of it as follows: For xinetd, create file /etc/xinetd.d/myechod containing:

 
 
 
 
5 
 
 
 
 
service myechod
{
        flags           = REUSE
        socket_type     = stream        
        wait            = no
        user            = root
        server          = /usr/local/sbin/myechod
        log_on_failure  += USERID
}

while for inetd add the following line to your /etc/inetd.conf file:

 
myechod stream  tcp     nowait  root    /usr/local/sbin/myechod

Of course, the service myechod does not exist. Add the following line to your /etc/services file:

 
myechod         400/tcp         # Temporary demo service

and then restart xinetd (or inetd) as usual.

You can now run netstat -na. You should see a line like this somewhere in the output:

 
tcp      0      0 0.0.0.0:400        0.0.0.0:*        LISTEN

You can now run telnet localhost 400 and type away happily. As you can see, the myechod service simply prints lines back to you.

Someone reading the code will realize that typing more than 256 characters will write into uncharted memory of the program. How can they use this effect to cause the program to behave outside of its design? The answer is simple. Should they be able to write processor instructions into an area of memory that may get executed later, they can cause the program to do anything at all. The process runs with root privileges, so a few instructions sent to the kernel could, for example, cause the passwd file to be truncated, or the file system superblock to be erased. A particular technique that works on a particular program is known as an exploit for a vulnerability. In general, an attack of this type is known as a buffer overflow attack.

To prevent against such attacks is easy when you are writing new programs. Simply make sure that any incoming data is treated as being dangerous. In the above case, the fgets function should preferably be used, since it limits the number of characters that could be written to the buffer. There are, however, many functions that behave in such a dangerous way: even the strcpy function writes up to a null character that may not be present; sprintf writes a format string that could be longer than the buffer. getwd is another function that also does no bound checking.

However, when programs grow long and complicated, it becomes difficult to analyze where there may be loopholes that could be exploited indirectly. A program is a legal contract with an impartial jury.

44.1.2 Setuid programs

A program like su must be setuid (see Chapter 14). Such a program has to run with root privileges in order to switch UIDs to another user. The onus is, however, on su to refuse privileges to anyone who isn't trusted. Hence, su requests a password and checks it against the passwd file before doing anything.

Once again, the logic of the program has to hold up to ensure security, as well as to provide insurance against buffer overflow attacks. Should su have a flaw in the authentication logic, it would enable someone to change to a UID that they were not privileged to hold.

Setuid programs should hence be considered with the utmost suspicion. Most setuid programs try be small and simple, to make it easy to verify the security of their logic. A vulnerability is more likely to be found in any setuid program that is large and complex.

(Of slightly more concern in systems hosting many untrusted user logins.)

44.1.3 Network client programs

Consider when your FTP client connects to a remote untrusted site. If the site server returns a response that the FTP client cannot handle (say, a response that is too long--a buffer overflow), it could allow malicious code to be executed by the FTP client on behalf of the server.

Hence, it is quite possible to exploit a security hole in a client program by just waiting for that program to connect to your site.

(Mostly a concern in systems that host user logins.)

44.1.4 /tmp file vulnerability

If a program creates a temporary file in your /tmp/ directory and it is possible to predict the name of the file it is going to create, then it may be possible to create that file in advance or quickly modify it without the program's knowledge. Programs that create temporary files in a predictable fashion or those that do not set correct permissions (with exclusive access) to temporary files are liable to be exploited. For instance, if a program running as superuser truncates a file /tmp/9260517.TMP and it was possible to predict that file name in advance, then a hacker could create a symlink to /etc/passwd of the same name, resulting in the superuser program actually truncating the passwd file.

(Of slightly more concern in systems that host many untrusted user logins.)

44.1.5 Permission problems

It is easy to see that a directory with permissions 660 and ownerships root:admin cannot be accessed by user jsmith if he is outside of the admin group. Not so easy to see is when you have thousands of directories and hundreds of users and groups. Who can access what, when, and why becomes complicated and often requires scripts to be written to do permission tests and sets. Even a badly set /dev/tty* device can cause a user's terminal connection to become vulnerable.

(Of slightly more a concern in systems that host many untrusted user logins.)

44.1.6 Environment variables

There are lots of ways of creating and reading environment variables to either exploit a vulnerability or obtain some information that will compromise security. Environment variables should never hold secret information like passwords.

On the other hand, when handling environment variables, programs should consider the data they contain to be potentially malicious and do proper bounds checking and verification of their contents.

(Of more concern in systems that host many untrusted user logins.)

44.1.7 Password sniffing

When telnet, ftp, rlogin, or in fact any program at all that authenticates over the network without encryption is used, the password is transmitted over the network in plain text, that is, human-readable form. These programs are all common network utilities that old UNIX hands were accustomed to using. The sad fact is that what is being transmitted can easily be read off the wire with the most elementary tools (see tcpdump on page [*]). None of these services should be exposed to the Internet. Use within a local LAN is safe, provided the LAN is firewalled, and your local users are trusted.

44.1.8 Password cracking

This concept is discussed in Section 11.3.

44.1.9 Denial of service attacks

A denial of service (DoS) attack is one which does not compromise the system but prevents other users from using a service legitimately. It can involve repetitively loading a service to the point that no one else can use it. In each particular case, logs or TCP traffic dumps might reveal the point of origin. You might then be able to deny access with a firewall rule. There are many types of DoS attacks that can be difficult or impossible to protect against.

44.2 Other Types of Attack

The preceding lists are far from exhaustive. It never ceases to amaze me how new loopholes are discovered in program logic. Not all of these exploits can be classified; indeed, it is precisely because new and innovative ways of hacking systems are always being found, that security needs constant attention.

44.3 Counter Measures

Security first involves removing known risks, then removing potential risks, then (possibly) making life difficult for a hacker, then using custom UNIX security paradigms, and finally being proactively cunning in thwarting hack attempts.

44.3.1 Removing known risks: outdated packages

It is especially sad to see naive administrators install packages that are well known to be vulnerable and for which ``script kiddy'' exploits are readily available on the Internet.

If a security hole is discovered, the package will usually be updated by the distribution vendor or the author. The bugtraq <http://www.securityfocus.com/forums/bugtraq/intro.html> mailing list announces the latest exploits and has many thousands of subscribers worldwide. You should get on this mailing list to be aware of new discoveries. The Linux Weekly News <http://lwn.net/> is a possible source for security announcements if you only want to read once a week. You can then download and install the binary or source distribution provided for that package. Watching security announcements is critical. [I often ask ``administrators'' if they have upgraded the xxx service and get the response, that either they are not sure if they need it, do not believe it is vulnerable, do not know if it is running, where to get a current package, or even how to perform the upgrade; as if their ignorance absolves them of their responsibility. If the janitor were to duct-tape your safe keys to a window pane, would you fire him?]

This goes equally for new systems that you install: never install outdated packages. Some vendors ship updates to their older distributions. This means that you can install from an old distribution and then upgrade all your packages from an ``update'' package list. Your packages would be then as secure as the packages of the distribution that has the highest version number. For instance, you can install RedHat 6.2 from a 6-month-old CD, then download a list of RedHat 6.2 ``update'' packages. Alternatively, you can install the latest RedHat version 7.? which has a completely different set of packages. On the other hand, some other vendors may ``no longer support'' an older distribution, meaning that those packages will never be updated. In this case, you should be sure to install or upgrade with the vendor's most current distribution or manually recompile vulnerable packages by yourself.

Over and above this, remember that vendors are sometimes slow to respond to security alerts. Hence, trust the free software community's alerts over anything vendors may fail to tell you.

Alternatively, if you discover that a service is insecure, you may just want to disable it (or better still, uninstall it) if it's not really needed.

44.3.2 Removing known risks: compromised packages

Packages that are modified by a hacker can allow him a back door into your system: so called Trojans. Use the package verification commands discussed in Section 24.2.6 to check package integrity.

44.3.3 Removing known risks: permissions

It is easy to locate world-writable files. There should be only a few in the /dev and /tmp directories:

 
find / -perm -2 ! -type l -ls

Files without any owner are an indication of mismanagement or compromise of your system. Use the find command with

 
find / -nouser -o -nogroup -ls

44.3.4 Password management

It is obvious that variety in user passwords is more secure. It is a good idea to rather not let novice users choose their own passwords. Create a randomizing program to generate completely arbitrary 8 character passwords for them. You should also use the pwconv utility from the shadow-utils package to create the shadow password files (explained in Section 11.3). See pwconv(8) for information.

44.3.5 Disabling inherently insecure services

Services that are inherently insecure are those that allow the password to be sniffed over the Internet or provide no proper authentication to begin with. Any service that does not encrypt traffic should not be used for authentication over the Internet. These are ftp, telnet, rlogin, uucp, imap, pop3, and any service that does not use encryption and yet authenticates with a password.

Instead, you should use ssh and scp. There are secure versions of POP and IMAP (SPOP3 and SIMAP), but you may not be able to find good client programs. If you really have to use a service, you should limit the networks that are allowed to connect to it, as described on page [*] and [*].

Old UNIX hands are notorious for exporting NFS shares ( /etc/exports) that are readable (and writable) from the Internet. The group of functions to do Sun Microsystems' port mapping and NFS--the nfs-utils ( rpc....) and portmap packages--don't give me a warm, fuzzy feeling. Don't use these on machines exposed to the Internet.

44.3.6 Removing potential risks: network

Install libsafe. This is a library that wraps all those vulnerable C functions discussed above, thus testing for a buffer overflow attempt with each call. It is trivial to install, and sends email to the administrator upon hack attempts. Go to http://www.avayalabs.com/project/libsafe/index.html for more information, or send email to libsafe@research.avayalabs.com. The libsafe library effectively solves 90% of the buffer overflow problem. There is a very slight performance penalty, however.

Disable all services that you are not using. Then, try to evaluate whether the remaining services are really needed. For instance, do you really need IMAP or would POP3 suffice? IMAP has had a lot more security alerts than POP3 because it is a much more complex service. Is the risk worth it?

xinetd (or inetd) runs numerous services, of which only a few are needed. You should trim your /etc/xinetd.d directory (or /etc/inetd.conf file) to a minimum. For xinetd, you can add the line disable = yes to the relevant file. Only one or two files should be enabled. Alternatively, your /etc/inetd.conf should have only a few lines in it. A real-life example is:

 
 
 
ftp     stream  tcp     nowait  root    /usr/sbin/tcpd  in.ftpd -l -a
pop-3   stream  tcp     nowait  root    /usr/sbin/tcpd  ipop3d
imap    stream  tcp     nowait  root    /usr/sbin/tcpd  imapd

This advice should be taken quite literally. The rule of thumb is that if you don't know what a service does, you should disable it. See also Section 29.6.

In the above real-life case, the services were additionally limited to permit only certain networks to connect (see page [*] and [*]).

xinetd (or inetd) is not the only problem. There are many other problematic services. Entering netstat -nlp gives initial output, like

 
 
 
 
5 
 
 
 
 
10 
 
 
 
 
15 
 
 
(Not all processes could be identified, non-owned process info
 will not be shown, you would have to be root to see it all.)
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address     Foreign Address   State    PID/Program name
tcp        0      0 0.0.0.0:25        0.0.0.0:*         LISTEN   2043/exim
tcp        0      0 0.0.0.0:400       0.0.0.0:*         LISTEN   32582/xinetd
tcp        0      0 0.0.0.0:21        0.0.0.0:*         LISTEN   32582/xinetd
tcp        0      0 172.23.80.52:53   0.0.0.0:*         LISTEN   30604/named
tcp        0      0 127.0.0.1:53      0.0.0.0:*         LISTEN   30604/named
tcp        0      0 0.0.0.0:6000      0.0.0.0:*         LISTEN   583/X
tcp        0      0 0.0.0.0:515       0.0.0.0:*         LISTEN   446/
tcp        0      0 0.0.0.0:22        0.0.0.0:*         LISTEN   424/sshd
udp        0      0 0.0.0.0:1045      0.0.0.0:*                  30604/named
udp        0      0 172.23.80.52:53   0.0.0.0:*                  30604/named
udp        0      0 127.0.0.1:53      0.0.0.0:*                  30604/named
raw        0      0 0.0.0.0:1         0.0.0.0:*         7        -
raw        0      0 0.0.0.0:6         0.0.0.0:*         7        -

but doesn't show that PID 446 is actually lpd. For that information just type ls -al /proc/446/.

You can see that ten services are actually open: 1, 6, 21, 22, 25, 53, 400, 515, 1045, and 6000. 1 and 6 are kernel ports, and 21 and 400 are FTP and our echo daemon, respectively. Such a large number of open ports provides ample opportunity for attack.

At this point, you should go through each of these services and (1), decide whether you really need them. Then (2), make sure you have the latest version; finally (3), consult the packages documentation so that you can limit the networks that are allowed to connect to those services.

It is interesting that people are wont to make assumptions about packages to the tune of ``This service is so popular it can't possibly be vulnerable.'' The exact opposite is, in fact, true: The more obscure and esoteric a service is, the less likely that someone has taken the trouble to find a vulnerability. In the case of named (i.e., bind), a number of most serious vulnerabilities were made public as regards every Bind release prior to 9. Hence, upgrading to the latest version (9.1 at the time of writing) from source was prudent for all the machines I administered (a most-time consuming process).

44.3.7 Removing potential risks: setuid programs

It is easy to find all the setuid programs on your system:

 
find / -type f -perm +6000 -ls

Disabling them is just as easy:

 
chmod -s /bin/ping

There is nothing wrong with the decision that ordinary users are not allowed to use even the ping command. If you do allow any shell logins on your system, then you should remove setuid permissions from all shell commands.

44.3.8 Making life difficult

There is much that you can do that is not ``security'' per se but that will make life considerably more difficult for a hacker, and certainly impossible for a stock standard attack, even if your system is vulnerable. A hack attempt often relies on a system being configured a certain way. Making your system different from the standard can go a long way.

Read-only partitions:
It is allowable to mount your /usr partition (and critical top-level directories like /bin) read-only since these are, by definition, static data. Of course, anyone with root access can remount it as writable, but a generic attack script may not know this. Some SCSI disks can be configured as read-only by using dip switches (or so I hear). The /usr partition can be made from an ISO 9660 partition (CD-ROM file system) which is read-only by design. You can also mount your CD-ROM as a /usr partition: access will be slow, but completely unmodifiable. Finally, you can manually modify your kernel code to fail write-mount attempts on /usr.
Read-only attributes:
LINUX has additional file attributes to make a file unmodifiable over and above the usual permissions. These attributes are controlled by the commands chattr and lsattr. You can make a log file append-only with chatter +a /var/log/messages /var/log/syslog or make files immutable with, chatter +i /bin/login: both actions are a good idea. The command

 
chattr -R +i /bin /boot /lib /sbin /usr

is a better idea still. Of course, anyone with superuser privileges can switch them back.
Periodic system monitoring:
It is useful to write your own crond scripts to check whether files have changed. the scripts can check for new setuid programs, permissions, or changes to binary files; or you can reset permissions to what you think is secure. Just remember that cron programs can be modified by anyone who hacks into the system. A simple command

 
find / -mtime 2 -o -ctime 2

searches for all files that have been modified in the last two days.
Nonstandard packages:
If you notice many security alerts for a package, switch to a different one. There are alternatives to bind, wu-ftpd, sendmail (as covered in Chapter 30), and almost every service you can think of. You can also try installing an uncommon or security-specialized distribution. Switching entirely to FreeBSD is also one way of reducing your risk considerably. [This is not a joke.]
Nonstandard messages:
Many services provide banners and informational messages which give away the version of your software. For example, mail servers have default HELO responses to advertise themselves; and login and FTP banners often display the operating system you are running. These messages should be customized to provide less information on which to base an attack. You can begin by editing /etc/motd.
Minimal kernels:
Its easy to compile your kernel without module support, with an absolutely minimal set of features. Loading of Trojan modules has been a source of insecurity in the past. Such a kernel can only make you safer.
Non-Intel architecture:
Hackers need to learn assembly language to exploit many vulnerabilities. The most common assembly language is that of Intel 80?86 processors. Using a non-Intel platform adds that extra bit of obscurity.
Removing fingerprints:
Your system identifies itself to
OpenWall project:
This has a kernel patch that makes the stack of a process non-executable (which will thwart most kinds of buffer overflow attempts) and does some other cute things with the /tmp directory and process I/O.

44.3.9 Custom security paradigms

Hackers have limited resources. Take oneupmanship away and security is about the cost of hacking a system versus the reward of success. If you feel the machine you administer is bordering on this category then you need to start billing far more for your hours and doing things like those described below. It is possible to go to lengths that will make a LINUX system secure against a large government's defense budget.

Capabilities:
This is a system of security that gives limited kinds of superuser access to programs that would normally need to be full-blown setuid root executables. Think: Most processes that run with root (setuid) privileges do so because of the need to access only a single privileged function. For instance, the ping program does not need complete superuser privileges (run ls -l /bin/ping and note the setuid bit). Capabilities are a fine-grained set of privileges that say that a process can do particular things that an ordinary user can't, without ever having full root access. In the case of ping, its capability would be certain networking access that only root is normally allowed to do.
Access control lists:
These lists extend the simple ``user/group/other'' permissions of UNIX files to allow arbitrary lists of users to access particular files. This really does nothing for network security but is useful if you have many users on the system and you would like to restrict them in odd ways. (ACL is a little out of place in this list.)
DTE:
Domain and Type Enforcement works like this: When a program is executed, it is categorized and only allowed to do certain things even if it is running as root. These limitations are extended to child processes that it may execute. This is real security; there are kernel patches to do this. The National Security Agency (of the U.S.) (NSA) actually has a LINUX distribution built around DTE.
medusa:
This is a security system that causes the kernel to query a user daemon before letting any process on the system do anything. It is the most ubiquitous security system out because it is entirely configurable--you can make the user daemon restrict anything however you like.
VXE:
Virtual eXecuting Environment dictates that a program executes in its own protected space while VXE executes a Lisp program to check whether a system call is allowed. This is effectively a lot like medusa.
MAC:
Mandatory Access Controls. This is also about virtual environments for processes. MAC is a POSIX standard.
RSBAC and RBAC:
Rule-Set-Based Access Controls and Role-Based Access Controls. These look like a combination of some of the above.
LIDS:
Linux Intrusion Detection System does some meager preventive measures to restrict module loading, file modifications, and process information.

Kernel patches exist to do all of the above. Many of these projects are well out of the test phase but are not in the mainstream kernel, possibly because developers are not sure of the most enduring approach to UNIX security. They all have one thing in common: double-checking what a privileged process does, which can only be a good thing.

44.3.10 Proactive cunning

Proactive cunning means attack monitoring and reaction, and intrusion monitoring and reaction. Utilities that do this come under a general class called network intrusion detection software. The idea that one might detect and react to a hacker has an emotional appeal, but it automatically implies that your system is insecure to begin with--which is probably true, considering the rate at which new vulnerabilities are being reported. I am weary of so-called intrusion detection systems that administrators implement even before the most elementary of security measures. Really, one must implement all of the above security measures before thinking about intrusion monitoring.

To picture the most basic form of monitoring, consider this: To hack a system, one usually needs to test for open services. To do this, one tries to connect to every port on the system to see which are open. This is known as a port scan. There are simple tools to detect a port scan, which will then start a firewall rule that will deny further access from the offending host although this can work against you if the hacker has spoofed your own IP address. More importantly, the tools will report the IP address from which the attack arose. A reverse lookup will give the domain name, and then a whois query on the appropriate authoritative DNS registration site will reveal the physical address and telephone number of the domain owner.

Port scan monitoring is the most elementary form of monitoring and reaction. From there up, you can find innumerable bizarre tools to try and read into all sorts of network and process activity. I leave this to your own research, although you might want to start with the Snort traffic scanner <http://www.snort.org/>, the Tripwire intrusion detection system <http://www.tripwiresecurity.com/>, and IDSA <http://jade.cs.uct.ac.za/idsa/>.

A point to such monitoring is also as a deterrent to hackers. A network should be able to find the origins of an attack and thereby trace the attacker. The threat of discovery makes hacking a far less attractive pastime, and you should look into the legal recourse you may have against people who try to compromise your system.

44.4 Important Reading

The preceding is a practical guide. It gets much more interesting than this. A place to start is the comp.os.linux.security FAQ. This FAQ gives the most important UNIX security references available on the net. You can download it from http://www.memeticcandiru.com/colsfaq.html, http://www.linuxsecurity.com/docs/colsfaq.html or http://www.geocities.com/swan_daniel/colsfaq.html. The Linux Security <http://www.linuxsecurity.com/> web page also has a security quick reference card that summarizes most everything you need to know in two pages.

44.5 Security Quick-Quiz

If your answer to any of these questions is fewer than 5, you are not being conscientious about security.

44.6 Security Auditing

This chapter is mostly concerned with securing your own LINUX server. However, if you have a large network, security auditing is a more extensive evaluation of your systems' vulnerabilities. Security auditing becomes an involved procedure when multiple administrators maintain many different platforms across a network. There are companies that specialize in this work: Any network that does not dedicate an enlightened staff member should budget generously for their services.

Auditing your network might involve the following:

Network attacks cost companies billions of dollars each year in service downtime and repair. Failing to pay attention to security is a false economy.


next up previous contents
Next: A. Lecture Schedule Up: rute Previous: 43. The X Window   Contents