Snort and Barnyard and Base and Swatch on Mountain Lion OS X Server
An intrusion prevention and detection system (IPS/IDS) is a must-have if you run a server. I've installed a snort/barnyard/base/swatch system on Mountain Lion OS X Server and post the step-by-step below. There are significant enough changes in both snort and and Mountain Lion that a thorough rework of the previous solution for Lion Server <https://discussions.apple.com/thread/3370709?start=0&tstart=0> is necessary.
Involved, but the payoff is an effective IPS/IDS that includes features like emailing Level I alerts to ad admin account and a World Map of attacks. Here's a map of attacks on my server occurring over the last couple days:
It's also possible to drill down and see, e.g., specific ssh attacks:
< Src IP address > | FQDN | Sensor # | < Total # > | < Unique Alerts > | < Dest. Addr. > | |
14.0.19.33 | dcenter.cuocsongmoi.vn | 1 | 2 | 1 | 1 | |
189.26.255.11 | 189.26.255.11.static.gvt.net.br | 1 | 1 | 1 | 1 | |
112.116.125.138 | 138.125.116.112.broad.km.yn.dynamic.163data.com.cn | 1 | 1 | 1 | 1 | |
175.136.230.54 | Unable to resolve address | 1 | 1 | 1 | 1 | |
10.0.1.114 | sts-ipad.domainname.com | 1 | 5 | 1 | 1 | |
90.80.92.217 | 217-92.80-90.static-ip.oleane.fr | 1 | 1 | 1 | 1 | |
109.3.134.102 | 102.134.3.109.rev.sfr.net | 1 | 1 | 1 | 1 | |
112.114.63.139 | 139.63.114.112.broad.km.yn.dynamic.163data.com.cn | 1 | 2 | 1 | 1 | |
123.138.30.219 | Unable to resolve address | 1 | 9 | 1 | 1 | |
189.4.1.213 | bd0401d5.ctb.static.virtua.com.br | 1 | 1 | 1 | 1 | |
202.46.14.104 | Unable to resolve address | 1 | 10 | 1 | 1 |
This is what's being built:
snort: IPS/IDS that watches all packets on en0, saves alerts in its own database
barnyard: Asynchronously copies the snort alert database into a PostGreSQL db
base: Web interface viewer for the PostGreSQL db
swatch: Log file watcher for Level 1 alerts
Preliminaries
I'm assuming you've installed Xcode and MacPorts for Lion. I use vi to edit, others prefer nano or emacs. Your choice.
Snort and Barnyard
# Build snort -- see http://www.snort.org/snort-downloads for latest versions
# Do NOT use macports snort or base, but DO use snort's dependencies from macports
sudo port install daq libdnet
curl -O -L http://www.snort.org/dl/snort-current/snort-2.9.3.1.tar.gz
curl -O -L http://www.snort.org/dl/snort-current/snort-2.9.3.1.tar.gz.sig
gpg --verify snort-2.9.3.1.tar.gz.sig snort-2.9.3.1.tar.gz
tar xzfvp ./snort-2.9.3.1.tar.gz
cd snort-2.9.3.1
./configure --enable-ipv6 --enable-gre --enable-mpls --enable-targetbased --enable-decoder-preprocessor-rules --enable-ppm --enable-perfprofiling --enable-zlib --enable-active-response --enable-normalizer --enable-reload --enable-react --enable-flexresp3
make && sudo make install
# Use latest rules from snort.org
# Register at snort.org and download latest ruleset: snortrules-snapshot-2931.tar.gz, snortrules-snapshot-2931.tar.gz.md5.txt
openssl md5 snortrules-snapshot-2931.tar.gz
cat snortrules-snapshot-2931.tar.gz.md5
tar -xzvf snortrules-snapshot-2931.tar.gz
sudo rsync -va --del ./etc /etc/snort
sudo rsync -va --del ./preproc_rules /etc/snort
sudo rsync -va --del ./rules /etc/snort
sudo rsync -va --del ./so_rules /etc/snort
sudo chown -R root:wheel /etc/snort
# Modify snort.conf and syslog.conf
sudo vi /etc/snort/snort.conf
var RULE_PATH rules
var SO_RULE_PATH so_rules
var PREPROC_RULE_PATH preproc_rules
var WHITE_LIST_PATH /etc/snort/rules
var BLACK_LIST_PATH /etc/snort/rules
preprocessor sfportscan: proto { all } \
memcap { 10000000 } \
scan_type { all } \
sense_level { low }
output unified2: filename snort.u2, limit 128
include $RULE_PATH/file-office.rules
include $RULE_PATH/file-other.rules
include $RULE_PATH/file-pdf.rules
include $RULE_PATH/indicator-compromise.rules
include $RULE_PATH/indicator-obfuscation.rules
include $RULE_PATH/policy-multimedia.rules
include $RULE_PATH/policy-other.rules
include $RULE_PATH/policy-social.rules
include $RULE_PATH/pua-p2p.rules
include $RULE_PATH/pua-toolbars.rules
include $RULE_PATH/server-mail.rules
include $PREPROC_RULE_PATH/preprocessor.rules
include $PREPROC_RULE_PATH/decoder.rules
include $PREPROC_RULE_PATH/sensitive-data.rules
include $SO_RULE_PATH/bad-traffic.rules
include $SO_RULE_PATH/chat.rules
include $SO_RULE_PATH/dos.rules
include $SO_RULE_PATH/exploit.rules
include $SO_RULE_PATH/icmp.rules
include $SO_RULE_PATH/imap.rules
include $SO_RULE_PATH/misc.rules
include $SO_RULE_PATH/multimedia.rules
include $SO_RULE_PATH/netbios.rules
include $SO_RULE_PATH/nntp.rules
include $SO_RULE_PATH/p2p.rules
include $SO_RULE_PATH/smtp.rules
include $SO_RULE_PATH/snmp.rules
include $SO_RULE_PATH/specific-threats.rules
include $SO_RULE_PATH/web-activex.rules
include $SO_RULE_PATH/web-client.rules
include $SO_RULE_PATH/web-iis.rules
include $SO_RULE_PATH/web-misc.rules
sudo touch /etc/snort/rules/white_list.rules
sudo touch /etc/snort/rules/black_list.rules
sudo mkdir /usr/local/lib/snort_dynamicrules
# Create org.snort.Snort.plist
sudo vi /Library/LaunchDaemons/org.snort.Snort.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>org.snort.Snort</string>
<key>KeepAlive</key>
<true/>
<key>RunAtLoad</key>
<true/>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/snort</string>
<string>-D</string>
<string>-d</string>
<string>-e</string>
<string>-i</string>
<string>en0</string>
<string>-c</string>
<string>/etc/snort/snort.conf</string>
</array>
<key>ServiceDescription</key>
<string>Snort Ethernet</string>
</dict>
</plist>
# Create snort user. The intention is to let user snort have access only to the snort database.
sudo createuser -U _postgres -P snort
Password:
Enter password for new role:
Enter it again:
Shall the new role be a superuser? (y/n) n
Shall the new role be allowed to create databases? (y/n) n
Shall the new role be allowed to create more new roles? (y/n) n
# Create snort PostgreSQL database owned by user snort and has all owner privileges for to-be-created database snort
sudo createdb -U _postgres -O snort -W snort
cd /usr/local/pgsql
sudo psql -U snort snort < ./create_postgresql
# To clean up tests, errors: $ sudo serveradmin stop postgres ; sudo serveradmin start postgres ; sudo dropdb -U _postgres snort
# inspect snort PostgreSQL database
sudo psql -q -d snort snort --password
snort=# \d
# check the tables, indices, privileges, etc.
sudo psql -q -d snort _postgres --password
snort=# \dt
snort=# \dp
# Mountain Lion: Tell postgres to listen on 127.0.0.1
sudo serveradmin settings postgres:listen_addresses = "127.0.0.1" && sudo serveradmin stop postgres && sudo serveradmin start postgres
sudo serveradmin settings postgres:hba_file = /Library/Server/PostgreSQL/Config/pg_hba.conf && sudo serveradmin stop postgres && sudo serveradmin start postgres
sudo vi /Library/Server/PostgreSQL/Config/pg_hba.conf
# Append these lines:
# Admin added dbs
host snort snort 127.0.0.1/32 password
# Restart postgresql on OS X Server
sudo serveradmin status postgres
sudo serveradmin stop postgres
sudo serveradmin start postgres
sudo less /Library/Logs/PostgreSQL/PostgreSQL.log
ps -ef | grep postgres | grep -v grep
nmap -p 5432 localhost
Starting Nmap 6.01 ( http://nmap.org ) at 2012-10-28 06:34 EDT
Nmap scan report for localhost (127.0.0.1)
Host is up (0.00012s latency).
PORT STATE SERVICE
5432/tcp open postgresql
# Sanity check that snort can connect to the database with non-daemon call
sudo /usr/local/bin/snort -d -e -i en0 -c /etc/snort/snort.conf
# Success looks like:
--== Initialization Complete ==--
,,_ -*> Snort! <*-
o" )~ Version 2.9.3.1 IPv6 GRE (Build 40)
'''' By Martin Roesch & The Snort Team: http://www.snort.org/snort/snort-team
Copyright (C) 1998-2012 Sourcefire, Inc., et al.
Using libpcap version 1.3.0
Using PCRE version: 8.31 2012-07-06
Using ZLIB version: 1.2.7
Rules Engine: SF_SNORT_DETECTION_ENGINE Version 1.16 <Build 18>
Preprocessor Object: SF_SSLPP (IPV6) Version 1.1 <Build 4>
Preprocessor Object: SF_SSH (IPV6) Version 1.1 <Build 3>
Preprocessor Object: SF_SMTP (IPV6) Version 1.1 <Build 9>
Preprocessor Object: SF_SIP (IPV6) Version 1.1 <Build 1>
Preprocessor Object: SF_SDF (IPV6) Version 1.1 <Build 1>
Preprocessor Object: SF_REPUTATION (IPV6) Version 1.1 <Build 1>
Preprocessor Object: SF_POP (IPV6) Version 1.0 <Build 1>
Preprocessor Object: SF_MODBUS (IPV6) Version 1.1 <Build 1>
Preprocessor Object: SF_IMAP (IPV6) Version 1.0 <Build 1>
Preprocessor Object: SF_GTP (IPV6) Version 1.1 <Build 1>
Preprocessor Object: SF_FTPTELNET (IPV6) Version 1.2 <Build 13>
Preprocessor Object: SF_DNS (IPV6) Version 1.1 <Build 4>
Preprocessor Object: SF_DNP3 (IPV6) Version 1.1 <Build 1>
Preprocessor Object: SF_DCERPC2 (IPV6) Version 1.0 <Build 3>
Commencing packet processing (pid=69660)
# Tweak snort to limit and/or ignore false alarms (after a day or so of collecting stats)
# /etc/snort/threshold.conf: add these lines to end
sudo vi /etc/snort/threshold.conf
# domainname.com rules
# See http://taosecurity.blogspot.com/2006/08/more-snort-and-sguil-tuning.html
# How to find the gid, sid: $ grep "Reset" /etc/snort/*.map
# Confirm at http://snortid.com/, e.g.
# To clear and restart the snort/barnyard/BASE system:
# $ sudo SystemStarter stop Swatch
# $ ps -ef | grep tail | grep -v grep # kill -9 all Swatch's tail processes
# $ sudo launchctl unload -w /Library/LaunchDaemons/org.opensource.barnyard.plist
# $ sudo launchctl unload -w /Library/LaunchDaemons/org.snort.Snort.plist
# BASE > Cache & Status > Database: Clear Data Tables
# $ sudo rm /var/log/snort/snort.u2*
# $ sudo rm /etc/barnyard2/barnyard2.waldo
# $ sudo launchctl load -w /Library/LaunchDaemons/org.snort.Snort.plist
# $ sudo launchctl load -w /Library/LaunchDaemons/org.opensource.barnyard.plist
# $ sudo SystemStarter start Swatch
# Other, more drastic methods
# BASE > Cache & Status > Database: Clear Data Tables
# $ sudo SystemStarter stop Swatch && sudo serveradmin stop postgres && sudo launchctl unload -w /Library/LaunchDaemons/org.snort.Snort.plist
# $ ps -ef | grep snort | grep -v grep
# ### $ sudo rm /var/log/snort/*
# $ sudo serveradmin start postgres && sudo serveradmin status postgres
# sudo launchctl load -w /Library/LaunchDaemons/org.snort.Snort.plist
# $ sudo SystemStarter start Swatch
# 128 || 4 || ssh: Protocol mismatch
event_filter gen_id 128, sig_id 4, type limit, track by_src, count 1, seconds 180
# 129 || 4 || stream5: TCP Timestamp is outside of PAWS window
event_filter gen_id 129, sig_id 4, type limit, track by_src, count 1, seconds 180
# 129 || 15 || stream5: Reset outside window
event_filter gen_id 129, sig_id 15, type limit, track by_src, count 1, seconds 180
suppress gen_id 129, sig_id 15, track by_src, ip 10.0.1.0/24
# 399 || ICMP Destination Unreachable Host Unreachable
event_filter gen_id 1, sig_id 399, type limit, track by_src, count 1, seconds 180
# 408 || ICMP Echo Reply
event_filter gen_id 1, sig_id 408, type limit, track by_src, count 1, seconds 180
# 648 || SHELLCODE x86 NOOP || arachnids,181
event_filter gen_id 1, sig_id 648, type limit, track by_src, count 1, seconds 180
suppress gen_id 1, sig_id 648, track by_src, ip 10.0.1.2
suppress gen_id 1, sig_id 648, track by_src, ip 169.254.0.0/16
# 1390 || SHELLCODE x86 inc ebx NOOP
event_filter gen_id 1, sig_id 1390, type limit, track by_src, count 1, seconds 180
suppress gen_id 1, sig_id 1390, track by_src, ip 10.0.1.2
suppress gen_id 1, sig_id 1390, track by_src, ip 169.254.0.0/16
# 1394 || SHELLCODE x86 inc ecx NOOP
event_filter gen_id 1, sig_id 1394, type limit, track by_src, count 1, seconds 180
suppress gen_id 1, sig_id 1394, track by_src, ip 10.0.1.2
suppress gen_id 1, sig_id 1394, track by_src, ip 169.254.0.0/16
# 12798 || SHELLCODE base64 x86 NOOP
event_filter gen_id 1, sig_id 12798, type limit, track by_src, count 1, seconds 180
suppress gen_id 1, sig_id 12798, track by_src, ip 10.0.1.2
suppress gen_id 1, sig_id 12798, track by_src, ip 169.254.0.0/16
# 12799 || SHELLCODE base64 x86 NOOP
event_filter gen_id 1, sig_id 12799, type limit, track by_src, count 1, seconds 180
suppress gen_id 1, sig_id 12799, track by_src, ip 10.0.1.2
suppress gen_id 1, sig_id 12799, track by_src, ip 169.254.0.0/16
# 12800 || SHELLCODE base64 x86 NOOP
event_filter gen_id 1, sig_id 12800, type limit, track by_src, count 1, seconds 180
suppress gen_id 1, sig_id 12800, track by_src, ip 10.0.1.2
suppress gen_id 1, sig_id 12800, track by_src, ip 169.254.0.0/16
# 12801 || SHELLCODE base64 x86 NOOP
event_filter gen_id 1, sig_id 12801, type limit, track by_src, count 1, seconds 180
suppress gen_id 1, sig_id 12801, track by_src, ip 10.0.1.2
suppress gen_id 1, sig_id 12801, track by_src, ip 169.254.0.0/16
# 12802 || SHELLCODE base64 x86 NOOP
event_filter gen_id 1, sig_id 12802, type limit, track by_src, count 1, seconds 180
suppress gen_id 1, sig_id 12802, track by_src, ip 10.0.1.2
suppress gen_id 1, sig_id 12802, track by_src, ip 169.254.0.0/16
Barnyard2
# Build barnyard2 -- see http://www.securixlive.com/barnyard2/download.php
curl -O -L http://www.securixlive.com/download/barnyard2/barnyard2-1.9.tar.gz
curl -O -L http://www.securixlive.com/download/barnyard2/org.opensource.barnyard.plist
openssl md5 barnyard2-1.9.tar.gz
openssl md5 org.opensource.barnyard.plist
cd barnyard2-1.9
./configure
make && sudo make install
# Configure barnyard2
sudo vi /etc/barnyard2/barnyard2.conf
config logdir: /var/log/barny
config hostname: myhostname
config interface: eth0
output alert_syslog
output database: log, postgresql, user=snort password=snort_db_password_used_above dbname=snort host=localhost
# Create org.opensource.barnyard.plist
sudo vi /Library/LaunchDaemons/org.opensource.barnyard.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>KeepAlive</key>
<true/>
<key>Label</key>
<string>org.opensource.barnyard.plist</string>
<key>ProgramArguments</key>
<array>
<string>/usr/local/bin/barnyard2</string>
<string>-c</string>
<string>/etc/barnyard2/barnyard2.conf</string>
<string>-n</string>
<string>-d</string>
<string>/var/log/snort</string>
<string>-f</string>
<string>snort.u2</string>
<string>-w</string>
<string>/etc/barnyard2/barnyard2.waldo</string>
</array>
</dict>
</plist>
Base
# Download from http://sourceforge.net/projects/secureideas/
# don't use Macports base -- currently 5 years out-of-date
tar xvzf base-1.4.5.tar.gz
sudo rsync -va --del ./base-1.4.5 /etc/base
# install adodb5 , PEAR
sudo port self update ; sudo port install adodb5 pear-Graph
# Add a bunch of PHP symlinks to base for graphing/mapping
cd /etc/base
sudo ln -s /opt/local/lib/php/pear/Console Console
sudo ln -s /opt/local/lib/php/pear/Image Image
sudo ln -s /opt/local/lib/php/pear/OS OS
sudo ln -s /opt/local/lib/php/pear/PEAR PEAR
sudo ln -s /opt/local/lib/php/pear/PEAR.php PEAR.php
sudo ln -s /opt/local/lib/php/pear/PHPUnit PHPUnit
sudo ln -s /opt/local/lib/php/pear/Structures Structures
sudo ln -s /opt/local/lib/php/pear/System.php System.php
sudo ln -s /opt/local/lib/php/pear/XML XML
# Add base schema to database snort
cd /etc/base/sql
sudo psql -U snort snort < ./create_base_tbls_pgsql.sql
# Configure base
sudo vi /etc/base/base_conf.php
$BASE_urlpath = '/base';
$DBlib_path = '/opt/local/share/adodb5';
$DBtype = 'postgres';
$alert_dbname = 'snort';
$alert_password = 'snort_db_password_used_above';
$archive_password = 'snort_db_password_used_above';
$action_email_smtp_host = 'smtp.domainname.com';
$use_sig_list = 2;
$resolve_IP = 1;
$show_expanded_query = 1;
$show_summary_stats = 1;
$colored_alerts = 1;
$Geo_IPfree_file_ascii = "/etc/base/ips-ascii.txt";
$IP2CC = "/usr/bin/ip2cc";
Webserver (Mountain Lion)
# Add the following line to /Library/Server/Web/Config/apache2/httpd_server_app.conf
sudo vi /Library/Server/Web/Config/apache2/httpd_server_app.conf
Include /Library/Server/Web/Config/apache2/domainname/*.conf
# Create the file /Library/Server/Web/Config/apache2/domainname/snort-base.conf
sudo vi /Library/Server/Web/Config/apache2/domainname/snort-base.conf
Alias /base /etc/base
<Directory "/etc/base">
Options Indexes MultiViews FollowSymLinks
AuthType Digest
AuthName "Base"
AuthUserFile /etc/base/.htdigest
AuthGroupFile /dev/null
Require user Snort
AllowOverride All
Order allow,deny
Allow from all
</Directory>
Alias /adodb /opt/local/share/adodb5
<Directory "/opt/local/share/adodb5">
AuthType Digest
AuthName "ADODB"
AuthUserFile /etc/base/.htdigest
AuthGroupFile /dev/null
Require user Snort
Options Indexes MultiViews
AllowOverride All
Order allow,deny
Allow from all
</Directory>
# Apache web server for base: Create password
sudo htdigest /etc/base/.htdigest Snort Base
# Restart Apache using either serveradmin or Server.app
sudo serveradmin stop web && sudo serveradmin start web
Swatch
See <https://discussions.apple.com/thread/3370709?start=0&tstart=0> .
Launch It All
sudo launchctl load -w /Library/LaunchDaemons/org.snort.Snort.plist
sudo launchctl load -w /Library/LaunchDaemons/org.opensource.barnyard.plist
sudo SystemStarter start Swatch
One final note: my Lion's web server returns a 400 Bad Request error for web pages that use a hex %23 (ascii #) in their urls, which affects some BASE queries. Any pointers to a fix to this problem would be greatly appreciated.
Mac mini Server (Mid 2010), OS X Mountain Lion (10.8.2), OS X Server, EyeTV HD, Turbo.264 HD