howto block w00tw00t.isc.sans.dfind:) und andere scans mit iptables

In letzter Zeit sind mir in meinen webserverlogs vermehrt scans von scripten nach bestimmten Pfaden bzw. nicht geschlossene Verbindungen die von user agents stammten die den string “w00tw00t.isc.sans.Dfind:)” und Variationen davon beeinhalteten aufgefallen. Diese stammten teilweise von Dialup ipadressen aber auch von vermutlich geknackten webservern mit festen ipadressen. Um dem ganzen Einhalt zu gebieten habe ich ein shellscript geschrieben, das die webserverlogs nach bestimmten strings absucht und die dazugehoerigen IP-adressen sperrt. Das script setzt voraus, das keinerlei Installationen von z.B. phpmyadmin oder anderer Verwaltungssoftware in standardpfaden existiert. Diese sollte ein verantwortungsvoller Admin auf öffentlichen Produktionsservern sowieso nicht verwenden ;)

Eine zeitabhängige Variante ist noch in Arbeit, leider fehlt mir dafür momentan die Zeit. Ich empfehle doppeltes und dreifaches testen bevor das ganze mit einem cronjob automatisiert wird.

Wenn die Befehle unterhalb der

###debug###

Statements einkommentiert werden kann das ganze getestet werden. Zum testen sollten auch die “scharfen”

iptables Zeilen wie folgt auskommentiert werden:


#${IPTABLESPATH} -I INPUT -s "$ip" -j LOG --log-level 4 --log-prefix '** HACKERS **';
#${IPTABLESPATH} -I INPUT -s "$ip" -j DROP;
#${IPTABLESPATH} -I OUTPUT -s "$ip" -j DROP;

Am Anfang der root crontab sollten folgende Zeilen stehen damit iptables gefunden wird und eventuelle Fehler per email gesendet werden.


MAILTO='someaddress@somedomain.com'
PATH=/usr/sbin:/usr/bin:/sbin:/bin

ich empfehle SEHR das whitelisting von anderen servern oder der momentan verwendeten ip
-> waehrend des testens habe ich auch aus Versehen meine eigene zu dem Zeitpunkt aktuelle dynamische ipadresse gesperrt :(

Und wie immer gilt: Benutzung auf eigene Gefahr + Erst DENKEN/verstehen und dann implementieren.

Hier nun das script:


#! /bin/bash
############################################################################################################################
# badstrings ban script
# version 0.3beta
# by arnd@netzturbine.de (https://identi.ca/netzturbine) and THEOTHERGUYOFNETZTURBINE
# parses the apache logs for banstrings and greps latest attacker ips from accesslogs and errorlogs
# loads list w/o doubles into iptables
# a time releveant component needs to be implemented
# !!!Handle w/ care whitelisting of ip’s is very necessary (i.e another server to keep access if locked out from own ip)!!!
############################################################################################################################

#devel path
#cd ~/Documents/devel/ip_blocker/;

#use on live systems directory must exist and contain this script
cd /root/bin/ip_block/;

###debug####
#pwd;

#set system type
#could be suse or non-suse
#if suse use SuSEfirewall2 scripts on top of this
system="suse"

#check if iptables is installed and found otherwise exit
IPTABLESPATH=$(which iptables);
if [ $? == "1" ]
then
echo "iptables not found";
exit;
fi

#set logformat
# if it is vhost 2nd ip ist to block if it is common 1st ip is to block
# check log_format.conf for possible values
# check somevhost.conf for used format
LOGFORMAT="vhost";

#set logpath
LOGPATH="/var/log/apache2/";

#Declare accesslogs array
#if multiple accesslogs are used put them with blanks like
# ACCESSLOGS=( ${LOGPATH}access_log ${LOGPATH}other_access_log);
ACCESSLOGS=( ${LOGPATH}access_log;

#Declare errorlogs array
#if multiple errorlogs are used put them with blanks
ERRORLOGS=( ${LOGPATH}error_log );

#declare banstringsarray
#be careful all requests containing these strings !!!case insensitive!!! AND throwing error 404 in access logs or showing up in error log are blocked except whitelisted ip's
BANSTRINGS=( 'w00t' 'phpmy' 'mysql' 'script' 'attacker' );

#resetting logs
# no better way to keep bans low until timestamps are implemented
# bears risk of being scanned by same host again
# comment in if users are mostly on dialup hosts
# logrotate should be on daily basis
#rm ./ban*;

# get number of elements in arrays

ACCESSLOGSNUMBER=${#ACCESSLOGS[@]}
###debug####
#echo "ACCESSLOGSNUMBER: ${ACCESSLOGSNUMBER}";
ERRORLOGSNUMBER=${#ERRORLOGS[@]}
###debug####
#echo "ERRORLOGSNUMBER: ${ERRORLOGSNUMBER}";
BANSTRINGSNUMBER=${#BANSTRINGS[@]}
###debug####
#echo "BANSTRINGSNUMBER: ${BANSTRINGSNUMBER}";

#parsing access logs looking for 404 errors and ${BANSTRINGS} to keep correct requests

i=0;
# outer loop through logs
while [ ${i} -lt ${ACCESSLOGSNUMBER} ]
do
###debug####
#echo "parsing log: "${ACCESSLOGS[${i}]};
#inner loop through banstrings
j=0;
while [ ${j} -lt ${BANSTRINGSNUMBER} ]
do
###debug####
#echo "No ${j} string to ban: ${BANSTRINGS[${j}]}";
#if logformat is vhost 2nd ip is attacker
if [ "${LOGFORMAT}" == "vhost" ]
then
#creating list - printing 2nd column - logformmat vhost - sorting w/ uniqueness
less ${ACCESSLOGS[${i}]} | grep 404 | grep -i ${BANSTRINGS[${j}]}.* | awk '{ print $2 '} | sort -u >> ./ban_latest_list;
else
#creating list - printing 1st column - Log format common - sorting w/ uniqueness
less ${ACCESSLOGS[${i}]} | grep 404 | grep -i ${BANSTRINGS[${j}]}.* | awk '{ print $1 '} | sort -u >> ./ban_latest_list;
fi
j=$[${j}+1];
done
#increment
i=$[${i}+1];
done

#parsing error logs
#creating list from error logs
i=0;
# outer loop through logs
while [ ${i} -lt ${ERRORLOGSNUMBER} ]
do
###debug####
#echo "parsing log: "${ERRORLOGS[${i}]};
#inner loop through banstrings
j=0;
while [ ${j} -lt ${BANSTRINGSNUMBER} ]
do
less ${ERRORLOGS[${i}]} | grep -i ${BANSTRINGS[${j}]}.* | awk '{ print $8 '} | sort -u | sed 's/]//g' >> ./ban_latest_list;
j=$[${j}+1];
done
#increment
i=$[${i}+1];
done

#merge lists
less ./ban_latest_list > ./ban_tmp_list;
less ./ban_list >> ./ban_tmp_list;
#create final list keep ip's unique
less ./ban_tmp_list | sort -u > ./ban_list_unique;
#remove empty lines
sed '/^$/d' ./ban_list_unique > ./ban_list;

#flushing firewall
if [ "${system}" == "suse" ]
then
###debug####
#echo "suse";
/sbin/SuSEfirewall2 stop 2>&1 > /dev/null;
/sbin/SuSEfirewall2 start 2>&1 > /dev/null;
else
###debug####
#echo "non-suse";
${IPTABLESPATH} -F;
${IPTABLESPATH} -X;
${IPTABLESPATH} -t nat -F;
${IPTABLESPATH} -t nat -X;
${IPTABLESPATH} -t mangle -F;
${IPTABLESPATH} -t mangle -X;
${IPTABLESPATH} -P INPUT ACCEPT;
${IPTABLESPATH} -P FORWARD ACCEPT;
${IPTABLESPATH} -P OUTPUT ACCEPT;
fi

#load list of blocked ip's
for ip in $(< ./ban_list);
do
#keep whitelisted hosts even if they give a false error + filter some strings falsely returned like "-" OR "PHP"
#ip’s put in if statement are NOT blocked whatever happens
if [ "${ip}" == "" ] || [ "${ip}" == "" ] || [ "${ip}" == "" ] \
|| [ "${ip}" == "-" ] || [ "${ip}" == "PHP" ] || [ "${ip}" == "file" ]
then
###debug####
#echo "${ip} whitelisted - do nothing";
continue;
else
###debug####
#echo "need to block attacker ${ip}";
${IPTABLESPATH} -I INPUT -s "$ip" -j LOG --log-level 4 --log-prefix '** HACKERS **';
${IPTABLESPATH} -I INPUT -s "$ip" -j DROP;
${IPTABLESPATH} -I OUTPUT -s "$ip" -j DROP;
fi
done

###debug####
#less ./ban_list;

Das ganze ersetzt natürlich keine apache modsecurity application firewall sondern ist ein eher krudes shellscript.

so long
Arnd

heute ist sysadminday

heute ist Sysadminday. Warum das so ist, weiss ich nicht mehr, und bin gerade zu fertig es zu recherchieren. Als guter sysadmin habe ich naemlich heute einen Kunden umgezogen und war von 8:10 bis 21:15 auf der “Baustelle”. Alles geht ;-) . Immerhin Sven hat mir gratuliert und ich moechte herzliche Glueckwuensche an dieser Stelle an Heiko und Hassan und Fabio und alle anderen Admins senden.

Happy Sysadminday folks ;-)

courier imap daemon Zertifikate einrichten fuer imaps, pop3s und smtps auf 1und1 SuSE 9.3 root server

Ich verwende email nur ueber imaps bzw. smtps. Das bietet eine verschluesselte Kommunikation und in meiner 1und1 Hardwarefirewall sind alle anderen email ports (25,110,143) gesperrt. Das haelt das log sauber, da keine Moeglichkeit besteht ueber die anderen Email Ports ueberhaupt eine Kommunikation zu initialisieren. Allerdings ist das von Plesk bei der Installation erzeugt Zertifikat mit “localhost” als Servername angelegt worden. Das fuehrt zu nervigen Fehlermeldungen, da Mailservername und Zertifikatshost nicht uebereinstimmen.

Deshalb habe ich das Zertifikat mit dem richtigen Mailservernamen neu angelegt. Die Vorgehensweise will ich kurz beschreiben.

weiterlesen »

Update howto 1und1 root server mit aktuellem Plesk 8.3 von SuSE 9.3 auf SuSE 10.1

Ich will meinen 1und1 root server updaten, da das Plesk mit Version 8.3 aktuell ist, aber die drunterliegende SuSE eine 9.3, die nicht mehr gepatcht wird. Eine gute Gelegenheit, um den ganzen Ablauf zu dokumentieren. Da ich schon einmal schlechte Erfahrungen mit “pleskbackup” machen musste, werden die wichtigen Dienste und Verzeichnisse zusaetzlich haendisch gesichert. Die Verzeichnispfade sollten mit einer Plesk Standardinstallation konform sein. Dieses Howto setzt grundlegende Linux Kenntnisse voraus. Ich uebernehme keine Verantwortung fuer Datenverluste.

weiterlesen »

should be invisible