DESIGNING OF A HONEYNET

The network setup for this project is fairly simple:

The bridge is completely transparent to the attacker – they have no knowledge that they are passing through this machine. Therefore, it makes for an excellent machine to carry out the network logging between the honeypot and the internet. I will use the OpenBSD 3.1 native packet filtering tool, pf, to allow all inbound
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
First I configured the OpenBSD bridge. When I refer to interfaces they are set up as follows – rl0 is the interface without an ip connected to the internet, rl1 is the interface without an ip connected to the honeypot, and rl2 is the interface with a public ip for remote management purposes connected to the internet.
Changes to /etc/rc.conf:
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
The OS I chose for my first honeypot is OpenBSD 3.1 vanilla. There isn’t much to explain here – just install the OS and connect the honeypot to the bridge. With everything up and humming along now, all I have to do is sit back and wait for someone to take the bait. I have ssh access to the bridge’s management interface so I can log in from my management ip’s and look at the alert file in /home/snort/log/alert. I actually created a quick and dirty script in the ~snort directory to see a summary of attacks:
#!/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
This complete setup, which included getting the right hardware together, took me a few hours here and a few hours there over the course of a weekend. I am using old hardware – a Pentium 133MHz for the OpenBSD bridge and a Pentium 166MHz as the honeypot. After my setup was up and running smoothly I was overall pretty pleased with the honeynet design I had chosen, both in its simplicity and elegance.
To Do
Run Snort under DJB’s daemontools. chroot() Snort. chroot() and run as non-root tcpdump.
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s