Network Defense by Rik Farrow When less is better Last month's column focused on reducing network services to the bare minimum for an exposed NT Web server. This month we will do the same for a UNIX-based Web server, as well as examining other things that you can do to lock down a any UNIX-based server, internal or external. If all networked services are disabled, the only way to access a system is from the console or by usurping network connections originating from that system. For example, a desktop user machine with no services enabled could still get into trouble by receiving email with an overly-endowed mail reader (the Melissa virus) or by receiving active content (ActiveX or Java). Our focus is on servers, and you can eliminate these threats from critical servers by eliminating desktop-styled users. Users have no business working on any server system. Microsoft attempts to enforce this behaviour on NT domain controllers by prevent non-administrative logins. The problem with this approach is that many NT users log into the Administrator account, or one in the Administrators group, defeating this protection. For the UNIX-based server system, we can go further in eliminating possible misuse. For a start, the only accounts on the server system will be for root and other administrative accounts, for example, a webadmin. And for another, we simply will not install software on the server that makes it into an attractive and useful desktop system. Less is More The UNIX operating system started out with a tiny memory footprint by today's standards. Early multi-user versions of UNIX required only 256 kilobytes of RAM, and had small amounts of disk space as well. As more features were added, the operating system and utilities grew to the point that the OS (kernel) required more than a megabyte just for itself, and a full installation required hundreds of megabytes of disk space. But you can still create a minimal installation of UNIX, simply through choosing the custom installation option provided in most UNIX installation scripts. For example, using BSDi, (Berkeley Software, Designs, Inc. Colorado Srpings, CO) you can choose Custom Installation, and then select to install only Required packages. This will provide you with the basic UNIX tools, networking including an Apache Web server, but no graphical user interface programs and no X Window server. The other BSD versions work similarly. Under RedHat (Raleigh, NC) Linux 5.2, you will have an opportunity to select components during installation. Choose the Web server component, and leave "Select Individual Packages" selected as well. After clicking "OK" to select components, go through the list of applications and make certain that you do not have the C compiler, C libraries, or X system selected. After you complete the check, RedHat checks cross-dependencies, and will automatically select any other required packages for you. Without the X client applications and the X server, any user is forced to use the command line (not that many UNIX users have to be forced to do this). Applications that can be exploited "passively", such as Web browsers, are not even installed. And, X has itself been an exploitable vulnerability on many UNIX systems. Because this system does not use X, you can dispense with the graphics adapter as well. Most UNIX systems will work "headless", that is, without a monitor and video adapter, and automatically select the first serial port as the console port. Again, we have made this system less attractive to ordinary users, as well as less expensive and better suited for its duty as a server. Of course, you might really like working with X, and using a mouse. Well, relax, because what I am suggesting is that you set up a second UNIX system with a full installation. You can have X, a C (and C++) development systems, and anything else you want on this system, because it will be on your internal network, and will be used to mirror to the exposed Web server. Striptease UNIX systems come with lots of network services, and most are enabled by default. Unlike NT, UNIX does not have a point-and-click method for disabling services (Linux versions do, but they require X, which we have excluded). What you need to do to disable network services is to edit configuration files and comment out certain lines, or rename some scripts. UNIX comes in two flavors when it comes to system startup. You can distinguish between the two flavors easily--just look for a file named /etc/inittab. System V-styled UNIX versions will have one, and BSD-style versions will not. Let's discuss the BSD version first. During bootup, BSD systems start the init program, which consults /etc/ttys, then runs the /etc/rc script. The /etc/rc script will, in turn, start other scripts (/etc/netstart and /etc/rc.local). Some of the network servers are started in /etc/rc and /etc/rc.local, and you can prevent them from being started after a reboot by commenting out the line where the service is started. For example, to prevent sendmail from starting, you comment out the line in /etc/rc where it gets executed during the boot process (Listing 1). System V-based UNIX versions take a different tack. Like BSD systems, they start the init process, but init follows the directions found in /etc/inittab rather than executing the /etc/rc script. Each line in /etc/inittab includes a label, run levels, an action field, and a command. If the run level matches, then the action field is consulted. Most inittab files will have an 'initdefault' action that defines the default run-level. If this entry is absent, the default run-level will be 2. RedHat has an initdefault entry that sets the run-level to 3. (Solaris 7 has a similar entry). Every inittab entry that either matches the run-level, or has an empty runlevel field, will be executed during boot, so the scripts at the end of the entries are where to look for services started at boot time. Again, this is easier than it seems, because the key script for most System V UNIX systems is called rc or rc2 (Linux uses /etc/rc.d/rc and Solaris uses /sbin/rc2 and /sbin/rc3). These scripts then execute other short scripts that stop or start network services. On Linux systems, these short scripts are found in /etc/rc.d, and under Solaris, you find then within the /etc directory. Each subdirectory includes the run-level name, for example /etc/rc3.d for run-level 3. To disable network services from starting during booting, you go to the appropriate directory and rename scripts that begin with S to a name beginning with something else, like a small 's' (UNIX is case sensitive). This simple change prevents thr rc script from locating the script and starting the related network service. For example, the /etc/rc.d/rc3.d directory on RedHat includes a script named S88sendmail. By renaming this script, you prevent sendmail from being startup during booting (see Listing 2). Internet Daemon There is one other location where network services get started for both styles of UNIX systems. The inetd program gets started (from /etc/rc or by one of the 'S' scripts, such as S50inetd), and inetd gets its instructions from the /etc/inetd.conf file. If you are not planning to use FTP (and will use SSH instead), you can disable inetd and skip the next section. The Web server (httpd) gets started within the startup scripts, as does the SSH server (sshd2). Each entry in /etc/inetd.conf controls a particular service. You disable services by commenting out a line, and then either rebooting or by signaling inetd by sending a hangup signal (kill -HUP pid_of_inetd). For the Web server, you want to disable everything in this file except the FTP server. Place a comment symbol (#) at the beginning of each line (Listing 3). Even if you are not planning on starting inetd, it is a good practice to disable most services anyway. Note that disabling network services can be done to any UNIX system to improve security. You want to leave only the services required for normal operation, which for a workstation, might be none at all. Commonly, FTP and telnet services are left enabled in /etc/inetd.conf, a name server is run in caching only mode, and sendmail (or an SMTP replacement like qmail) runs to receive email from a central mail server. Okay, now that you've done all of that, let's check your work. Reboot the system, login, and try the netstat command to see what network services are still running. On most UNIX systems, netstat -a -f inet will list services that are listening and active Internet connections only. Linux does not include the -f inet options, and will also list UNIX domain sockets (there will not be many of these if an X server has not been started). Running netstat gives you an opportunity to check your work. If you think you have disabled sendmail, and you see the local address *.smtp, think again, because a mail transport agent (MTA) like sendmail is listening at port 25. On the hardened Web server, you should see either FTP or SSH, HTTP, and syslog. If you see more, you have more work to do disabling services. If you can't find a particular service, you may be able to use the lsof command to identify which service is listening to that port. You can also use the ps command (ps -auxww on BSD and ps ef under Linux) to learn the name of running processes, then use the grep command to search for that program's name in the startup scripts. UNIX systems come with a root account, just like NT includes the Administrator account. On the exposed Web server, only the root user will be able to login and use the command line. You do want to create another special account, the webadmin account mentioned earlier. This account will not be permitted to log in, but will use either FTP or (better) SSH to remotely manage the Web server. Since only the root will be be permitted to login, and then only from the serial port or via SSH, you can go wild with permissions on executable programs. Normally, any user can execute a program, and some programs have the set-user-id bit set. To start with, you can remove the set-user-id bit on any program that has it with the command lines in Listing 4. To go further yet, you can remove execute permission of group and other on all executables except /bin/ls (which is used by FTP) and any programs that will be used by the Web server (Perl, for example, although this can be an integrated module in Apache). Hardened Now, your Web server is almost ready for service. Only a the minimum necessary network services are enabled, and there are no unnecessary user accounts, and very little a non-root user could do anyway. The key to managing this hardened Web server is to build of clone of the Web directory hierarchy on an internal system which is fully configured, and mirror any changes out to the exposed (well, hopefully on a subnet behind the firewall) Web server. SSH and other encrypting tunnels are excellent choice for mirroring, and we will examine mirroring Web server in another column. [end test, beginning listings] Listing 1: On SBD systems, you comment out lines that start services that you do not want to start in the /etc/rc and /etc/rc.local files. For example, to prevent sendmail from starting, edit /etc/rc and comment out the line that starts sendmail: if [ -f /etc/sendmail.cf -a -x /usr/sbin/sendmail ]; then (cd /var/spool/mqueue; rm -f [lnx]f*) if [ ! -f /etc/aliases.db ]; then /usr/bin/newaliases >/dev/null 2>&1 fi # echo -n ' sendmail'; /usr/sbin/sendmail -bd -q30m fi Listing 2: On System V-styled systems, find the directory that contains the scripts to be executed during boot by examining /etc/inittab. Then rename scripts (with the mv command) to prevent them from being executed at boot time: root ) ls K07dmi S47asppp S74autofs S80spc K07snmpdx S69inet S74syslog S85power K28nfs.server S70uucp S74xntpd S88sendmail README S71rpc S75cron S88utmpd S01MOUNTFSYS S71sysid.sys S75savecore S92volmgt S05RMTMPFILES S72autoinstall S76nscd S93cacheos.finish S20sysetup S72inetsvc S80PRESERVE S99audit S21perf S73cachefs.daemon S80kdmconfig S99dtlogin S30sysid.net S73nfs.client S80lp root ) mv S88sendmail s88sendmail Listing 3: Both styles of UNIX systems will have an /etc/inetd.conf file. You prevent services from starting by commenting out lines in this file (only a few lines are shown): ftp stream tcp nowait root /usr/libexec/tcpd ftpd #telnet stream tcp nowait root /usr/libexec/tcpd telnetd -h #shell stream tcp nowait root /usr/libexec/tcpd rshd #login stream tcp nowait root /usr/libexec/tcpd rlogind -a #exec stream tcp nowait root /usr/libexec/tcpd rexecd #uucpd stream tcp nowait root /usr/libexec/tcpd uucpd Listing 4: Collect a list of set-user-id files, then remove the set-user-id bit from each of these files. Keep the list around for later reference: root ) find / -type f -perm -4000 -print > suidfiles root ) cat suidfiles | xargs chmod u-s Resources: BSDi: www.bsdi.com NetBSD: www.netbsd.com openbsd: www.openbsd.com RedHat Linux: www.redhat.com SSH: www.ssh.fi or www.datafellows.com