Hi
there,
Here is a
simple script I've coded up that I use on 3 of my RedHat Enterprise Linux 3
(RHEL3) servers. I decided to do this after seeing the
amount of
activity
from places like China/Korea/Taiwan in relation to SSH brute force probes. I'll
throw it open here for analysis/suggestions. It
leverages off the
TCPWrappers /etc/hosts.deny /etc/hosts.allow functionality.
Naturally I could
implement SSH port-knocking or something similar or move the SSH port, but I
feel that I'm pretty well off blocking the sorts
of hosts that would
attempt this in the first place, as they seem to mainly be compromised unix
boxen and are persistent, and why should I
change on their
behalf?
It may have a
bugs related to counting the attacks, but otherwise it is solid. The thing you
want to keep in mind is that you should add friendly
hosts to
/etc/hosts.allow lest they get blocked by accident. /etc/hosts.allow will
override /etc/hosts.deny always, even if a host is
accidentally
added there. I have
yet to code up an exclusions list technique that would achieve a similar
effect.
I don't want to
debate the goodness or badness of the strategy of blocking hosts like this in
/etc/hosts.deny. It works perfectly for me, and most
likely would for
you, so no religious debates thanks. It's effective at blocking bruteforce attacks.
If a host EXCEEDS a specified number of guesses
during the
(configurable) 30 seconds it takes the script to cycle, the host is
blacklisted.
The script is
simple, and it is one script, it doesn't require gobs of documentation,
CPU, or ancillary files as some methods appear to. It uses
Korn
shell simply because
that's my preferred shell, it could be easily ported to other shells as it lacks
any complexity.
I have left in some
of the original lines of code during development, but they can be safely
removed.
I hope it proves of
some use to you.
-------------------------------8<-------------------------------8<-------------------------------8<-------------------------------8<-------------------------------8<-------------------------------8<
#!/bin/ksh
#
# ssh_brute_blocker
#
# 05/07/2004 15:05 - Michael L. Benjamin
#
#
# ssh_brute_blocker
#
# 05/07/2004 15:05 - Michael L. Benjamin
#
SCRIPT_NAME=$(basename
$0)
LOG_FILE="/var/log/secure"
DENY_FILE="/etc/hosts.deny"
TMP_FILE="/tmp/${SCRIPT_NAME}.$$"
INBOUND_IP=""
INLINE=""
GUESS_COUNT=0
PERMIT_GUESS=4
LOG_FILE="/var/log/secure"
DENY_FILE="/etc/hosts.deny"
TMP_FILE="/tmp/${SCRIPT_NAME}.$$"
INBOUND_IP=""
INLINE=""
GUESS_COUNT=0
PERMIT_GUESS=4
touch
${TMP_FILE}
while
:
do
do
tail -10000
${LOG_FILE} | grep "Failed password for illegal user" | awk -F"from" {'print
$2'} | awk {'print $1'} | uniq > ${TMP_FILE}
while read -r
INBOUND_IP
do
GUESS_COUNT=0
# GUESS_COUNT=$(grep ${INBOUND_IP} ${LOG_FILE} | wc -l)
GUESS_COUNT=$(grep "from ${INBOUND_IP}" /var/log/secure | grep "Failed password for" | wc -l | awk {'print $1'})
do
GUESS_COUNT=0
# GUESS_COUNT=$(grep ${INBOUND_IP} ${LOG_FILE} | wc -l)
GUESS_COUNT=$(grep "from ${INBOUND_IP}" /var/log/secure | grep "Failed password for" | wc -l | awk {'print $1'})
# echo IP:
${INBOUND_IP} made ${GUESS_COUNT} guesses against our server
if [
${GUESS_COUNT} -ge ${PERMIT_GUESS} ]
then
if grep ${INBOUND_IP} ${DENY_FILE} > /dev/null
then
# echo ${INBOUND_IP} is already listed in ${DENY_FILE} ; echo
echo > /dev/null
else
# echo ${INBOUND_IP} is not listed. Adding host ${INBOUND_IP} to ${DENY_FILE} ; echo
echo "ALL: ${INBOUND_IP}" >> ${DENY_FILE}
/usr/bin/logger -t ssh_brute_blocker -is Added SSH attacking host ${INBOUND_IP} to ${DENY_FILE} [${GUESS_COUNT} attempts].
fi
else
# echo Ignoring host ${INBOUND_IP} less than ${PERMIT_GUESS} wrong guesses.
echo > /dev/null
fi
then
if grep ${INBOUND_IP} ${DENY_FILE} > /dev/null
then
# echo ${INBOUND_IP} is already listed in ${DENY_FILE} ; echo
echo > /dev/null
else
# echo ${INBOUND_IP} is not listed. Adding host ${INBOUND_IP} to ${DENY_FILE} ; echo
echo "ALL: ${INBOUND_IP}" >> ${DENY_FILE}
/usr/bin/logger -t ssh_brute_blocker -is Added SSH attacking host ${INBOUND_IP} to ${DENY_FILE} [${GUESS_COUNT} attempts].
fi
else
# echo Ignoring host ${INBOUND_IP} less than ${PERMIT_GUESS} wrong guesses.
echo > /dev/null
fi
done <
${TMP_FILE}
sleep
30
rm -f
${TMP_FILE}
done
exit
0
-------------------------------8<-------------------------------8<-------------------------------8<-------------------------------8<-------------------------------8<-------------------------------8<
I call it as follows in /etc/rc.local, and runs
completely silently in the background blocking bad
hosts:
# Fire up ssh_brute_blocker security
script
/usr/local/scripts/ssh_brute_blocker
&
-------------------------------8<-------------------------------8<-------------------------------8<-------------------------------8<-------------------------------8<-------------------------------8<
I also have some webpages that I generate to show me
/etc/hosts.deny, count blocked hosts and report on blocked hosts from
/var/log/messages
eg:
Aug 29 03:05:57 XXXXXXXXXXXX ssh_brute_blocker[20644]:
Added SSH attacking host 83.133.125.4 to /etc/hosts.deny [4 attempts].
Aug 29 13:18:33 XXXXXXXXXXXX ssh_brute_blocker[15590]: Added SSH attacking host 220.82.197.48 to /etc/hosts.deny [4 attempts].
Aug 30 04:24:39 XXXXXXXXXXXX ssh_brute_blocker[20637]: Added SSH attacking host 203.98.150.6 to /etc/hosts.deny [9 attempts].
Aug 30 19:24:08 XXXXXXXXXXXX ssh_brute_blocker[10139]: Added SSH attacking host 62.61.140.116 to /etc/hosts.deny [8 attempts].
Sep 1 03:49:01 XXXXXXXXXXXX ssh_brute_blocker[4104]: Added SSH attacking host 83.16.116.110 to /etc/hosts.deny [5 attempts].
Sep 2 02:48:22 XXXXXXXXXXXX ssh_brute_blocker[1633]: Added SSH attacking host 60.248.154.162 to /etc/hosts.deny [8 attempts].
Aug 29 13:18:33 XXXXXXXXXXXX ssh_brute_blocker[15590]: Added SSH attacking host 220.82.197.48 to /etc/hosts.deny [4 attempts].
Aug 30 04:24:39 XXXXXXXXXXXX ssh_brute_blocker[20637]: Added SSH attacking host 203.98.150.6 to /etc/hosts.deny [9 attempts].
Aug 30 19:24:08 XXXXXXXXXXXX ssh_brute_blocker[10139]: Added SSH attacking host 62.61.140.116 to /etc/hosts.deny [8 attempts].
Sep 1 03:49:01 XXXXXXXXXXXX ssh_brute_blocker[4104]: Added SSH attacking host 83.16.116.110 to /etc/hosts.deny [5 attempts].
Sep 2 02:48:22 XXXXXXXXXXXX ssh_brute_blocker[1633]: Added SSH attacking host 60.248.154.162 to /etc/hosts.deny [8 attempts].
IP's have been left in place to un-protect the guilty...
Here are some typical attacks logged to
/var/log/secure:
Aug 30 04:24:02 XXXXXXXXXXXX sshd[20561]: Illegal user
patrick from 203.98.150.6
Aug 30 04:24:06 XXXXXXXXXXXX sshd[20563]: Illegal user patrick from 203.98.150.6
Aug 30 04:24:32 XXXXXXXXXXXX sshd[20604]: Illegal user rolo from 203.98.150.6
Aug 30 04:24:37 XXXXXXXXXXXX sshd[20606]: Illegal user iceuser from 203.98.150.6
Aug 30 05:48:43 XXXXXXXXXXXX sshd[31199]: Illegal user test from 218.69.8.78
Aug 30 19:23:15 XXXXXXXXXXXX sshd[10045]: Illegal user test from 62.61.140.116
Aug 30 19:23:23 XXXXXXXXXXXX sshd[10047]: Illegal user guest from 62.61.140.116
Aug 30 19:23:29 XXXXXXXXXXXX sshd[10049]: Illegal user admin from 62.61.140.116
Aug 30 19:23:36 XXXXXXXXXXXX sshd[10051]: Illegal user admin from 62.61.140.116
Aug 30 19:23:42 XXXXXXXXXXXX sshd[10091]: Illegal user user from 62.61.140.116
Aug 30 19:24:06 XXXXXXXXXXXX sshd[10099]: Illegal user test from 62.61.140.116
Aug 31 09:52:59 XXXXXXXXXXXX sshd[4375]: Illegal user test from 211.147.5.54
Sep 1 03:48:34 XXXXXXXXXXXX sshd[4000]: Illegal user fluffy from 83.16.116.110
Sep 1 03:48:41 XXXXXXXXXXXX sshd[4049]: Illegal user admin from 83.16.116.110
Sep 1 03:48:49 XXXXXXXXXXXX sshd[4051]: Illegal user test from 83.16.116.110
Sep 1 03:48:56 XXXXXXXXXXXX sshd[4053]: Illegal user guest from 83.16.116.110
Sep 1 03:49:04 XXXXXXXXXXXX sshd[4055]: Illegal user webmaster from 83.16.116.110
Sep 1 21:17:35 XXXXXXXXXXXX sshd[11002]: Illegal user admin from 202.129.34.101
Sep 2 02:47:27 XXXXXXXXXXXX sshd[1505]: Illegal user alin from 60.248.154.162
Sep 2 02:47:41 XXXXXXXXXXXX sshd[1507]: Illegal user alin from 60.248.154.162
Sep 2 02:47:46 XXXXXXXXXXXX sshd[1509]: Illegal user theo from 60.248.154.162
Sep 2 02:47:51 XXXXXXXXXXXX sshd[1511]: Illegal user theo from 60.248.154.162
Sep 2 02:48:00 XXXXXXXXXXXX sshd[1569]: Illegal user theo from 60.248.154.162
Sep 2 02:48:10 XXXXXXXXXXXX sshd[1571]: Illegal user damian from 60.248.154.162
Sep 2 02:48:15 XXXXXXXXXXXX sshd[1573]: Illegal user damian from 60.248.154.162
Sep 2 02:48:20 XXXXXXXXXXXX sshd[1575]: Illegal user comun from 60.248.154.162
Aug 30 04:24:06 XXXXXXXXXXXX sshd[20563]: Illegal user patrick from 203.98.150.6
Aug 30 04:24:32 XXXXXXXXXXXX sshd[20604]: Illegal user rolo from 203.98.150.6
Aug 30 04:24:37 XXXXXXXXXXXX sshd[20606]: Illegal user iceuser from 203.98.150.6
Aug 30 05:48:43 XXXXXXXXXXXX sshd[31199]: Illegal user test from 218.69.8.78
Aug 30 19:23:15 XXXXXXXXXXXX sshd[10045]: Illegal user test from 62.61.140.116
Aug 30 19:23:23 XXXXXXXXXXXX sshd[10047]: Illegal user guest from 62.61.140.116
Aug 30 19:23:29 XXXXXXXXXXXX sshd[10049]: Illegal user admin from 62.61.140.116
Aug 30 19:23:36 XXXXXXXXXXXX sshd[10051]: Illegal user admin from 62.61.140.116
Aug 30 19:23:42 XXXXXXXXXXXX sshd[10091]: Illegal user user from 62.61.140.116
Aug 30 19:24:06 XXXXXXXXXXXX sshd[10099]: Illegal user test from 62.61.140.116
Aug 31 09:52:59 XXXXXXXXXXXX sshd[4375]: Illegal user test from 211.147.5.54
Sep 1 03:48:34 XXXXXXXXXXXX sshd[4000]: Illegal user fluffy from 83.16.116.110
Sep 1 03:48:41 XXXXXXXXXXXX sshd[4049]: Illegal user admin from 83.16.116.110
Sep 1 03:48:49 XXXXXXXXXXXX sshd[4051]: Illegal user test from 83.16.116.110
Sep 1 03:48:56 XXXXXXXXXXXX sshd[4053]: Illegal user guest from 83.16.116.110
Sep 1 03:49:04 XXXXXXXXXXXX sshd[4055]: Illegal user webmaster from 83.16.116.110
Sep 1 21:17:35 XXXXXXXXXXXX sshd[11002]: Illegal user admin from 202.129.34.101
Sep 2 02:47:27 XXXXXXXXXXXX sshd[1505]: Illegal user alin from 60.248.154.162
Sep 2 02:47:41 XXXXXXXXXXXX sshd[1507]: Illegal user alin from 60.248.154.162
Sep 2 02:47:46 XXXXXXXXXXXX sshd[1509]: Illegal user theo from 60.248.154.162
Sep 2 02:47:51 XXXXXXXXXXXX sshd[1511]: Illegal user theo from 60.248.154.162
Sep 2 02:48:00 XXXXXXXXXXXX sshd[1569]: Illegal user theo from 60.248.154.162
Sep 2 02:48:10 XXXXXXXXXXXX sshd[1571]: Illegal user damian from 60.248.154.162
Sep 2 02:48:15 XXXXXXXXXXXX sshd[1573]: Illegal user damian from 60.248.154.162
Sep 2 02:48:20 XXXXXXXXXXXX sshd[1575]: Illegal user comun from 60.248.154.162
Cheers,
Mike.
_______________________________________________ Full-Disclosure - We believe in it. Charter: http://lists.grok.org.uk/full-disclosure-charter.html Hosted and sponsored by Secunia - http://secunia.com/
