So I was tinkering with my ASA the other day. I was interested in this neat Botnet Traffic Filter thingy they’d been clamoring about. Cisco frequently pitches how their products are made with magic and rainbows and cruelty-free unicorn meat, and I tend to be a bit skeptical. But a lot of people have been talking about it recently in my circles, and I really can’t help but tinker with things anyways.
After some reading, Cisco words it like the Botnet Filter is pretty much useless without a proper license. However it is enabled and ready to use in all ASAs 8.2(x) and above… the license only activates the subscription service, the base functionality works just fine. Below is a script I wrote to manually apply and update blacklists using the Botnet Filter on an ASA without bothering with a subscription license. It’s a bash script which does most of the work and depends additionally on the expect scripting interpreter for operating on the ASA itself. The script looks for an external tftp server but can be easily written to use a local /tftpboot directory instead. Older versions of the script failed seldom but in amusingly spectacular ways, so the current version is somewhat lengthy due to the sanity checks I built into it.
A big problem with blacklists tends to be keeping them current. A stale blacklist is worse than useless as the IPs may belong to legitimate sites after some time. I’ve used the
lists over at
Emerging Threats for a while now, and they’re very frequently updated. The script can be easily modified for use with any published or local list.. 5 minutes of work adapted this script from using the C&C list to the larger “-ALL” list. Just do some find/replace magic and modify the regex syntax that changes ACL entries into dynamic-filter formatted “address x.x.x.x m.a.s.k” lines.
I apologize in advance for the terrible line wrapping in the code, I need to find a new theme. Note that the box running this is OpenBSD, you’ll probably have to change your bash path. UUOC police: It’s my cat and I’ll do what I want with it.
Ez-wget links to the below script and the larger “-ALL” variant as a modification example.
asa-botlist.txt asa-botlist_all.txt #!/usr/local/bin/bash
#
# asa-botlist.sh - written by Iggdawg
#
# This script uses a feature in the Cisco ASA Botnet Filter feature. Although
# a licensed feature that requires a paid subscription, this feature also
# allows administrators to use the "dynamic-filter blacklist" directive for
# manual blacklisting. Emerging Threats (
http://www.emergingthreats.net)
# publishes well maintained blacklists from many sources. This script applies
# that list as a manual blacklist on the ASA, and keeps it up to date with diffs
# rather than removing and re-applying the list every time to change as little
# as possible with each transaction.
#
#
# Variables, modify to your liking
PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/sbin
export PATH
# NOTE: I use scp with certificates to ransport stuff to the tftp server.
# Expect the script to fail if you're not set up to do this.
TFTPSERV="tftp server IP address"
FWIP="firewall IP address"
USERNAME="tftp server user"
FWUSERNAME="firewall user"
PASSWORD="firewall password"
PASSWORD="firewall enable password"
FWHOSTNAME="firewall hostname"
BASEPATH="/tmp"
#Blacklist Revisions
touch $BASEPATH/emerging-PIX-CC.rev
Rev0="$(cat $BASEPATH/emerging-PIX-CC.rev)"
Rev1="$(lynx --source
http://rules.emergingthreats.net/fwrules/FWrev)"
# script depends on expect, check for it
EXP="$(which expect)"
if [ $? -ne 0 ] ; then
echo "Expect binary not found, exiting"
exit 1
elif [ -e "$EXP" ] ; then
echo "Expect binary found, running"
fi
# check list revision
if [ -s $BASEPATH/emerging-PIX-CC.rev ] ; then
if [ $Rev0 -ge $Rev1 ] ; then
echo "Current revision $Rev1 matches last revision processed $Rev0, Exiting"
exit 0
else
echo "Current revision $Rev1 is newer than last revision processed $Rev0, Working"
fi
else
echo "No existing blacklist revision number. Possible file errors. Starting from scratch with $Rev1"
echo "Snagging most current list:"
wget
http://rules.emergingthreats.net/fwrules/emerging-PIX-CC.rules -O $BASEPATH/emerging-PIX-CC.rules
# update revision now so script won't re-run in case of some random failure:
awk '/Rev/ {print $3}' $BASEPATH/emerging-PIX-CC.rules > $BASEPATH/emerging-PIX-CC.rev
# start processing
# rewrite ET-drop to ET-cc so the list is consistant, then parse
sed 's/ET-drop/ET-cc/g' $BASEPATH/emerging-PIX-CC.rules | egrep "^access-list ET-cc deny" $BASEPATH/emerging-PIX-CC.rules | sed 's/access-list ET-cc deny ip/address/g;s/host //g;s/any/255.255.255.255/g' | awk '{print $1,$2,$3}' > $BASEPATH/emerging-PIX-CC.rules.pix
# can't verify current version, remove all old entries and apply current list.
# this will be a temporary list, preserving "raw" list so diffs don't break next time
echo "no dynamic-filter blacklist" > $BASEPATH/emerging-PIX-CC.rules.pix.tmp
echo "dynamic-filter blacklist" >> $BASEPATH/emerging-PIX-CC.rules.pix.tmp
cat $BASEPATH/emerging-PIX-CC.rules.pix >> $BASEPATH/emerging-PIX-CC.rules.pix.tmp
chmod 666 $BASEPATH/emerging-PIX-CC.rules.pix.tmp
chown nobody:nogroup $BASEPATH/emerging-PIX-CC.rules.pix.tmp
echo "Sending files to TFTP server"
echo "emerging-PIX-CC.rules.pix..."
scp $BASEPATH/emerging-PIX-CC.rules.pix.tmp $USERNAME@$TFTPSERV:/tftpboot/emerging-PIX-CC.rules.pix.tmp
# log into the firewall and tell it to snag the diffs
#
# uncomment to call expect script from its own file
#$EXP /some/script
$EXP - << EndMark spawn ssh -l $FWUSERNAME $FWIP expect "*assword:" exp_send -- "$PASSWORD\r" expect "$FWHOSTNAME>"
exp_send -- "enable\r"
expect "Password:"
exp_send -- "$ENPASSWORD\r"
expect "$FWHOSTNAME#"
exp_send -- "
copy /noconfirm tftp://$TFTPSERV/emerging-PIX-CC.rules.pix.tmp running-config
\r"
expect "$FWHOSTNAME#"
exp_send -- "exit\r"
interact
EndMark
exit 0
fi
echo ""
echo ""
echo ""
# If old revision exists but the list is missing, script will diff against an
# empty file and just use whole current list. ASA silently dismisses
# duplication of existing address entries, so this is not harmful.
if [ -e $BASEPATH/emerging-PIX-CC.rules.pix ] ; then
mv $BASEPATH/emerging-PIX-CC.rules.pix $BASEPATH/emerging-PIX-CC.rules.pix.old
else
echo "Revision file exists, but last blacklist file missing. Will apply whole list."
touch $BASEPATH/emerging-PIX-CC.rules.pix.old
fi
# clean up
echo "" > $BASEPATH/emerging-PIX-CC.rules.egress.pix
# grab current
echo "Snagging most current list:"
wget
http://rules.emergingthreats.net/fwrules/emerging-PIX-CC.rules -O $BASEPATH/emerging-PIX-CC.rules
# update revision now so script won't re-run in case of some random failure:
echo "Updating revision"
awk '/Rev/ {print $3}' $BASEPATH/emerging-PIX-CC.rules > $BASEPATH/emerging-PIX-CC.rev
# start processing
# rewrite ET-drop to ET-cc so the list is consistant, then parse
sed 's/ET-drop/ET-cc/g' $BASEPATH/emerging-PIX-CC.rules | egrep "^access-list ET-cc deny" $BASEPATH/emerging-PIX-CC.rules | sed 's/access-list ET-cc deny ip/address/g;s/host //g;s/any/255.255.255.255/g' | awk '{print $1,$2,$3}' >> $BASEPATH/emerging-PIX-CC.rules.pix
echo "Processing blacklist diffs"
diff $BASEPATH/emerging-PIX-CC.rules.pix $BASEPATH/emerging-PIX-CC.rules.pix.old | grep ^\< | sed 's/\< //g' > $BASEPATH/emerging-PIX-CC.rules.ingress
diff $BASEPATH/emerging-PIX-CC.rules.pix $BASEPATH/emerging-PIX-CC.rules.pix.old | grep ^\> | sed 's/\> //g' > $BASEPATH/emerging-PIX-CC.rules.egress
# check for errors in processing
echo "" > $BASEPATH/ingress.exceptions
echo "" > $BASEPATH/egress.exceptions
echo "Blacklist diff errors:"
echo ""
awk '{print $2}' $BASEPATH/emerging-PIX-CC.rules.egress | while read LINE ; do
grep $LINE $BASEPATH/emerging-PIX-CC.rules.ingress > $BASEPATH/ingress.exceptions
done
echo "$BASEPATH/emerging-PIX-CC.rules.ingress:"
cat $BASEPATH/ingress.exceptions
awk '{print $2}' $BASEPATH/emerging-PIX-CC.rules.ingress | while read LINE; do
grep $LINE $BASEPATH/emerging-PIX-CC.rules.egress > $BASEPATH/egress.exceptions
done
echo "$BASEPATH/emerging-PIX-CC.rules.egress:"
cat $BASEPATH/egress.exceptions
# bring it all together and dump it on a tftp server
echo "Combining diffs"
echo "dynamic-filter blacklist" > $BASEPATH/emerging-PIX-CC.rules.diff.pix
sed 's/^/no\ /g' < $BASEPATH/emerging-PIX-CC.rules.egress >> $BASEPATH/emerging-PIX-CC.rules.egress.pix
cat $BASEPATH/emerging-PIX-CC.rules.egress.pix $BASEPATH/emerging-PIX-CC.rules.ingress >> $BASEPATH/emerging-PIX-CC.rules.diff.pix
# some tftp servers are weird about permisssions
chmod 666 $BASEPATH/emerging-PIX-CC.rules.diff.pix
chown nobody:nogroup $BASEPATH/emerging-PIX-CC.rules.diff.pix
chmod 666 $BASEPATH/emerging-PIX-CC.rules.pix
chown nobody:nogroup $BASEPATH/emerging-PIX-CC.rules.pix
echo "Sending files to TFTP server"
echo "emerging-PIX-CC.rules.pix..."
scp $BASEPATH/emerging-PIX-CC.rules.pix $USERNAME@$TFTPSERV:/tftpboot/emerging-PIX-CC.rules.pix
echo "emerging-PIX-CC.rules.diff.pix..."
scp $BASEPATH/emerging-PIX-CC.rules.diff.pix $USERNAME@$TFTPSERV:/tftpboot/emerging-PIX-CC.rules.diff.pix
# log into the firewall and tell it to snag the diffs
#
# uncomment to call expect script from its own file
#$EXP /some/script
$EXP - << EndMark spawn ssh -l $FWUSERNAME $FWIP expect "*assword:" exp_send -- "$PASSWORD\r" expect "$FWHOSTNAME>"
exp_send -- "enable\r"
expect "Password:"
exp_send -- "$ENPASSWORD\r"
expect "$FWHOSTNAME#"
exp_send -- "
copy /noconfirm tftp://$TFTPSERV/emerging-PIX-CC.rules.diff.pix running-config
\r"
expect "$FWHOSTNAME#"
exp_send -- "exit\r"
interact
EndMark
exit 0
Originally published at
The IggBlog. You can comment here or
there.