connections to the honeypot and only allow outbound icmp echo requests, tcp 21 (FTP, active), tcp/udp 53 (DNS), tcp 80 (HTTP), and tcp 6667 (IRC). I take the previous measures to bring down my liability yet try not to raise suspicion from the attacker. The second logging facility on the bridge, pf being the first, will be Snort, a powerful sniffer and IDS. The third and final logging facility will be the trusty tcpdump. It will capture full packet dumps going to and from the ip of the honeypot. Data control from the honeypot is also controlled on the bridge. Refer the paper about data control for honeypots at The Honeynet Project. Thanks to the Brazil team of the Honeynet Research Alliance I can use a tool specifically developed for OpenBSD’s pf for data control calledsessionlimit. After compromise of the honeypot it will interact with pf in order to contain activity of the intruders. There is no way I can guarantee that the intruders will not indulge in malicious activity but I hope to limit that possibility with this tool. The interface on the bridge with the public ip will be used strictly for remote management purposes. This interface will be packet filtered to only allow SSH connections from specific ips and only allow outbound HTTP traffic to update Snort rules and email notification of said updated rules.
The Configuration |
pf=YES portmap=NO inetd=NO ntpd=NO |
Enable packet forwarding in /etc/sysctl.conf so upon reboot it is enabled:
net.inet.ip.forwarding=1 # 1=Permit forwarding (routing) of packets |
Create /etc/hostname.rl0:
# echo up > /etc/hostname.rl0 |
Create /etc/hostname.rl1:
# echo up > /etc/hostname.rl1 |
rl2 will get its public address assigned via DHCP from the ISP:
# echo dhcp NONE NONE NONE > /etc/hostname.rl2 |
Create /etc/bridgename.bridge0:
# echo add rl0 add rl1 up > /etc/bridgename.bridge0 |
The pf configuration file, /etc/pf.conf, needs to be created, here’s my end result:
# pf.conf ruleset # # to view the logfiles: # tcpdump -n -e -ttt -r /var/log/pflog # # to tail -f the logfile: # tcpdump -n -e -ttt -i pflog0 # VARIABLES # my mgmt interface. pf can interpret interface as an ip # very practical for dynamic ips mgmtif="rl2" # these interfaces do not have an ip stack outif="rl0" inif="rl1" # remote management ip addresses mgmtips ="{ x.x.x.x/32, x.x.x.x/32 }" # honeypot public ip honeypot ="x.x.x.x/32" # honeypot allowed TCP outbound services allowed_svcs_tcp="{ ftp, domain, www, ircd }" # honeypot allowed UDP outbound services allowed_svcs_udp="{ domain, bootps }" # http://www.iana.org/assignments/ipv4-address-space # http://rfc.net/rfc1918.html reserved ="{ 0.0.0.0/8, 10.0.0.0/8, 20.20.20.0/24, 127.0.0.0/8, 169.254.0.0/16, 172.16.0.0/12, 192.0.2.0/24, 192.168.0.0/16, 204.152.64.0/23, 224.0.0.0/3, 255.255.255.255 }" # SPOOFERS # don't allow spoofed reserved addresses block in quick on $outif from $reserved to any block out quick on $outif from $honeypot to $reserved # block and log outgoing packets that don't have honeypot address as source block out log quick on $outif from ! $honeypot to any # DEFAULT POLICY # filtering on the bridge will be done on the outside (rl0) interface # predetermined svc's from the honeypot will be allowed out individually block out log on $outif all # everything is allowed in to the honeypot pass in on $outif all keep state # only ssh will be allowed to the mgmt interface block in log on $mgmtif all # only smtp, domain, and http will be allowed out from the mgmt interface block out log on $mgmtif all # NOISE # noise from my cable modem segment that is silently dropped block in quick on $mgmtif inet from any to { 255.255.255.255, 224.0.0.1 } # HONEYPOT OUTBOUND CONNECTIONS pass out log quick on $outif inet proto tcp from $honeypot to any port $allowed_svcs_tcp flags S/SA keep state pass out log quick on $outif inet proto udp from $honeypot to any port $allowed_svcs_udp keep state pass out log quick on $outif inet proto icmp from $honeypot to any icmp-type 8 code 0 keep state # REMOTE MANAGEMENT CONNECTIONS pass in log quick on $mgmtif inet proto tcp from $mgmtips to $mgmtif port ssh keep state pass out quick on $mgmtif inet proto tcp from $mgmtif to any port { smtp, domain, http } flags S keep state pass out quick on $mgmtif inet proto udp from $mgmtif to any port domain keep state
|
Snort was next. First, I created a user snort with a login of /sbin/nologin. Then I downloaded Snort 1.9.0, compiled it, and tweaked the snort.conf file to fit my needs. I also installed oinkmaster. Oinkmaster is a perl script to update Snort rules from the latest ruleset available on snort.org. I unpacked the tar.gz in /home/snort and then added an entry to snort’s crontab to update the rules every day at 3:00 PM. The output from oinkmaster, which is any rule that is deleted, modified, or added, is then emailed to me if there are any changes. Here is the crontab entry:
0 15 * * * cd $HOME/oinkmaster-0.6 ; TMP=`mktemp /tmp/oinkmaster.XXXXX` && (./oinkmaster.pl -o $HOME/rules/ -q -c > $TMP 2>&1; if [ -s $TMP ]; then mail -s "Snort Oinkmaster Update `date +%m-%d-%Y`" me@foo.bar < $TMP; fi; rm $TMP) |
Next is data control with sessionlimit. It will monitor the state table (Note: outgoing traffic needs to have keep state) and block honeypot connections outbound when 1) the number of states associated with the honeypot increases too fast, 2) when the honeypot makes more than 20 connections, and 3) when the number of bytes associated with an ICMP state has reached a predefined limit – the default is 65k (a la lame ping -f DoS). Keep in mind the attacker’s interactive session with the honeypot won’t be affected, only new outbound connections. After 30 minutes, the sessionlimit rule added to pf will expire. All of this is logged to syslog. Since we are about to go live, we will start up sessionlimit manually:
# /usr/local/bin/sessionlimit -H x.x.x.x -i rl1 & |
Enable packet forwarding now:
# sysctl -w net.inet.ip.forwarding=1 |
Manually initialize interfaces, bring up the bridge, and grab an ip for rl2:
# ifconfig rl0 delete # ifconfig rl1 delete # brconfig bridge0 add rl0 add rl1 up # dhclient rl2 |
Make sure all of the interfaces and the bridge are up and configured correctly:
# ifconfig rl0 # ifconfig rl1 # ifconfig rl2 # brconfig bridge0 |
Enable pf and load rules:
# pfctl -e # /sbin/pfctl -R /etc/pf.conf |
Manually start Snort:
# /home/snort/snort-1.9.0/src/snort -i rl1 -deq -h x.x.x.x/32 -l /home/snort/log -c /home/snort/rules/snort.conf -D |
Lastly, I run tcpdump by hand on rl1 to capture all traffic from my honeypot’s ip. A useful switch that was added in tcpdump 3.7.1 is -C which rotates the saved file every optarg * 1,000,000 bytes. This way I won’t have to load up an enormous file in ethereal, just makes analysis a little more manageable:
# tcpdump -i rl1 -n -s 1500 -C 2 -w /var/log/tcpdump/tcpdump.log host x.x.x.x & |
For easy startup of Snort, tcpdump, and sessionlimit, I created a wrapper script called honeypot-wrapper. This way I only have to call the wrapper script and pass the honeypot ip as an argument to start these three services:
#!/bin/sh # snort, tcpdump, sessionlimit startup for honeypot SNORT=/home/snort/snort-1.9.0/src/snort CONFIG=/home/snort/rules-1.9.0/snort.conf SNORTLOG=/home/snort/log TCPDUMP=/usr/local/bin/tcpdump TCPDUMPLOG=/var/log/tcpdump/tcpdump.log SESSIONLIMIT=/usr/local/bin/sessionlimit if [ -n "$1" ]; then ip=$1 else echo -n "Usage: `basename $0` (honeypot ip)n" exit fi if [ -x $SNORT ]; then echo -n " Snort starting...n" $SNORT -i rl1 -g snort -u snort -deq -h $ip/32 -l $SNORTLOG -c $CONFIG -D >/dev/null 2>&1 fi if [ -x $TCPDUMP ]; then echo -n " Tcpdump starting...n" $TCPDUMP -i rl1 -n -s 1500 -C 2 -w $TCPDUMPLOG host $ip & >/dev/null 2>&1 fi if [ -x $SESSIONLIMIT ]; then echo -n " Sessionlimit starting...n" /usr/local/bin/sessionlimit -H $ip -i rl1 & >/dev/null 2>&1 fi
|
The Deployment |
#!/bin/sh grep -v 'spp' ~snort/log/alert | grep '[**]' | sort | uniq -c |
Here is the output:
# ./summary 9 [**] [1:1227:4] X11 outbound client connection detected [**] 3 [**] [1:1394:3] SHELLCODE x86 NOOP [**] 5 [**] [1:1418:2] SNMP request tcp [**] 4 [**] [1:1420:2] SNMP trap tcp [**] 4 [**] [1:1421:2] SNMP AgentX/tcp request [**] 1 [**] [1:1810:1] MISC Successful Gobbles SSH exploit [**] 1 [**] [1:1812:1] MISC Gobbles SSH exploit attempt [**] 1 [**] [1:249:1] DDOS mstream client to handler [**] 5 [**] [1:469:1] ICMP PING NMAP [**] 7 [**] [1:474:1] ICMP superscan echo [**] 1 [**] [1:498:3] ATTACK RESPONSES id check returned root [**] 1 [**] [1:587:2] RPC portmap request status [**] 1 [**] [1:598:5] RPC portmap listing [**] 9 [**] [1:618:2] SCAN Squid Proxy attempt [**] 3 [**] [1:628:1] SCAN nmap TCP [**] |
Sure enough, someone took the bait after just 2 days, compromising the honeypot using the Gobbles SSH exploit.
Conclusion |
To Do |