Firewalls, password policies, and encryption go a long way toward protecting your system from malicious access. They still aren't enough, though, to defend against a really determined hacker who has a "rootkit" or other tool designed to take advantage of some known weakness in one of your system's services. You can use a variety of third-party tools in FreeBSD that go beyond the functionality of a simple firewall to dynamically block suspicious hosts, monitor for intrusions, and control access to individual services on a host-by-host basis. The following sections describe a few of these tools. Using PortSentryPortSentry, from Psionic Software, is a daemon that monitors all incoming network traffic to detect port scanspreliminary attacks in which a hacker probes your system for open services that can be exploited. PortSentry listens in on a list of ports you specify. When PortSentry detects traffic that might indicate a port scan, it blocks that host from accessing your system by wrapping it in a blackhole route (a route that silently discards packets from a given IP address or range) or IPFW rule. All future connection attempts from the offending host are discarded. PortSentry monitors both TCP and UDP traffic, dynamically building a "killfile" table of sortsa list of banned addressesthat acts like an antibody against a virus. PortSentry reacts to suspicious activity by blocking it before it has a chance to cause any damage. PortSentry is an open-source tool and can be installed out of the ports (/usr/ports/security/portsentry). The portsentry binary is installed into /usr/local/bin, and the configuration file is /usr/local/etc/portsentry.conf. Open this file in your favorite text editor; it needs to be edited in order for PortSentry to work properly. You must decide which set of ports you want PortSentry to monitor. There are three available sets, in pairs beginning with TCP_PORTS and UDP_PORTS: # Un-comment these if you are really anal: #TCP_PORTS="1,7,9,11,15,70,79,80,109,110,111,119,138,139,143,512,513,514... #UDP_PORTS="1,7,9,66,67,68,69,111,137,138,161,162,474,513,517,518,635,640... # # Use these if you just want to be aware: TCP_PORTS="1,11,15,111,119,540,635,1524,2000,5742,12345,12346,20034,31337... UDP_PORTS="1,7,9,69,161,162,513,635,640,641,700,32770,32771,32772,32773... # # Use these for just bare-bones #TCP_PORTS="1,11,15,110,111,143,540,635,1080,524,2000,12345,12346,20034... #UDP_PORTS="1,7,9,69,161,162,513,640,700,32770,32771,32772,32773,32774... The first set is quite large; it is intended for a very strict security policy in which any remotely suspicious port will trigger a blocking rule. The second set is more moderate, and the third is minimal, watching only the ports that a remote user can't possibly be contacting unless he's performing a port scan or trying to run an exploit. The middle set, the "if you want to be aware" grouping, is enabled by default. To switch to one of the other two, comment out the middle set and uncomment the one you want. If you like, you can create your own set. Make sure that none of the ports used by your core services are included in this list! For example, port 143 is listed in all three sample sets, but 143 is the IMAP port. If you're running IMAP services, make sure to remove port 143 from the list. If you're not, however, leave it init will trap attackers who try to exploit IMAP-related security flaws. After choosing the ports to be monitored, you must choose a method by which to block suspicious hosts. You can do this through IPFW (if you're running it, as discussed earlier in the chapter) or through blackhole routes (if you're not running IPFW). Choosing a method involves uncommenting a single line beginning with KILL_ROUTE, which specifies the system command that PortSentry should use to block an offending host. For a system running IPFW, uncomment the line in portsentry.conf containing /sbin/ipfw, like so: # For those of you running FreeBSD (and compatible) you can # use their built in firewalling as well. # KILL_ROUTE="/sbin/ipfw add 1 deny all from $TARGET$:255.255.255.255 to any" If you're not using IPFW, use the blackhole route method, which, despite the comments, works just as well as IPFW: # FreeBSD (Not well tested.) KILL_ROUTE="route add -net $TARGET$ -netmask 255.255.255.255 127.0.0.1 -blackhole" After you've enabled a blocking method, PortSentry is ready to run. However, as of this writing, the PortSentry port doesn't come with an automated startup script. You can use the script shown in Listing 30.1 set it to be executable, and copy it into your /usr/local/etc/rc.d directory to start up PortSentry each time your system boots. Listing 30.1. Sample PortSentry Startup Scriptportsentry.sh
Tip While PortSentry is running, you can see which ports it's listening on by using the sockstat command: # sockstat USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS root portsent 2432 0 udp4 *:1 *:* root portsent 2432 1 udp4 *:7 *:* root portsent 2432 2 udp4 *:9 *:* root portsent 2432 3 udp4 *:69 *:* root portsent 2432 4 udp4 *:161 *:* root portsent 2432 5 udp4 *:162 *:* ... Each time PortSentry detects an attack attempt, it lists the host and ports that triggered the detection in /usr/local/etc/portsentry.blocked.tcp for TCP attacks and /usr/local/etc/portsentry.blocked.udp for UDP attacks. PortSentry uses these lists to keep track of which hosts it has already blocked so that it doesn't try to block them again later. You can also use these files to see what hosts have been caught by your attackdetection system. These files are cleared out automatically each time PortSentry starts up. When you reboot, both IPFW and the routing table are cleared of any entries that were added during runtime, so a host that was blocked once will have access to you again if you rebootat least until it tries to probe your ports again. Tip If you're using the IPFW KILL_ROUTE method, view the current blocking rules with ipfw -a list: # ipfw -a list 00001 1 44 deny ip from 209.237.26.165 to any If you're using blackhole routes, use netstat -rn: # netstat -rn Routing tables Internet: Destination Gateway Flags Refs Use Netif Expire ... 209.237.26.165/32 127.0.0.1 UGScB 0 0 lo0 The B flag indicates a "blackhole" route, in which packets are simply discarded. Tip Each time an attack is detected, /var/log/messages receives lines indicating what PortSentry is doing about it:
Another tool from the makers of PortSentry is Logcheck (available in /usr/ports/security/logcheck); it analyzes this and other log files and sends you a daily report on any unusual activity or detected attacks. Caution As with IPFW, be careful when testing PortSentry. It's very easy to trigger an attack detection; if you do, the system from which you're administering your FreeBSD machine becomes blocked. That can happen, for instance, if you telnet to port 1 "just to see what happens." What will happen is that your host will be blocked, and further connection attempts will simply time out. You will have to connect from a different host or the physical console to remove the mistakenly applied rule, either through an ipfw delete 1 or route delete IP-address/32 command. As with IPFW, you can set up a cron job to issue these commands every five minutes to protect against locking yourself out. If you want to protect certain hosts (such as your own machines) from ever being blocked by PortSentry, add their IP addresses to the /usr/local/etc/portsentry.ignore file. Using /etc/hosts.allowThe /etc/hosts.allow file lets you block certain hosts from accessing certain services on your system. This file is like a manual version of PortSentry. You can specify a block of rules for a given service and apply each rule to a certain IP address or set of addresses; each rule either allows or denies matching hosts access to the service. Here's a sample block of rules from the default /etc/hosts.allow file, with a few extra lines added to show sample syntaxes: sendmail : localhost : allow sendmail : .nice.guy.example.com : allow sendmail : .evil.cracker.example.com : deny sendmail : 231.21.15.0/255.255.255.0 : deny sendmail : 12.124.231. : deny sendmail : ALL : allow Because you've seen how IPFW works, the format of these rules is pretty easy to figure out. A rule has at least three fields:
The first two columns can be lists (multiple entries separated by spaces), and the host column can match a variety of different ways: a leading dot to specify an entire DNS subnet or a trailing dot to do the same for an IP address. Separate an IP address and a netmask with a slash to specify a network. The block should end with a "default" rule, specifying whether to allow or deny access to the service by default. Generally, if you're running the service, there's a good reason for it; you'll probably want your default rule to be "allow" so that clients other than ones you've explicitly allowed can access that service. You can use /etc/hosts.allow to specify actions other than simply "allow" and "deny." You can use it to make unauthorized access to a service, trigger an email to you, or execute a program that does some kind of reverse probing against the remote host (although this is probably not a good ideait can be fun to "fight fire with fire," but it's bad form, and dangerous, to stoop to the level of the hacker who attacked you). This file can execute any shell command in response to a match for a given rule. The default rule for the fingerd service shows an example of this type of configuration: fingerd : ALL \ : spawn (echo Finger. | \ /usr/bin/mail -s "tcpd\: %u@%h[%a] fingered me!" root) & \ : deny The %u, %h, and %a codes and additional configuration options are described in man 5 hosts_access and man hosts_options. Using TripwireYou can use intrusion detection to provide security that goes beyond outright blocking of suspicious hosts. A sufficiently wily hacker will be able to get past your security checks, no matter how carefully you set them up. If that happens, you need to be able to see whether he got into the system and caused any damage. If your system has been "owned," you want to know about it as soon as it happens, and the exact extent of the damage. Tripwire, available at /usr/ports/security/tripwire, is a widely used intrusion-detection tool. Tripwire keeps an authenticity record of every program on the system. It compiles an "authoritative" record on your programs when you first run it during installation, and it adds records of new programs when you install them. On a daily basis, Tripwire compares a new record of every program on the system to the authoritative record. If Tripwire detects any differences in the programs (for example, if the sshd executable has suddenly changed size or had its contents or meta-data altered in any way), it notifies you via email. That email gives you an immediate notification that your system has been compromised. When you first install Tripwire, it builds its initial database of program "fingerprints" during the make install phase, and it writes this out into a file in the /var/db/tripwire directory. This file is signed with local and site passphrases that you specify at installation time; therefore, you don't have to worry about the database file being tampered with. If it's modified without your knowledge, Tripwire will warn you that a security breach has occurred at the next time you use it. You must first create a configuration file for Tripwire. This is done with the twadmin utility; in this case, you'll use the m F mode (Create Configuration File), specifying the site keyfile with S and the input configuration file at the end: # twadmin m F S /usr/local/etc/tripwire/site.key /usr/local/etc/tripwire/twcfg.txt Please enter your passphrase: Wrote configuration file: /usr/local/etc/tripwire/tw.cfg From now on, you can have the system run TRipwire every night in the periodic tasks (you learned about these tasks in Chapter 15, "Performance Monitoring, Process Control, and Job Automation"). When TRipwire is run with the --check argument, it operates in integrity-check mode, scanning all the files specified in /usr/local/etc/tripwire/twpol.txt for mismatches against the database of file fingerprints. If any inconsistencies are found, it reports them, as with this example, in which the file modification time of /usr/sbin/sshd has been changed: # tripwire --check ... ============================================================================== Rule Summary: ============================================================================== ------------------------------------------------------------------------------ Section: UNIX File System ------------------------------------------------------------------------------ Rule Name Severity Level Added Removed Modified --------- -------------- ----- ------- -------- Invariant Directories 66 0 0 0 Sources 100 0 0 0 Temporary directories 33 0 0 0 Tripwire Data Files 100 0 0 0 Local files 100 0 8 0 Tripwire Binaries 100 0 0 0 Libraries, include files, and other system files 100 0 0 0 * System Administration Programs 66 0 0 1 User Utilities 100 0 0 0 X11R6 100 0 0 0 NIS 100 0 0 0 (/var/yp) /etc 100 0 0 0 Security Control 100 0 0 0 Root's home 100 0 0 0 FreeBSD Kernel 100 0 0 0 FreeBSD Modules 100 0 0 0 /dev 100 0 0 0 Linux Compatibility 100 0 0 0 (/compat) Total objects scanned: 466299 Total violations found: 1 It may well be that you expect this file to be different from what Tripwire expects; you may have installed an updated version of sshd, for example. Whenever you update files that Tripwire is monitoring, you should update the Tripwire database to reflect the new information. You can update it with the --update option: # tripwire --update This command reruns the entire Tripwire database-generation process, which scans the entire filesystem and writes out an updated database file signed with your site and local passphrases (for which you are prompted when you run the program). Caution Be sure to update your Tripwire database only if you know the system is uncompromised! You don't want to pollute the database with information that says your already-compromised files are the gold standard against which future versions are compared. The best policy is to remove the system from the network, reboot, run a Tripwire scan to verify that your system is clean based on its known information, and then update the Tripwire database. If you really want to make sure your Tripwire database is secure, and you don't even trust the built-in signing mechanism that protects it, you can create a Tripwire floppy diskplacing the database in a separate location from the computer is the most secure method of all to ensure data integrity. Unfortunately, a Tripwire database is too big to fit on a floppy; however, you can remove items from the Tripwire "policy" to make the database file smaller. Do this by editing /usr/local/etc/tripwire/twpol.txt, removing or commenting-out the lines specifying file locations you don't want, and then creating the actual (non-human-readable) policy file by issuing the twadmin command with the m P (or --create-polfile) argument: # twadmin m P S /usr/local/etc/tripwire/site.key /usr/local/etc/tripwire/twpol.txt Then, when the database file that results from another tripwire --update run is less than 1.44MB in size, you can go to /usr/ports/security/tripwire and use the make floppy command to automatically create a floppy disk with the Tripwire database file and the associated tools copied to it. You should note, however, that going to the length of creating a Tripwire floppy disk is considered completely unnecessary today, now that the local database files are themselves protected, and the make floppy command is being deprecated and might not be available on your system. Another option, naturally, is to use a writable CD or DVD for your offline Tripwire database. You'll have to create this disc manually, though, without the aid of Tripwire's tools.
If You Think You've Been Hacked...As you learned earlier, you should assume that your systemno matter how securewill be hacked at some point. Although Tripwire and PortSentry can take a great deal of the drudgery of intrusion prevention and detection off your shoulders, you should still be on the alert for subtle and subjective changes in how the system behaves. Here are some simple ways you can monitor your system's security:
In short, be constantly on the lookout for anything out of the ordinary. Such ad-hoc watchfulness is sometimes the only way to notice that your system isn't behaving the way it should. Note A favorite place to find evidence of hacker activity is in /dev. That's where packet-sniffing tools are often placed by intruders running prepackaged "rootkits" or scripts. However, because FreeBSD now uses a dynamically generated DEVFS device filesystem, this is less of a worrybut it still doesn't hurt to keep an eye out. If you do suspect that you've been hacked (and especially if you find any evidence of it), you must assume that the damage is greater than it appears. The most common mistake for an administrator to make who has discovered evidence of a security breach is to simply disable a few services and assume that the attacker has gone away. Often, this may be the case; however, treating all such incidents in this manner is an invitation to disaster. All it takes is for the attacker to have installed a "backdoor" of some kind that lets him return and cause much more destructive damage than before. If you suspect you have been hacked, or "owned," here are some steps you must take:
|