Psionic PortSentry

   

One of the most common precursors to a network attack is a portscan. Portscans (discussed in Chapter 20, "Disaster Planning and Recovery") test remote sites for open ports, and can be used to identify potential vulnerabilities and even use the responses to determine the remote operating system. Attackers typically scan entire subnets, locate potential targets, then mount a real attack using known service exploits. PortSentry detects many types of stealth portscans, and can be used to provide quick and dirty protection on individual systems or a firewall. This provides very basic intrusion detection, is extremely simple to set up and configure, and provides an excellent starting point for exploring intrusion detection options on your Mac OS X system.

NOTE

At the time of this writing, PortSentry 2.0 was in beta testing, and requires a few tweaks in compilation/configuration to work correctly on Mac OS X. I highly recommend reading the README.install file included in the source distribution because it is likely that there will be differences between the instructions provided here and the latest version available.

Installing PortSentry

To start, download PortSentry 2.0 from Psionic (shortly to be owned by Cisco Systems) at http://www.macosxunleashed.com/downloads. Be sure to download the 2.0 version; PortSentry 1.0 installs and works on Mac OS X, but does not support stealth scan detection on our favorite platform. As stealth scans are the bread and butter of attackers, their detection is critical for any semblance of security. Unarchive and enter the source distribution directory after downloading the archive.

 %  curl -O "http://www.macosxunleashed.com/downloads/portsentry-2.0b1.tar.gz"  %  tar zxf portsentry-2.0b1.tar.gz   % cd portsentry-2.0b1  

Next , attempt to compile the software by typing make bsd . At this point in the current distribution, the compile will fail with errors detecting a nonexistent ip_ether.h header file. Assuming the errors are still present, edit portsentry.h , looking for these lines:

 #ifdef BSD         #include <netinet/in_systm.h>         #include <netinet/ip_ether.h> #endif 

Comment out the line #include <netinet/ip_ether.h> by adding the prefix // :

 #ifdef BSD         #include <netinet/in_systm.h> //      #include <netinet/ip_ether.h> #endif 

Now, try the compile process ( make bsd ) once again:

 %  make bsd  SYSTYPE=bsd Making cc -O -Wall -DBSD44 -o ./portsentry ./portsentry.c \         ./portsentry_io.c ./portsentry_util.c -lpcap 

Finally, type make install (as root) or sudo make install to install the software in /usr/local/psionic/portsentry2 :

 #  make install  Creating psionic directory /usr/local/psionic Setting directory permissions Creating portsentry directory /usr/local/psionic/portsentry2 Setting directory permissions chmod 700 /usr/local/psionic/portsentry2 Copying files cp ./portsentry.conf /usr/local/psionic/portsentry2 cp ./portsentry.ignore /usr/local/psionic/portsentry2 cp ./portsentry /usr/local/psionic/portsentry2 Setting permissions chmod 600 /usr/local/psionic/portsentry2/portsentry.ignore chmod 600 /usr/local/psionic/portsentry2/portsentry.conf chmod 700 /usr/local/psionic/portsentry2/portsentry Edit /usr/local/psionic/portsentry2/portsentry.conf and change your settings if you haven't already. (route, etc) 

Configuring PortSentry

To finish the PortSentry setup, you must configure it to recognize your network interface and the ports that you want to monitor for scans. Currently PortSentry is limited to monitoring only specific ports; by the time you read this, it should be capable of monitoring a port range (a feature available in the 1.0 release).

Open the config file, /usr/local/psionic/portsentry2/portsentry.conf , now. We'll work our way through the file starting at the top.

First, set the network interface that will be monitored and the IP address of the interface by using the INTERFACE and INTERFACE_ADDRESS options, respectively. By default, the INTERFACE is set to auto , which automatically detects your primary interface. If you have multiple active interfaces, you can choose which PortSentry will monitor by specifying them in a comma separated list, such as en0, en1 . The INTERFACE_ADDRESS should be set to the IP address of your active network interface:

 ########################### # Interface Configurations# ########################### # You can set the interface to monitor with this option. Examples include # "eth0", "ep0", etc. You do not need to put in the dev directory path. # If you leave this as "auto" PortSentry will attempt to monitor the # primary interface automatically. Most people should leave this alone # unless you have a multi-homed system (firewall, etc.) and want to monitor # a particular interface only.  INTERFACE="auto"  # This MUST BE SET to the address of the interface being monitored on # your system. It is NOT determined automatically in this version of # PortSentry.  INTERFACE_ADDRESS="10.0.1.101"  

Next, provide a list of ports to monitor with the TCP_PORTS and UDP_PORTS directives. In the current software, there is a low limit on the number of ports that the Mac OS X libpcap packet filter can handle, so you'll probably need to remove some of the monitored ports from the default values included in the file.

 ####################### # Port Configurations # ####################### # # # Some example port configs for stealth modes # # We like to always keep some ports at the "low" end of the spectrum. # This will detect a sequential port sweep really quickly and usually # these ports are not in use (i.e. tcpmux port 1) # # Use these if you just want to be aware (default):  TCP_PORTS="1,11,15,79,111,119,143,515,540,635,666,1080,   1524,2000,6667,12345,12346"   UDP_PORTS="1,7,9,69,161,162,513,635,2049,27444"  

Although the port list is arbitrary, the monitor is most effective if the ports are those of commonly exploited services, or ports left open by such things as Trojan horses. They should not overlap any services that are running and actively serving information on your computer (such as port 80 if you're running a Web server).

Next, if desired, you can change the location of the ignore, history, and blocked files. These three files are used by PortSentry to determine what hosts should never be blocked, where a history (log) of portscans should be stored, and finally, where a list of the currently blocked hosts should be stored. By default, these files are stored in /usr/local/psionic/portsentry2/portsentry.ignore , /usr/local/psionic/portsentry2/portsentry.history , and /usr/local/psionic/portsentry2/portsentry.blocked , respectively.

 ###################### # Configuration Files# ###################### # # Hosts to ignore  IGNORE_FILE="/usr/local/psionic/portsentry2/portsentry.ignore"  # Hosts that have been denied (running history)  HISTORY_FILE="/usr/local/psionic/portsentry2/portsentry.history"  # Hosts that have been denied this session only (temporary until next restart)  BLOCKED_FILE="/usr/local/psionic/portsentry2/portsentry.blocked"  

PortSentry, like other software, such as Apache, won't log hostnames for attacking machines ”just IP addresses. This is standard practice because name resolution can drastically slow things down, potentially resulting in a DoS attack on PortSentry itself. If you want to enable name resolution, change RESOLVE_HOST="0" to RESOLVE_HOST="1" .

 ############################## # Misc. Configuration Options# ############################## # # DNS Name resolution - Setting this to "1" will turn on DNS lookups # for attacking hosts. Setting it to "0" (or any other value) will shut # it off. Turning on this value can slow down PortSentry if a lot of attacks # are coming in concurrently while it waits for the DNS resolution to return. # This option can can also alert an attacker to PortSentry's presence if they # see DNS queries come to a nameserver they control after they initiate an # attack. The default is to keep this off.  RESOLVE_HOST = "0"  

The most powerful aspect of an intrusion detection system is the ability to react to attacks rather than simply log them. PortSentry can react to scans by logging, blocking them with TCP Wrappers, running an arbitrary command, or using the Mac OS X firewall to stop the attacking traffic. Firewall rules are more strict than TCP Wrappers; they are capable of blocking all traffic from a remote system and don't require the server process to execute through xinetd / inetd , nor do they support TCP Wrappers.

When processing an attack, three variables are made available for passing to external commands:

  • $TARGET$ . The address of the computer that is attacking.

  • $PORT$ . The port that triggered the attack response.

  • $MODE$ . The type (UDP or TCP) of scan.

The first step in setting up your defense is choosing how PortSentry will respond to TCP and UDP scans, which you do by setting BLOCK_UDP or BLOCK_TCP to a value between 0 and 2. You can choose to simply log the scans (0), block them (1), or run an external command of your choice (2). For our purposes, we'll be blocking hosts that perform scans.

 ################## # Ignore Options # ################## # These options allow you to enable automatic response # options for UDP/TCP. This is useful if you just want # warnings for connections, but don't want to react for # a particular protocol (i.e. you want to block TCP, but # not UDP). To prevent a possible Denial of service attack # against stealth scan detection for TCP, you may # want to disable blocking, but leave the warning enabled. # We personally would wait for this to become a problem before # doing though as most attackers really + command # in case of a scan to have a pager script or such execute # but not drop the route. This may be useful for some admins # who want to block TCP, but only want pager/e-mail warnings # on UDP, etc.# # # 0 = Do not block UDP/TCP scans. # 1 = Block UDP/TCP scans. # 2 = Run external command only (KILL_RUN_CMD)  BLOCK_UDP="1"   BLOCK_TCP="1"  

Next, set the KILL_ROUTE variable to the ipfw command to execute upon an attack. There are a few dozen preset KILL_ROUTE options already entered in the file. Be sure to use the one for FreeBSD: /sbin/ipfw add 1 deny all from $TARGET$/32 to any . This will force all traffic from the remote host to be blocked.

NOTE

If you'd like to be a bit more lenient on the attacker, you can, instead, choose to block only traffic to the port that triggered the attack. To do this, change the KILL_ROUTE to /sbin/ipfw add 1 deny $MODE$ from $TARGET$/32 to any $PORT$ .

 ################### # Dropping Routes:# ################### # This command is used to drop the route or add the host into # a local filter table. # # The gateway (XXX.XXX.XXX.XXX) should ideally be a dead host on # the *local* subnet. On some hosts you can also point this at # localhost (127.0.0.1) and get the same effect. NOTE THAT # XXX.XXX.XXX.XXX WILL *NOT* WORK. YOU NEED TO CHANGE IT!! # # ALL KILL ROUTE OPTIONS ARE COMMENTED OUT INITIALLY. Make sure you # uncomment the correct line for your OS. If your OS is not listed # here and you have a route drop command that works then please # mail it to us so we can include it. ONLY ONE KILL_ROUTE OPTION # CAN BE USED AT A TIME SO DON'T UNCOMMENT MULTIPLE LINES. # # NOTE: The route commands are the least optimal way of blocking # and do not provide complete protection against UDP attacks and # will still generate alarms for both UDP and stealth scans. We # always recommend you use a packet filter because they are made # for this purpose. # # For those of you running FreeBSD (and compatible systems) you can # use their built-in firewalling as well. # KILL_ROUTE="/sbin/ipfw add 1 deny all from $TARGET$/32 to any" 

Next, if you want to add the blocked hosts to your TCP Wrappers file, configure the KILL_HOSTS_DENY line with what should be added to the /etc/hosts.deny TCP Wrapper file. The default value should be fine and will result in the line ALL: <ip address> being added to the wrapper file to deny access to all services.

 ############### # TCP Wrappers# ############### # This text will be dropped into the hosts.deny file for wrappers # to use. There are two formats for TCP wrappers: # # Format One: Old Style - The default when extended host processing # options are not enabled. #  KILL_HOSTS_DENY="ALL: $TARGET$"  

We're close to wrapping things up! If you choose to run an arbitrary command in response to a scan (to send an email or perform some other action), you can set that command by using the KILL_RUN_CMD option, and choose whether it should run before it is blocked by the firewall or after by setting KILL_RUN_CMD_FIRST to 1 or 0, respectively.

 ################### # External Command# ################### # This is a command that is run when a host connects, it can be whatever # you want it to be (pager, etc.). This command is executed before the # route is dropped or after depending on the KILL_RUN_CMD_FIRST option below# # # WE NEVER RECOMMEND YOU PUT IN RETALIATORY ACTIONS AGAINST THE HOST SCANNING # YOU! # # TCP/IP is an *unauthenticated protocol* and people can make scans appear out # of thin air. Do you really want to counter-attack an innocent third party? # That could happen if you aren't careful. # # The KILL_RUN_CMD_FIRST value should be set to "1" to force the command # to run *before* the blocking occurs and should be set to "0" to make the # command run *after* the blocking has occurred. # #KILL_RUN_CMD_FIRST = "0" # # #KILL_RUN_CMD="/some/path/here/script $TARGET$ $PORT$ $MODE$" 

Finally, choose the number of connects that constitute a "connect." A value of 0, the default, reacts immediately, even if a single port is scanned. If you find that you're blocking too many hosts, you may wish to raise this value.

 ##################### # Scan trigger value# ##################### # Enter in the number of port connects you will allow before an # alarm is given. The default is 0 which will react immediately. # A value of 1 or 2 will reduce false alarms. Anything higher is # probably not necessary. This value must always be specified, but # generally can be left at 0. # SCAN_TRIGGER="0" 

Setting Up the PortSentry Ignored Hosts

Before starting PortSentry, you should edit the /usr/local/psionic/portsentry2/portsentry.ignore file to include the IP addresses and subnets that should never trigger an attack. Be sure to leave the default values in the example file because they will prevent your machine from detecting an attack from itself.

Addresses should be added to the file in the form < IP address> / <mask> . For example, a Class C subnet of 192.168.1.xxx could be entered as 192.168.1.0/24 . Individual hosts can simply be entered as the IP address with no mask; a 32-bit subnet mask will be assumed.

Starting and Testing PortSentry

To start PostSentry, simply start the daemon from the command line as root:

 # /usr/local/psionic/portsentry2/portsentry 

You should be able to check /var/log/system.log and verify that the PortSentry process has indeed started:

[View full width]
 
[View full width]
Nov 7 01:33:56 portsentry[2408]: Monitoring interface en1 and address: 10.0.1.101 Nov 7 01:33:56 portsentry[2408]: Initializing PortSentry BPF filters. Nov 7 01:33:56 portsentry[2408]: Monitoring TCP ports: 1,11,15,79,111,119,143,515,540, graphics/ccc.gif 635,666,1080,1524,2000,6667,12345,12346 Nov 7 01:33:56 portsentry[2408]: Monitoring UDP ports: 1,7,9,69,161,162,513,635,2049, graphics/ccc.gif 27444 Nov 7 01:33:56 portsentry[2408]: PortSentry is initialized and monitoring.

To verify that PortSentry is working, log into another machine and use a portscanner (or simply attempt to Telnet into a monitored port) to "attack" the protected computer. Monitor your /var/log/system.log file to verify that the scan is detected and blocked:

[View full width]
 
[View full width]
Nov 7 01:38:38 portsentry[951]: attackalert: TCP SYN scan from host 10.0.1.250/10.0.1. graphics/ccc.gif 250 to TCP port: 1 from TCP port: 50427 Nov 7 01:38:38 portsentry[951]: attackalert: Host 10.0.1.250 has been blocked via graphics/ccc.gif wrappers with string: "ALL: 10.0.1.250"

In this example, a scan is initiated from the host 10.0.1.250 to the PortSentry monitored machine. The scan is detected as soon as it hits port 1, is blocked, and subsequent scans are blocked. Remember that a history of scans is stored in /usr/local/psionic/portsentry2/portsentry.history , while the details are logged with syslog . For more information on ipfw and how to manually add or remove blocks, see Chapter 17, "Blocking Network Access."

Your computer is now running an "entry-level" intrusion detection system, capable of recognizing and transparently dealing with potential attackers scanning your system.

To start PortSentry at boot-time, create a new folder named Portsentry in /Library/StartupItems . Add two files: StartupParameters. plist and Portsentry into the folder StartupParameters.plist:

 {   Description     = "Portsentry Portscan Detection";   Provides        = ("PSDetection");   Requires        = ("Resolver");   OrderPreference = "Last";   Messages =   {     start = "Starting Portsentry";   }; } 

and Portsentry:

 #!/bin/sh ## # Start Portsentry ## . /etc/rc.common if [ "${PORTSENTRY:=-NO-}" = "-YES-" ]; then     ConsoleMessage "Starting Portsentry Portscan Detection"    cd /usr/local/psionic/portsentry2    ./portsentry & fi 

Finally, add the line PORTSENTRY=-YES- to /etc/hostconfig to turn the automatic startup on.


   
Top


Mac OS X Maximum Security
Maximum Mac OS X Security
ISBN: 0672323818
EAN: 2147483647
Year: 2003
Pages: 158

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net