Full Disclosure mailing list archives
SSH Bruteforce blocking script
From: "Michael L Benjamin" <mike.benjamin () clarinet com au>
Date: Fri, 2 Sep 2005 15:37:11 +0800
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 # 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 touch ${TMP_FILE} while : 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'}) # 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 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]. 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 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/
Current thread:
- SSH Bruteforce blocking script Michael L Benjamin (Sep 02)
- Re: SSH Bruteforce blocking script Alejandro Barrera (Sep 02)
- Re: SSH Bruteforce blocking script Christoph Moench-Tegeder (Sep 02)
- Re: SSH Bruteforce blocking script Gerald Holl (Sep 03)
- <Possible follow-ups>
- RE: SSH Bruteforce blocking script Michael L Benjamin (Sep 02)
- RE: SSH Bruteforce blocking script Michael L Benjamin (Sep 02)
- RE: SSH Bruteforce blocking script Michael L Benjamin (Sep 02)
- Re: SSH Bruteforce blocking script Christoph Moench-Tegeder (Sep 02)
- Re: SSH Bruteforce blocking script Pedro Hugo (Sep 02)
- RE: SSH Bruteforce blocking script Michael L Benjamin (Sep 02)
- Re: SSH Bruteforce blocking script miah (Sep 02)
(Thread continues...)