#!/bin/sh # # ssh_chk.sh By H.Uekusa 2007 # Automated defending tool for ssh attack. # This command must be set on the cron with every minutes ############################################################################### # # You should set # $SHPATH [$TMP]/total_min_ipfw_add_cmd.txt # $SHPATH [$TMP]/total_hour_ipfw_add_cmd.txt # in /etc/rc.local # ############################################################################### # Set variable for location of commands, Path of files... # I recommend "--mmap" option for grep # CATPATH="/bin/cat" AWKPATH="/usr/bin/awk" GREPPATH="nice -n 10 /usr/bin/grep --mmap " DIFFPATH="/usr/bin/diff" SORTPATH="/usr/bin/sort" MAILPATH="/usr/bin/mail" DATEPATH="/bin/date" SHPATH="/bin/sh" LOOKUP="/usr/sbin/nslookup" AUTHLOG="/var/log/auth.log" TMP="/var/tmp" # Should be BSD-Firewall IPFWPATH="/sbin/ipfw" # Select to check "attempt" CHK_IP_RESOLV="yes" CHK_IP_MAP="yes" # Set threshold number such as 1 to 100,1000,10000 OK_PER_MIN="10" OK_PER_HOUR="100" # Set IPFW parameters # Check "ipfw -a list" and "ifconfig -a" IPFW_NUM="199" PORT="22" IF_NAME="fxp0" # Set valid e-mail! MAILTO="hogehoge" ############################################################################### # #Get date values # ############################################################################### NOW=`$DATEPATH +%Y%m%d%H%M` PREV=`$DATEPATH -v -1M +%Y%m%d%H%M` NOW_HOUR=`$DATEPATH +%Y%m%d%H` PREV_HOUR=`$DATEPATH -v -1H +%Y%m%d%H` ############################################################################### # #Get failed lines from auth log # ############################################################################### # Find a tring for invalid user $GREPPATH Invalid $AUTHLOG > $TMP/"$NOW"_fail.txt # It's old version of above for FreeBSD 4.x/5.x # $GREPPATH Illegal $AUTHLOG > $TMP/"$NOW"_fail.txt # #Touch the previous file for safe # touch $TMP/"$PREV"_fail.txt ############################################################################### # #Compare with before one minutes # ############################################################################### $DIFFPATH $TMP/"$NOW"_fail.txt $TMP/"$PREV"_fail.txt |$GREPPATH '^<' > $TMP/diff_raw.txt NONE_STATUS=`$GREPPATH -c ssh $TMP/diff_raw.txt` ############################################################################### # #Detect a probing of ssh from attacker (Selective) #As same as above procedure for normal check # ############################################################################### if [ "$CHK_IP_RESOLV" = "yes" ];then $GREPPATH "POSSIBLE BREAK-IN ATTEMPT" $AUTHLOG |$GREPPATH "getaddrinfo" > $TMP/"$NOW"_fail-attack.txt touch $TMP/"$PREV"_fail-attack.txt $DIFFPATH $TMP/"$NOW"_fail-attack.txt $TMP/"$PREV"_fail-attack.txt |$GREPPATH '^<' > $TMP/diff_raw-attack.txt NONE_STATUS_ATTACK=`$GREPPATH -c ssh $TMP/diff_raw-attack.txt` else NONE_STATUS_ATTACK="0" fi if [ "$CHK_IP_MAP" = "yes" ];then $GREPPATH "POSSIBLE BREAK-IN ATTEMPT" $AUTHLOG |$GREPPATH "not map back to the address" > $TMP/"$NOW"_fail-attack2.txt touch $TMP/"$PREV"_fail-attack2.txt $DIFFPATH $TMP/"$NOW"_fail-attack2.txt $TMP/"$PREV"_fail-attack2.txt |$GREPPATH '^<' > $TMP/diff_raw-attack2.txt NONE_STATUS_ATTACK2=`$GREPPATH -c ssh $TMP/diff_raw-attack2.txt` else NONE_STATUS_ATTACK2="0" fi ############################################################################### # # if diff is null, skip all process and exit # ############################################################################### if [ "$NONE_STATUS" = "0" ];then if [ "$NONE_STATUS_ATTACK" = "0" ];then if [ "$NONE_STATUS_ATTACK2" = "0" ];then touch $TMP/"$NOW_HOUR"-summary-hour_count_list.txt touch $TMP/count_list.txt touch $TMP/count_cmd.sh touch $TMP/min_ipfw_add_cmd.txt touch $TMP/min_ipfw_add_cmd_prev.txt touch $TMP/ipfw_added.txt touch $TMP/hour_ipfw_add_cmd.txt touch $TMP/hour_ipfw_add_cmd_prev.txt touch $TMP/"$NOW_HOUR"-hour_count_list.txt rm -f $TMP/"$PREV_HOUR"* exit fi fi fi ############################################################################### # #Exec for attack suddenly # ############################################################################### ############################################################################### # For IP resolv ############################################################################### if [ "$NONE_STATUS_ATTACK" != "0" ];then touch $TMP/min_ipfw_add_cmd-attack.txt cp -p $TMP/min_ipfw_add_cmd-attack.txt $TMP/min_ipfw_add_cmd_prev-attack.txt $CATPATH $TMP/"$NOW"_fail-attack.txt|$AWKPATH '{print $12}' | $AWKPATH -F"\]" '{print $1}' | $AWKPATH -F'\[' '{print $2}' > $TMP/count_list-attack.txt $SORTPATH -u $TMP/count_list-attack.txt >$TMP/count_list-attack.sort.txt cp -p $TMP/count_list-attack.sort.txt $TMP/count_list-attack.txt rm -f $TMP/count_list-attack.sort.txt $GREPPATH -v -f $TMP/ipfw_added.txt $TMP/count_list-attack.txt| $AWKPATH -v IPFW_NUM=`echo $IPFW_NUM` -v IF_NAME=`echo $IF_NAME` -v PORT=`echo $PORT` -v IPFWPATH=`echo $IPFWPATH` '{ print IPFWPATH" add "IPFW_NUM" deny tcp from "$1"/24 to any "PORT" via "IF_NAME}' > $TMP/min_ipfw_add_cmd-attack.txt $DIFFPATH $TMP/min_ipfw_add_cmd_prev-attack.txt $TMP/min_ipfw_add_cmd-attack.txt|$GREPPATH '^>' if [ "$?" = "0" ]; then $DATEPATH >> $TMP/defend-log $DATEPATH >> $TMP/defend-log.all $SHPATH $TMP/min_ipfw_add_cmd-attack.txt >> $TMP/defend-log $SHPATH $TMP/min_ipfw_add_cmd-attack.txt >> $TMP/defend-log.all $AWKPATH '{print $7}' $TMP/min_ipfw_add_cmd-attack.txt | $AWKPATH -v LOOKUP=`echo $LOOKUP` -F/ '{print LOOKUP" "$1}' > $TMP/defend-name-log-attack.cmd $CATPATH $TMP/min_ipfw_add_cmd-attack.txt > $TMP/min_mailbody-attack.txt $SHPATH $TMP/defend-name-log-attack.cmd >> $TMP/min_mailbody-attack.txt echo "by POSSIBLE BREAK-IN ATTEMPT ip-resolv" >> $TMP/min_mailbody-attack.txt $MAILPATH -s "SSH attack detected by minutes" $MAILTO < $TMP/min_mailbody-attack.txt ### to keep when reboot ### $CATPATH $TMP/min_ipfw_add_cmd-attack.txt >> $TMP/total_min_ipfw_add_cmd.txt ### check for double ### $GREPPATH -v -f $TMP/ipfw_added.txt $TMP/count_list-attack.txt >> $TMP/ipfw_added.txt fi fi ############################################################################### # For IP reverse map ############################################################################### if [ "$NONE_STATUS_ATTACK2" != "0" ];then touch $TMP/min_ipfw_add_cmd-attack2.txt cp -p $TMP/min_ipfw_add_cmd-attack2.txt $TMP/min_ipfw_add_cmd_prev-attack2.txt $CATPATH $TMP/"$NOW"_fail-attack2.txt|$AWKPATH '{print $7}' > $TMP/count_list-attack2.txt $SORTPATH -u $TMP/count_list-attack2.txt >$TMP/count_list-attack.sort2.txt cp -p $TMP/count_list-attack.sort2.txt $TMP/count_list-attack2.txt rm -f $TMP/count_list-attack.sort2.txt $GREPPATH -v -f $TMP/ipfw_added.txt $TMP/count_list-attack2.txt| $AWKPATH -v IPFW_NUM=`echo $IPFW_NUM` -v IF_NAME=`echo $IF_NAME` -v PORT=`echo $PORT` -v IPFWPATH=`echo $IPFWPATH` '{ print IPFWPATH" add "IPFW_NUM" deny tcp from "$1"/24 to any "PORT" via "IF_NAME}' > $TMP/min_ipfw_add_cmd-attack2.txt $DIFFPATH $TMP/min_ipfw_add_cmd_prev-attack2.txt $TMP/min_ipfw_add_cmd-attack2.txt|$GREPPATH '^>' if [ "$?" = "0" ]; then $DATEPATH >> $TMP/defend-log $DATEPATH >> $TMP/defend-log.all $SHPATH $TMP/min_ipfw_add_cmd-attack2.txt >> $TMP/defend-log $SHPATH $TMP/min_ipfw_add_cmd-attack2.txt >> $TMP/defend-log.all $AWKPATH '{print $7}' $TMP/min_ipfw_add_cmd-attack2.txt | $AWKPATH -v LOOKUP=`echo $LOOKUP` -F/ '{print LOOKUP" "$1}' > $TMP/defend-name-log-attack2.cmd $CATPATH $TMP/min_ipfw_add_cmd-attack2.txt > $TMP/min_mailbody-attack2.txt $SHPATH $TMP/defend-name-log-attack2.cmd >> $TMP/min_mailbody-attack2.txt echo "by POSSIBLE BREAK-IN ATTEMPT ip-reverse-map" >> $TMP/min_mailbody-attack2.txt $MAILPATH -s "SSH attack detected by minutes" $MAILTO < $TMP/min_mailbody-attack2.txt ### to keep when reboot ### $CATPATH $TMP/min_ipfw_add_cmd-attack2.txt >> $TMP/total_min_ipfw_add_cmd.txt ### check for double ### $GREPPATH -v -f $TMP/ipfw_added.txt $TMP/count_list-attack2.txt >> $TMP/ipfw_added.txt fi fi ############################################################################### # #Count per min # ############################################################################### $SORTPATH -u +10 $TMP/diff_raw.txt |$AWKPATH -v TMP=`echo $TMP` '{print "echo -n \""$11" \"; grep -c "$11" "TMP"/diff_raw.txt"}' > $TMP/count_cmd.sh $SHPATH $TMP/count_cmd.sh > $TMP/count_list.txt ############################################################################### # #Count per hour # ############################################################################### $CATPATH $TMP/count_list.txt >>$TMP/"$NOW_HOUR"-hour_count_list.txt $SORTPATH +1 $TMP/"$NOW_HOUR"-hour_count_list.txt |$AWKPATH '{if ( $1 == PREV ) { ADDR = $1; COUNT = COUNT + $2; PREV = ADDR;} else { ADDR = $1; print PREV" "COUNT; COUNT = $2 ; PREV = ADDR;} next} END {print $1" "COUNT}' >$TMP/"$NOW_HOUR"-summary-hour_count_list.txt ############################################################################### # #Process with threthold # ############################################################################### touch $TMP/ipfw_added.txt ### minutes ### touch $TMP/min_ipfw_add_cmd.txt cp -p $TMP/min_ipfw_add_cmd.txt $TMP/min_ipfw_add_cmd_prev.txt $GREPPATH -v -f $TMP/ipfw_added.txt $TMP/count_list.txt | $AWKPATH -v OK_PER_MIN=`echo $OK_PER_MIN` -v IPFW_NUM=`echo $IPFW_NUM` -v IF_NAME=`echo $IF_NAME` -v PORT=`echo $PORT` -v IPFWPATH=`echo $IPFWPATH` '{ if ( $2 > OK_PER_MIN ) {print IPFWPATH" add "IPFW_NUM" deny tcp from "$1"/24 to any "PORT" via "IF_NAME}}' > $TMP/min_ipfw_add_cmd.txt ### to keep when reboot ### $CATPATH $TMP/min_ipfw_add_cmd.txt >> $TMP/total_min_ipfw_add_cmd.txt ### check for double ### $GREPPATH -v -f $TMP/ipfw_added.txt $TMP/count_list.txt | $AWKPATH -v OK_PER_MIN=`echo $OK_PER_MIN` '{ if ( $2 > OK_PER_MIN ) {print $1}}' >> $TMP/ipfw_added.txt ### hour ### touch $TMP/hour_ipfw_add_cmd.txt cp -p $TMP/hour_ipfw_add_cmd.txt $TMP/hour_ipfw_add_cmd_prev.txt $GREPPATH -v -f $TMP/ipfw_added.txt $TMP/"$NOW_HOUR"-summary-hour_count_list.txt | $AWKPATH -v OK_PER_HOUR=`echo $OK_PER_HOUR` -v IPFW_NUM=`echo $IPFW_NUM` -v IF_NAME=`echo $IF_NAME` -v PORT=`echo $PORT` -v IPFWPATH=`echo $IPFWPATH` '{ if ( $2 > OK_PER_HOUR ) {print IPFWPATH" add "IPFW_NUM" deny tcp from "$1"/24 to any "PORT" via "IF_NAME}}' > $TMP/hour_ipfw_add_cmd.txt ### to keep when reboot ### $CATPATH $TMP/hour_ipfw_add_cmd.txt >> $TMP/total_hour_ipfw_add_cmd.txt ### check for double ### $GREPPATH -v -f $TMP/ipfw_added.txt $TMP/"$NOW_HOUR"-summary-hour_count_list.txt | $AWKPATH -v OK_PER_HOUR=`echo $OK_PER_HOUR` '{ if ( $2 > OK_PER_HOUR ) {print $1}}' >> $TMP/ipfw_added.txt ############################################################################### # # Execute IPFW # ############################################################################### $DIFFPATH $TMP/min_ipfw_add_cmd_prev.txt $TMP/min_ipfw_add_cmd.txt|$GREPPATH '^>' if [ "$?" = "0" ]; then $DATEPATH >> $TMP/defend-log $DATEPATH >> $TMP/defend-log.all $SHPATH $TMP/min_ipfw_add_cmd.txt >> $TMP/defend-log $SHPATH $TMP/min_ipfw_add_cmd.txt >> $TMP/defend-log.all $AWKPATH '{print $7}' $TMP/min_ipfw_add_cmd.txt | $AWKPATH -v LOOKUP=`echo $LOOKUP` -F/ '{print LOOKUP" "$1}' > $TMP/defend-name-log.cmd $CATPATH $TMP/min_ipfw_add_cmd.txt > $TMP/min_mailbody.txt $SHPATH $TMP/defend-name-log.cmd >> $TMP/min_mailbody.txt $MAILPATH -s "SSH attack detected by minutes" $MAILTO < $TMP/min_mailbody.txt fi $DIFFPATH $TMP/hour_ipfw_add_cmd_prev.txt $TMP/hour_ipfw_add_cmd.txt|$GREPPATH '^>' if [ "$?" = "0" ]; then $DATEPATH >> $TMP/defend-log $DATEPATH >> $TMP/defend-log.all $SHPATH $TMP/hour_ipfw_add_cmd.txt >> $TMP/defend-log $SHPATH $TMP/hour_ipfw_add_cmd.txt >> $TMP/defend-log.all $MAILPATH -s "SSH attack detected by hour" $MAILTO < $TMP/hour_ipfw_add_cmd.txt fi ############################################################################### # #Delete previous files # ############################################################################### rm -f $TMP/"$PREV_HOUR"* exit