HostedDB - Dedicated UNIX Servers

-->
Beginner's guide to armoring Linux Preparing your linux box for the Internet
Armoring Linux

Lance Spitzner
http://www.enteract.com/~lspitz/papers.html
Last Modified: 25 June, 2000

Organizations throughout the world are adopting Linux as their production platform.   By connecting to the Internet to provide critical services, they also become targets of opportunity.  To help protect these Linux systems, this article covers the basics of securing a Linux box.  The examples provided here are based on Red Hat 6.0, but should apply to most Linux distributions.

Installation
The best place to start in armoring your system is at the beginning, OS installation. Since this is a production system, you cannot trust any previous installations. You want to start with a clean installation, where you can guarantee the system integrity. Place your system in an isolated network. At no time do you want to connect this box to an active network nor the Internet, exposing the system to a possible compromise. I personally witnessed a system hacked by a script kiddie within 15 minutes of connecting to the Internet.  To get critical files and patches later, you will need a second box that acts as a go between. This second box will download files from the Internet, then connect to your isolated, configuration "network" to transfer critical files or burn the patches to a CDROM.

Once you have placed your future Linux box in an isolated network, you are ready to begin. The first step is selecting what OS package to load. As of RH 6.0, you have three options, Workstation, Server, and Custom (default).  I highly recommend Custom, as this allows you to choose what services are added and how the system is partitioned.  The idea is to load the minimum packages, while maintaining maximum efficiency.   The less software that resides on the box, the fewer potential security exploits or holes.  This means if you do not need a News or Real Audio Server, don't install it.  The nice thing about Linux is, if you change your mind, it is easy to add packages later.  Regardless of which installation you choose, I would add the manual pages and HOWTO docs.  I find the on-line man pages and docs to be a critical resource that add little risk to your system.

If you selected Custom, you will be asked to partition your system.  I always like to make root as big as possible and just throw everything in there, then you do not run out of room in the future.  However, we do need several partitions to protect the root drive.  If we were to fill the root partition with data, such as logging or email, we would cause a denial of service, potentially crashing the system.

Therefore, I always recommend a separate partition for /var, this is where all the system logging and email goes.  By isolating the /var partition, you protect your root partition from overfilling.   I've found 400 MB to be more then enough for /var (increase this if your system will have alot of mail) .  You may also consider making a separate partition for specific application purposes, especially applications that store extensive logging. If you are going to have users on your system you do not trust, you may also want to create a seperate /home directory, so malicious users cannot fille the / partition. For a standalone server, your partitions may look as follows:

/        - everything else
/var     - 400 MB
swap     - (I normally go with 256 MB)
 

Once the system has rebooted after the installation, be sure to install the recommend security patches. For Red Hat, you can find these security patches at Red Hat's errata support site.  Patches are critical to armoring a system and should always be updated.  bugtraq@securityfocus.com or redhat-watch-list-request@redhat.com are excellent sources for following bugs and system patches.  Without these patches, your system can be easily compromised.  Be sure to use your go between box to get the patches, the Linux box should always remain on an isolated network. . For Red Hat, once you download the rpm, you can easily update your system using the following syntax.  An excellent example of this is the security update for wu-ftpd

rpm -Uvh wu-ftpd-2.6.0-14.6x.i386.rpm

For systems that are already on-line, you can ftp the rpm and install it at the same time, using the following syntax.

rpm -Uvh ftp://updates.redhat.com/6.1/i386/wu-ftpd-2.6.0-14.6x.i386.rpm

As of RH 6.1, there is a new utility for patches called 'up2date'. I highly recommend you try this excellent utility. When ran on a local system, it determines which .rpm's need to be updated, gets those rpm's from Red Hats's web site, and then downloads and installs the updated files. This tool is highly customizable and easy to use.

Eliminating Services
Once you have loaded the installation package, patches, and rebooted, we are now ready to armor the operating system. Armoring consists mainly of turning off services, adding logging, tweaking several files, and configuring TCP Wrappers. First we will begin with turning off services.

By default, Linux is a powerful operating system that executes many useful services. However, most of these services are unneeded and pose a potential security risk. The first place to start is /etc/inetd.conf. This file specifies which services the /usr/sbin/inetd daemon will listen for. By default, /etc/inetd.conf is configured for a variety of services, you most likely only need two, ftp and telnet. You eliminate the remaining unnecessary services by commenting them out (example A).  This is critical, as many of the services run by inetd pose serious security threats, such as popd, imapd, and rsh.  Confirm what you have commented out with the following command (this will show you all the services that were left uncommented)

 grep -v "^#" /etc/inetd.conf

The next place to start are the .rc scripts, these scripts determine what services are started by the init process. For Red Hat, you will find these scripts in /etc/rc.d/rc3.d (or /etc/rc.d/rc5.d if you automatically boot to a GUI, such as Gnome or KDE).  To stop a script from starting, replace the capital S with a small s. That way you can easily start the script again just by replacing the small s with a capital S. Or, if you prefer, Red Hat comes with a great utility for turning off these services.  Just type "/usr/sbin/setup" at the command prompt, and select "System Services", from there you can select what scripts are started during the boot up process.  Another option is chkconfig, which you will find on most distributions.  The following startup scripts may be installed by default but are not critical to system functioning.  If you don't need them, turn these scripts off.  The numbers in the names determine the sequence of initialization, they may vary based on your distribution and version.  Scripts that start with a capital K instead of a captial S are used to kill services that are already running.

S05apmd       (You only need this for laptops)
S10xntpd     (Network time protocol)
S11portmap   (Required if you have any rpc services, such as NIS or NFS)
S15sound     (Saves sound cared settings)
S15netfs     (This is the nfs client, used for mounting filesystems from a nfs server)
S20rstatd    (Try to avoid running any r services, they provide too much information to remote users)
S20rusersd
S20rwhod
S20rwalld
S20bootparamd (Used for diskless clients, you probably don't need this vulnerable service)
S25squid     (Proxy server)
S34yppasswdd (Required if you are a NIS server, this is an extremely vulnerable service)
S35ypserv    (Required if you are a NIS server, this is an extremely vulnerable service)
S35dhcpd     (Starts dhcp server daemon)
S40atd       (Used for the at service, similar to cron, by not required by the system)
S45pcmcia    (You only need this script for laptops)
S50snmpd     (SNMP daemon, can give remote users detailed information about your system)
S55named     (DNS server.  If you are setting up DNS, upgrade to the latest version of BIND,  http://www.isc.org/bind.html)
S55routed    (RIP, don't run this unless you REALLY need it)
S60lpd       (Printing services)
S60mars-nwe   (Netware file and print server)
S60nfs       (Use for NFS server, do not run unless you absolutely have to).
S72amd        (AutoMount daemon, used to mount remote file systems)
S75gated      (used to run other routing protocols, such as OSPF)
S80sendmail  (You can still send email if you turn this script off, you just will not be able to receive or relay)
S85httpd     (Apache webserver, I recommend you upgrade to the latest version, http://www.apache.org)
S87ypbind     (Required if you are a NIS client)
S90xfs       (X font server)
S95innd      (News server)
S99linuxconf  (Used to remotely configure Linux systems via browser, every black-hat's dream :)

To see how many services are running before you change the startup scripts, type

ps aux | wc -l

Once you are done with the installation and have turned off the startup scripts, type the command again and compare how the number of services have decreased. The fewer services running, the better. Also, confirm which are left running by executing the following command:

netstat -na --ip

Logging and Tweaking
Once you have eliminated as many services as possible, we want to enable logging. All system logging occurs in /var/log.   By default, Linux has excellent logging, except for ftp.  You have two options for logging for ftp, configure /etc/ftpaccess file or edit /etc/inetd.conf.  I prefer to edit /etc/inetd.conf, as it is simpler (i.e. harder to mess up :).  Edit /etc/inetd.conf as follows to ensure full logging of all FTP sessions.

ftp     stream  tcp     nowait  root    /usr/sbin/tcpd  in.ftpd -l -L -i -o

--- From the man pages ---

If the -l option is specified, each ftp session is logged in the syslog
If the -L flag is used, command logging will be on by default as soon as the ftp server is invoked.  This will cause  the  server  to log all USER commands, which if a user accidentally enters a password for that command instead of the username, will cause passwords to be logged via syslog.
If the -i option is specified, files received by the ftpd(8) server will be logged to the xferlog(5).
If the -o option is specified, files transmitted by the ftpd(8) server will be logged to the xferlog(5).

--- snip snip ---

Next comes tweaking. This involves various file administration. The first thing we want to do is secure our /etc/passwd file (this is the database file that holds your user accounts and passwords).  First, we want to ensure our system is using /etc/shadow, this securely stores everyone's password as hashes in a file only root can access.  This protects your passwords from being easily accessed and cracked (one of the first exploits a hacker looks for).  The use of shadow passwords is default as of RH 6.0, however it never hurts to be sure. All you have to do is type the following command as root.  This automatically  converts your passwords to the /etc/shadow file. Of all the actions you can take to secure your system, I consider this to be one of the most important.

pwconv

The second step is to remove most of the default system accounts in /etc/passwd.  Linux provides these accounts for various system activities which you may not need.  If you do not need the accounts, remove them.  The more accounts you have, the easier it is to access your system.  An example is the "news" account.  If you are not running nntp, a news group server, you do not need the account (be sure to update /etc/cron.hourly, as this looks for the user "news"). Also, make sure you remove the "ftp" account, as this is the account used for anonymous ftp.  From the man pages.

man ftpd:

       Ftpd authenticates users according to four rules.

       4)     If  the  user name is ``anonymous'' or ``ftp'', an anonymous ftp account must be pre-sent in the password file (user ``ftp'').  In this case the user is allowed to log in by specifying any password (by convention this is given as the client host's name).

For an example of my /etc/passwd file, check out example C.

We also want to modify the file /etc/ftpusers (example D). Any account listed in this file cannot ftp to the system. This restricts common system accounts, such as root or bin, from attempting ftp sessions. Linux has the file by default.  Ensure that root stays in this file, you never want root to be able to ftp to this system.  Ensure that any accounts that need to ftp to the box are NOT in the file /etc/ftpusers.

Also, ensure that root cannot telnet to the system. This forces users to login to the system as themselves and then su to root. The file /etc/securetty lists what ttys root can connect to.  List only tty1, tty2, etc in this file, this restricts root logins to local access only.  ttyp1, ttyp2, are pseudo terminals, they allow root to telnet to the system remotely (example E).

Last, create the file /etc/issue. This file is an ASCII text banner that appears for all telnet logins (example B). This legal warning will appear whenever someone attempts to login to your system. If you want to continue using the same /etc/issue file, you will have to modify /etc/rc.d/init.d/S99local.  By default, Linux creates a new /etc/issue file on every reboot.
 

Connecting to your server
For those of you who will be doing remote administration, it is critical that you develop a secured, controlled way to connect to the server.  Often, you need remote access to your server for administration or the uploading of files, these communications need to be secured  I will discuss two options here, ssh and TCP Wrappers.

I prefer ssh, as it encrypts all communication between you and the firewall.  TCP Wrappers will NOT protect your network traffic from sniffing.  Users can still capture all of your keystrokes  (including passwords) on the network.  If you are concerned about users capturing communications to your firewall, I recommend you replace telnet/ftp with ssh.  ssh will encrypt all communications to your server, allowing you both to upload files and administer the server in a secure manner.  ssh is similar to TCP wrappers in that it has its own layer of logging, and can limit what systems can connect to it.  For more information on ssh, you can find ssh here, including source for both ssh clients and server daemon.  I recommend you use ssh version 1.2.x, as version 2.x has a limiting license. Another ssh option is Openssh.

TCP Wrappers, while it does not encrypt, it does log and control who can access your system.  It is a binary that wraps itself around inetd services, such as telnet or ftp. With TCP Wrappers, the system launches the wrapper for inetd connections, logs all attempts and then verifies the attempt against a access control list. If the connection is permitted, TCP Wrappers hands the connection to the proper binary, such as telnet. If the connection is rejected by the access control list, then the connection is dropped.  Fortunately for us Linux users, TCP Wrappers is already installed, the only thing left for us to do is edit the /etc/hosts.allow and /etc/hosts.deny file.  These files determine who can and cannot access our systems.  Also, TCP Wrappers allows us to do fancy things, such as banners or spawn additional programs, such as safe_finger.  The syntax is relatively simple.  Put the IP address or networks in /etc/hosts.allow that you want to permit connections from.  Put IP addresses or networks in /etc/hosts.deny that you do not want to permit access.  By default, Linux allows connections from everyone, so you will need to modify these files.  2 recommendations when working with TCP Wrappers.

  1. Use IP addresses instead of system or domain names.
  2. Set up /etc/hosts.deny to deny everything (ALL), then permit only specific sites with /etc/hosts.allow.
For examples on how to setup /etc/hosts.allow and /etc/hosts.deny, see example F.  For more ideas on how to use TCPWrappers, check out Intrusion Detection.
 
 

For the Truly Paranoid
I consider the measures discussed above absolutely essential.  By following these steps, you have greatly improved your system's security, congratulations!  Unfortunately, your system is not 100% secure, nor will it ever be.  So, for the truly paranoid, I have added some additional steps you can take.

First we will create the wheel group.  The wheel group is a group of select individuals that can execute powerful commands, such as /bin/su. By limiting the people that can access these commands, you enhance the system security.  To create the group, vi the file /etc/group, create the group wheel, and add the system admins to the group.  Then identify critical system binaries, such as /bin/su.  Change the group ownership to wheel, and the permissions to owner and group executable only (be sure to maintain the suid or guid bit for specific binaries).  For /bin/su, the commands would be:

/bin/chgrp wheel /bin/su
/bin/chmod 4750 /bin/su

Second, we will lock down the files .rhosts, .netrc, and /etc/hosts.equiv.  The r commands use these files to access systems.  To lock them down, touch the files, then change the permissions to zero, locking them down. This way no one can create or alter the files. For example,

/bin/touch /root/.rhosts /root/.netrc /etc/hosts.equiv
/bin/chmod 0 /root/.rhosts /root/.netrc /etc/hosts.equiv

Third, we configure /etc/shadow to use MD5 hashes instead of the crypt(3) function.  This makes the encrypted password file far more difficult to crack.  This is done by modifying the PAM modules.  PAM (Pluggable Authentication Modules) is a suite of shared libraries that enable you to choose how applications authenticate users.  To learn more about PAM, check out ftp://ftp.us.kernel.org/pub/linux/libs/pam/Linux-PAM-html/pam.html.

In the old days, you had to manually modify the PAM modules to use MD5 hashes.  However, with Red Hat 6.0 or greater, you can select MD5 hashes with the setup utility.  Just type "setup" at the command prompt, then select "authentication configuration".  From there, you can choose to use MD5 hashes.  However, the MD5 hashes will not take effect until the user re-enters their password.  For those of you who do not have the setup utility (or have Red Hat 5.2 or earlier), you can still modify the PAM modules manually (example G).

For us bash users, I'm not a big fan of the .bash_history file.  I do not want people (including root) to know my command history.  So, in my .bash_profile, I export the following entry:

HISTFILESIZE=0

This means that nothing will be logged to my .bash_history file.  I will still have keystroke history and recall, the HISTSIZE env variable, but command history will not be written to the .bash_history file.

Last thing we can do is protect our system from physical access.  This mainly consists of setting up a password for our BIOS.  Also, you can password protect your system during boot-up by configuring /etc/lilo.conf with a password (password=xxx)  where xxx is your password.  However, keep in mind, once someone has physical access to your system, there is no guaranteed way to protect it.

IPChains
No discussion about Linux security would be complete without covering IPChains.  IPChains is packet filtering software that comes with the 2.2.x kernel and above. This means if you are running Red Hat 6.0 or later, you have it as part of your Linux installation kit.  IPChains is similar to Cisco Access Control Lists, it can control what packets can come in and out of your Linux box.  Primarly used as a firewall application, IPChains can also be used to armor your standalone Linux box.    To armor a standalone system, I configure IPChains to allow only TCP connections I initiate.  If anyone attempts to initate any TCP connections to me, the connection is denied.  Since IPChains is not stateful, I do allow all UDP and ICMP connections.  Last, I log all denied connections, this lets me know if someone out there is being naughty :)  However, I drop but do not log all the broadcat/multicast traffic, as this would quickly fill up the system logs. A simple IPChains configuration to armor a standalone system would look something like this.

bash# ipchains -L
Chain input (policy DENY):
target prot opt source destination ports
DENY all ------ 0.0.0.0 anywhere n/a
DENY all ------ anywhere 255.255.255.255 n/a
DENY all ------ anywhere BASE-ADDRESS.MCAST.NET/8 n/a
ACCEPT tcp !y---- anywhere anywhere any -> any
ACCEPT udp ----l- anywhere anywhere any -> any
ACCEPT icmp ----l- anywhere anywhere any -> any
DENY all ----l- anywhere anywhere n/a
Chain forward (policy ACCEPT):
Chain output (policy ACCEPT):

To see the config files for this, see example H. To learn more about using IPChains as a firewall or for a standalone system, check out the IPChains HOWTO.

Conclusion
We have covered some of the more basic steps involved in armoring a Linux box (Red Hat distribution). The key to a secure system is having the minimal software installed, with protection in layers, such as TCP Wrappers, IPChains, and shadowed passwords. There are many additional steps that can be taken, such as  tripwire (monitor changes in system binaries) and swatch (automated log monitoring and alerts). I also recommend that new Linux users check out Bastille Linux, a PERL script that can automatically secure your new Linux system, step by step. Remember, no system is truly 100% secure. However, with the steps outlined above, you greatly reduce the security risks.
 

Author's bio
Lance Spitzner enjoys learning by blowing up his Unix systems at home. Before this, he was an Officer in the Rapid Deployment Force, where he blew up things of a different nature. You can reach him at lance@spitzner.net .
 
 

Whitepapers / Publications