- Introduction
The purpose of this paper is to describe necessary measures that should be taken in order to secure a default Linux installation. Most default installations of Linux are grossly insecure. This paper focuses on methods that can be used not only to secure a machine with a high degree of confidence, but still allow your users to be able to accomplish their work.
This paper does not cover procedures for securing a machine that is already on a network. As a rule, no machine should be placed on any network prior to its having been secured against local and remote attack. If a machine has already been compromised, none of the following procedures will improve the system's security. In most cases, depending on the skill of the intruder, the machine will likely already be trojaned or backdoored. Applying the following security procedures on such a machine would only provide a false sense of security.
As a firm adherent to the philosophy of proactive security, the author does not recommend any attempt to "back-track" and attempt to secure machines that are already in place. It is best to freshly re-install and secure these machines from scratch. After all, it only takes one compromised machine to shatter the security posture of one's entire network.
Because of the amount of material being covered, this paper will be divided into two parts:
- Part I will deal with securing the system with the tools Linux provides. One exception to this rule is the inclusion of Secure Shell or SSH.
- Part II will cover additional software the sysadmin can install, such as log analyzers, port monitors, and kernel modifications. Some of the built-in firewalling capabilities of Linux will also be examined in Part II.
Before undertaking the task of securing a machine, it is a advisable to determine the purpose that machine will serve. Will the system serve only as a web server, a mail server, or a combination of other services? The server's purpose should be planned well in advance, so the admin can best determine the approach to properly secure the machine. As cheap as computing power is these days, there is little justification for a single machine that is publicly exposed to the Internet to serve multiple functions. As a rule, a web server should provide only web services and should not provide FTP or SMTP services. By limiting the services a machine provides, the sysadmin can significantly limit the risk of the machine being compromised.
Another thing for the admin to consider is the type of intruder they are trying to secure this machine against. While most admins prepare against attacks from outside, very few take any form of precaution against intruders from within their organization. This is known as a "hard crunchy shell with a soft chewy inside" security model. Such an approach is ill-advised, given recent statistics which indicate that 60 to 75 percent of computer intrusions are actually committed by insiders.
With the above in mind, this document will place special emphasis on securing the machine in such a way that it can readily repel both remote and local attacks.
- Prerequisites
It is assumed that the reader already has a freshly-installed Linux machine with a freshly built kernel and wishes to secure it. Although this paper concentrates on securing a Slackware Linux machine, the concepts here can be applied to most any flavor of Linux or Unix, whether a SVR4 or BSD derivative. It is also assumed that the machine is already configured with a TCP/IP stack and is ready to be placed on a network. Understanding of fundamental concepts of Unix (such as file permissions and editing scripts) will be helpful.
Disclaimer:
Properly securing a machine can be a daunting task; especially with the amount of new exploits surfacing on an almost daily basis. This paper is not meant to be a total security solution, but should instead be regarded as a guide to security through many of the measures that can be taken to protect a machine from intruders.
- Services
Before installing any software to increase the machine's security, the first task in locking down the system is shutting down services. This is accomplished by means provided by Linux.
- Inetd services
The first thing to take a look at is the /etc/inetd.conf file. Most Unix TCP and UDP services are initialized from this file. A short section is shown below:
-- sample inetd.conf section --
ftp stream tcp nowait root /usr/libexec/ftpd ftpd -l #telnet stream tcp nowait root /usr/libexec/telnetd telnetd #shell stream tcp nowait root /usr/libexec/rshd rshd #login stream tcp nowait root /usr/libexec/rlogind rlogind -- sample inetd.conf section --
(1) (2) (3) (4) (5) (6) (7)
- /etc/inetd.conf fields explained
- service name
- socket type (stream or datagram)
- protocol type (TCP or UDP)
- wait/nowait - If wait server will subsequently process all connections, if nowait server will exec a new server process for each connection
- user
- command Name
- arguments (Optional)
Any services preceded by a pound sign (#) are commented out and therefore will not be started at boot time.
Inetd is a daemon (also known as the SuperServer) whose purpose is to listen for TCP or UDP connections. When a connection is received, inetd passes that connection to the appropriate service.
As an example, if a user establishes an ftp connection to a machine, inetd will answer the connection and pass it off to the ftp daemon, ftpd. This reduces overhead on the machine by having one daemon listen for connections rather than each individual service listening on their own. It is important for the admin to know their /etc/inetd.conf file intimately as this is often where an intruder will place one of many backdoors.
The first step will be to open the /etc/inetd.conf file with a text editor and comment out any and all services which are not necessary to the system's purpose. In general, the admin should be able to comment-out the overwhelming majority of the services in this file. Again, this depends on what sorts of services the machine is designated to provide. And for the purpose of a service-versus-security model, less is definitely more. If the admin is not sure if a particular service is needed, it's best to turn it off. If the service is later deemed necessary, it can be re-enabled. The only caveat on re-enabling a previously disabled service is that the version being enabled must come from trusted source (eg, vendor media) and be the latest version with all applied patches. In short, the admin is strongly encouraged to do their research and know their software.
After commenting out unnecessary services inetd needs to be restarted so the changes just made will take effect.
# ps -auwx | grep inetd
#kill -HUP
Note: It is generally a good idea to completely remove any packages that you will not be using. This can be accomplished in Slackware Linux using the 'pkgtool' feature .
- RPC / NFS Services
Remote Procedure Call (RPC) and Network File Service (NFS) are a series of network protocols that allow a network of systems to operate as if they were a single machine. RPC essentially allows programs to run on a distributed basis across many machines. NFS allows a machine to share parts of its filesystem to a remote machine. Not surprisingly, both RPC and NFS are notoriously insecure and should be avoided at all costs. As an example, if NFS is set up incorrectly -- which is very easy to do -- any remote machine could feasibly mount that NFS partition and have access to the data within.
RPC and NFS connections are managed by the portmapper. The portmapper is a daemon that is called from /etc/rc.d/rc.inet2 on Slackware systems. If you are using another flavor of Linux or Unix you may have to do some searching to discover from what start-up script the portmapper and rpc services are called from. To do this, issue commands such as:
# find /etc -name "*map*" -print | more
# find /etc -name "*nfs*" -print | more
# find /etc -name "*port*" -print | more
# find /etc -name "*rpc*" -print | more
The above commands should yield where the specific scripts to start these services reside in your /etc/rc.d hierarchy.
Since the value of using RPC and NFS services is usually outweighed by the insecurity of the protocols, these services will be disabled. In a text editor, open /etc/rc.d/rc.inet2. Go through each section of the file and determine what services to leave and which to comment out. The specific section we are looking for should look something like:
# Start the SUN RPC Portmapper. if [ -f ${NET}/rpc.portmap ]; then echo -n " portmap" ${NET}/rpc.portmap fi
We can comment out these lines and when the system is restarted, the portmapper will not be started. Take the time to go through this file line by line. Further down in the file is a section where the RPC services are called from, these can be commented out also.
It should also be noted that many Linux and Unix variants initiate the rc.d scripts which are prefaced by an "S". Renaming these scripts so they are prefaced by a "K" will direct your server to kill said processes instead of starting them.
- Logging
Logging on Unix system is handled by the syslogd daemon. As with Linux's overall default security posture, the default logging leaves much to be desired. The global file that controls how logging is handled, and where log files are stored is the /etc/syslog.conf file:
-- sample syslog.conf section -- *.=info;*.=notice /usr/adm/messages *.=debug /usr/adm/debug -- sample syslog.conf section -- (1).(2) (3)
- SUID/SGID Binaries
SUID and SGID files are files with a special bit set on them that allow a regular user to run binaries with elevated privileges. As an example, the Sendmail program must access system resources that only the root user can normally access. By making the Sendmail program Set User ID (SUID) root, a regular user will still be able to run the program. A Group User ID (SGID) file follows the same approach but runs the binary with a group other than that of which the user belongs to. These files will often be the focus of malicious local users looking to gain unauthorized elevated privileges. These files are easy to spot because of the SUID/SGID flag:
# ls -al /usr/sbin/sendmail
r-sr-xr-x 1 root kmem 326329 Oct 15 01:21 /usr/sbin/sendmail
Notice in the user permission field for the files owner there is an 's' where you normally find an 'x'. This indicates the file is SUID and can be executed by a regular user even though the files runs with elevated privileges.
# ls -al /usr/sbin/foo
r-xr-sr-x 2 foo foo 14567 Oct 15 01:22 /usr/sbin/foo
In this example we find an 's' in place of the executable bit in the group permissions field. This indicates the file is SGID and can be run by a regular user but with elevated group access.
- Locating and Removing SUID/SGID Binaries
It is a good idea to determine what binaries on our system are SUID/SGID and try to reduce that list to the bare minimum. The following command will search the entire file system for SUID/SGID files and list them in a file called /tmp/suids. We are going to use this list as a script to remove unnecessary SUID/SGID files.
#find / \( -perm -4000 -o -perm -2000 \) -exec ls -ldb {} \; >> /tmp/suids
Now we can examine the /tmp suids file with an editor and remove any files from the list we wish to allow to remain running SUID/SGID. Most files that are set SUID/SGID can be run with more favorable permissions. Another option to removing the SUID and SGID bits is to refine the access control to limit access to those files to a particular group.
After we have determined which files we wish to remain running SUID/SGID we can use vi to convert our file into a script.
- cat /tmp/suids |cut -b55-200 > $HOME/remove_suid.sh
- cd
- vi remove_suid.sh
- :%s/ \//chmod -s \//g
- <return>
- Add the following to the top of the file:
- #!/sbin/sh
- :wq!
- chmod 700 remove_suid.sh
- ./remove_suid.sh
The script will then strip the SUID and SGID bits from any files that were left on our list. After running the script run the above find command again to ensure the bits were stripped properly. Ensure these files are removed from the /tmp and $HOME directories once the script has been executed.
- TCP-Wrappers
TCP-Wrappers is an access control mechanism for TCP and UDP services written and maintained by Wietse Venema. Fortunately, TCP Wrappers comes default with most flavors of Linux. If for some reason you do not have TCP Wrappers on your system, it can be obtained from ftp://ftp.porcupine.org/pub/security.
TCP-Wrappers are designed to restrict TCP or UDP services called from inetd to particular host names and or IP addresses. They can also be used to restrict certain hostnames and or IP addresses from accessing TCP and UDP services.
This is done through two separate access control lists. The first, /etc/hosts.allow determines what hosts are allowed to connect to what services. The second file, /etc/hosts.deny determine what hosts are specifically restricted from what services. These access control lists provide a powerful and flexible method for allowing and denying access to a system. First we will examine a sample /etc/hosts.allow file:
-- sample /etc/hosts.allow file --
wu.ftpd: 192.168.1.1, 192.168.1.2
ipop3d: barney
-- sample /etc/hosts.allow file --
The syntax of the file is fairly obvious. In the above example we are allowing ftp access to the two IP addresses listed and pop access to the host 'barney'.
Typically setting up the /etc/hosts.deny file is even easier as we can see in below:
-- sample /etc/hosts.deny file --
ALL: ALL
-- sample /etc/hosts.deny file --
At first glance it may seem we are restricting access to the system's services to everyone. By setting up our access control list in this fashion we are following the golden rule of "that which is not expressly permitted is denied". Essentially we are denying everyone access to all services called from inetd.conf with the exception of the hosts listed in the /etc/hosts.allow file. Obviously this is a much better policy than the flipside which is "everything is allowed except that which is forbidden".
These concepts may seem confusing but they are very simple. It is much easier to deny everything to everyone then set up allows for specific trusted hosts than to try and allow everything to everyone with the exception of certain untrusted hosts.
TCP Wrappers also contains other specialized functions such as the ability to set customized logging variables and also display a banner upon connection to certain services. Be sure to consult the documentation included with the distribution to use these features.
- SSH
There is no sane reason to still be using telnet to remotely connect to a machine. With programs like telnet, all of our data is sent across the wire unencrypted. SSH is a client-server utility that provides an encrypted tunnel between two or more machines.
- Tripwires
Tripwire is a commercial program that can be used to monitor and detect changes to critical files and binaries on your system. Often times an attacker will replace a binary on a system with a trojaned version. As an example, the 'ps' command is frequently trojaned binary. The attacker can configure the trojaned version of 'ps' to hide any system processes, such as a sniffer, from the machines administrator. The heart of tripwire is the MD5 series of encryption algorithms. MD5 works by taking a message (this can be a binary file or a text file) as it's input, and producing a 128-bit digital fingerprint as it's output. An example is shown below.
------- ps -----------> | MD5 | -------------> b38674b49f679a4ecdd47b7e0642dc85 -------
Generally a database of fingerprints for important system binaries and files is generated and kept offline or read-only media. If an attacker was to modify the ps binary in any way and we generated a new fingerprint, it would be drastically different than the first fingerprint we generated. Keeping the fingerprint database stored offline or on read-only media cannot be stressed enough. If this database is kept online and attacker could easily trojan a system and then generate new fingerprints to the database. The next time fingerprints were reconciled, the prints would match. This also goes back to what I said about proactive security. If you are implementing a tripwire on a system that is already in place, you may be generating fingerprints for binaries that had already been trojaned. Another reason why it is best to start out on a freshly installed system
Essentially Tripwire is a program written around the MD5 algorithm. I have always found it to be a bit cumbersome so we will take a look at building a home-made tripwire using readily available software. Depending on your needs, if you'd prefer to use the commercial product it may be obtained from www.tripwire.com.
Now we will take a look at setting up a home-made tripwire. First we need to generate a set of known good fingerprints. A minimal set of recommended binaries to tripwire are already in the script. The script is generic and can be easily modified to suit your needs.
Note: This script relies on the md5sum utility which is a default package for most Linux installations. If md5sum is not installed on your system, it may be downloaded from: ftp://ftp.pgp.net/pub/pgp/utils/md5sum/.
--begin generate.sh--
#!/bin/sh #Generate a set of known-good fingerprints for important system files #Make sure you have a blank floppy formatted with the ext2 file system #in /dev/fd0 mount -t ext2 /dev/fd0 /mnt md5sum /sbin/ifconfig > /mnt/database.orig md5sum /bin/netstat >> /mnt/database.orig md5sum /usr/bin/who >> /mnt/database.orig md5sum /usr/bin/md5sum >> /mnt/database.orig md5sum /bin/ls >> /mnt/database.orig md5sum /bin/ps >> /mnt/database.orig md5sum /usr/sbin/syslogd >> /mnt/database.orig md5sum /sbin/ifconfig >> /mnt/database.orig md5sum /usr/sbin/inetd >> /mnt/database.orig sleep 5 umount /dev/fd0
--end generate.sh--
We now have a known clean set of fingerprints for our important system files on a floppy disk. Be sure to write-protect the floppy via the physical tab located on the floppy disk, or optimally, burn the fingerprints to CD-ROM.
The following script will generate a new set of fingerprints called /tmp/databse, mount the media which the known good set of prints is contained on, compare the two sets of fingerprints, and then take appropriate measures. The /tmp/database file will then be removed and the media with the known-good set of prints will be unmounted. Once again this script can be easily tailored to suit your particular needs.
Note: This script can be run from cron on whatever basis you feel is necessary. If paranoid, once an hour wouldn't hurt. Ensure the permissions on the /tmp directory are readable and writable by root only. Also ensure that you save this file with the proper file permissions, otherwise all the work we have done can easily be thwarted by a clever attacker. The following crontab will run this script once an hour:
00 * * * * /bin/sh /usr/sbin/update.sh
--begin update.sh-- #!/bin/sh # A customizable tripwire # Thanks to munge@attrition.org for the shell scripting help # Mount our known-good fingerprint database # Change /dev/fd0 to suit your needs mount -t ext2 /dev/fd0 /mnt # additionally add to email to root? if [ $? -ne 0 ] then echo "Aborting, perhaps disk is not in drive?" exit 99 fi # this gets run in 2 situations, what the hell: RMS() { rm -f /tmp/database /tmp/diffs } # Generate a new batch of fingerprints and temporarily store them in /tmp/database sleep 5 md5sum /sbin/ifconfig > /tmp/database md5sum /bin/netstat >> /tmp/database md5sum /usr/bin/who >> /tmp/database md5sum /usr/bin/md5sum >> /tmp/database md5sum /bin/ls >> /tmp/database md5sum /bin/ps >> /tmp/database md5sum /usr/sbin/syslogd >> /tmp/database md5sum /sbin/ifconfig >> /tmp/database md5sum /usr/sbin/inetd >> /tmp/database sleep 5 # DIAGNOSTICS # An exit status of 0 means no differences were found, # 1 means some differences were found, and 2 means trouble.' # 'create temp file of diffs:' # Compare the newly generated set of fingerprints to the known good set diff /tmp/database /mnt/database.orig > /tmp/diffs # '$? is the exit code of the previous command' EXIT=$? # if all is well mail will be sent to root if [ $EXIT -eq 0 ] then echo "Finger Prints match" | mail -s FingerPrints root RMS ; # run the rm function umount /mnt exit 0 ; # no need to run the rest of the program, die fi # rest of program assumes things have gone badly....
# Insert this as the first line of the body # and pipe to mail: # If fingerprints don't match mail root stating so sed '1iBAD MATCH! SHAME ON ADMIN! ' /tmp/diffs | mail -s FingerPrints root # 'changed rm flag to -f so your # program does not crap out if # it does not find the file' RMS umount /mnt # Additionally send mail to our pager stating we have a problem # Something bad has happened so halt the machine after the page has been # sent. if [ $EXIT -ne 0 ] then echo "Possible System Compromise" | mail -s "Badmatch!" pager@pagemart.net sleep 30 shutdown -h now fi
--end update.sh--
- Closing
If you take the time to walk through your filesystem and ensure that both file and group permissions are reasonable you should then have a secure Linux machine. In the next article additional measures and software will be discussed that can be used to further secure the machine. Remember, the security of a machine is an on-going job. Stay current with new exploits and vulnerabilities. Know your system and know your software. It is always a good idea to frequently audit your system to make sure none of the controls you have put into place have been compromised.
One other thing to keep in mind is the physical security of a machine. Yes, you may have spent the greater part of a day securing that box but it only took Bob the Disgruntled Employee five minutes to reboot the system with installation floppies and add himself a root account. If the machine must remain in a place accessible to others invest in floppy drive locks or remove the floppy drive altogether.
To read Securing Linux Part II, click here.
|