Purchase | Copyright © 2002 Paul Sheer. Click here for copying permissions. | Home |
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.
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.
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.
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.)
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.)
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.)
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.)
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.)
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.
This concept is discussed in Section 11.3.
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.
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.
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.
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.
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.
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 |
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.
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.
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 [email protected]. 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).
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.
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.
|
chattr -R +i /bin /boot /lib /sbin /usr |
|
find / -mtime 2 -o -ctime 2 |
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.
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.
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.
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.
If your answer to any of these questions is fewer than 5, you are not being conscientious about security.
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. |