Brute Force Attack対策+α(iptables)
20160117

パスワードやファイル名に対してのブルートフォースアタック、総当り攻撃、辞書攻撃及びhttpサーバへのディレクトリトラサーバル対策

SSH、FTP、MAIL、HTTP、およびDNSサーバのログを定期的に監視し、攻撃元IPをiptablesに登録していくスクリプトを自動実行させます。
攻撃を検知してから何らかの処置を取る事から、簡易的ではありますがIPSのような動作となります。

ブラックリストは、CentOSで自宅サーバー構築様の「deny_ip」方式を採用します。
深くお礼申し上げます。

※Firewalldを利用の方は、Brute Force Attack対策(Firewalld)をご参照ください。
確認環境
 CentOS7.x
 CentOS6.x
 CentOS5.x
 Cron
 sshd
 vsftpd
 Postfix+Dovecot
 Apache
 BIND

頻繁にtmpファイルを作成する事から、「tmpfs(RAMディスク)」の設定も検討して下さい。
◆処理の流れ(デフォルトの場合)
 1.SSH、FTP、MAIL、HTTP、およびDNSサーバのログをCronにて1分毎に監視する。

 2.累計10回の不正アクセスの痕跡を確認した場合はIPレベルでのアクセス拒否を実施する。
 →「iptables -I INPUT -s 取得したIPアドレス -j DROP」及び、ブラックリストファイルに追加
 →不正なアクセスのログが無ければ処理の終了
 →ホワイトリストファイルにIPアドレスを1行ずつ記述する事で監視除外IPの指定が可能
 →HTTP監視においては、存在しないディレクトリ及びファイルの参照を試みる行為を監視します。
 →また、HTTP監視においては誤検知を減らす工夫が必要となる為、除外ディレクトリの指定が可能

 3.不正アクセスの痕跡を確認し、対処した事場合は詳細をログに保存

 4.上記内容をroot宛にメールで送信

→2011/12/18 実行速度の向上及び機能の追加に伴う不具合の発生等を考え、最初から作り直しました。

◆監視ログメッセージ
 SSH
  "Invalid user"
  "Failed password"

 FTP
  "FAIL LOGIN"

 MAIL
  "authentication failure"
  "auth failed"

 HTTP
  "File does not exist"
  "script" & "not found or unable to stat"
  "../"
  "//"

 DNS
  "denied"
◆まずはシェルスクリプトの作成
 [root@Server ~]# vi /root/brute_force_attack.sh

#!/bin/sh
export LANG=ja_JP.UTF-8

# Ver 20160115

# 攻撃判断回数(デフォルト10回以上)
NG="9"

# ログ監視の有効化設定 「no」で無効。(デフォルトは全て有効)
TELNET_CHECK="yes"
SSH_CHECK="yes"
FTP_CHECK="yes"
MAIL_CHECK="yes"
HTTP_CHECK="yes"
DNS_CHECK="yes"

# 監視ログファイル
SSH_LOG="/var/log/secure"
FTP_LOG="/var/log/vsftpd.log"
MAIL_LOG="/var/log/maillog"
HTTP_LOG="/var/log/httpd/error_log"
HTTP_LOG2="/var/log/httpd/access_log"
DNS_LOG="/var/log/named.log"

# HTTP監視除外ディレクトリ及びファイル設定(デフォルトでは「/home」ディレクトリ 以下に存在するファイル全て)
DIR="/home"

# 攻撃を検知した際にメールを送信するか否か。「no」で無効。(デフォルト有効)
MAILMESSAGES="yes"
# メール送信先アドレス。(デフォルトroot宛)
MAILADDRESS="root"

# 動作ログのファイル名
BR_LOG="/var/log/brute_force_attack.log"

# ホワイトリストファイルの指定
WHITE_LIST="/root/allow_ip"
# ブラックリストファイルの指定
BLACK_LIST="/root/deny_ip"
#BLACK_LIST="/etc/hosts.deny"
# →TCP Wrapperを使用する場合は後者

# 一時ファイル作成ディレクトリの指定
TMP_DIR="/tmp"

# 以降設定不要

# タイムスタンプ設定
LOG_DATE=`date '+%Y/%m/%d %k:%M:%S'`
# 一時ファイル設定
TMP="$TMP_DIR/brute_force_attack.tmp"
TMP2="$TMP_DIR/brute_force_attack2.tmp"
# フラグ管理
UP_FLAG=0

function_CORE()
{
if [ $1 = "TELNET" -a $TELNET_CHECK = "yes" ] ; then
SYSTEM_NAME="$1"
grep "login:" $SSH_LOG | grep "FAILED LOGIN" | grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+" > $TMP
elif [ $1 = "SSH" -a $SSH_CHECK = "yes" ] ; then
SYSTEM_NAME="$1"
grep "sshd" $SSH_LOG | grep "Invalid user" | grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+" > $TMP
grep "sshd" $SSH_LOG | grep "Failed password" | grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+" >> $TMP
elif [ $1 = "FTP" -a $FTP_CHECK = "yes" ] ; then
SYSTEM_NAME="$1"
grep "FAIL LOGIN" $FTP_LOG | grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+" > $TMP
elif [ $1 = "MAIL" -a $MAIL_CHECK = "yes" ] ; then
SYSTEM_NAME="$1"
grep "authentication failure" $MAIL_LOG | grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+" > $TMP
grep "auth failed" $MAIL_LOG | grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+" >> $TMP
elif [ $1 = "HTTP" -a $HTTP_CHECK = "yes" ] ; then
SYSTEM_NAME="$1"
DIR_LIST=`ls $DIR`
grep "error" $HTTP_LOG | grep "File does not exist" | grep -v "$DIR_LIST" | grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+" > $TMP
grep "error" $HTTP_LOG | grep "script" | grep "not found or unable to stat" | grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+" >> $TMP
grep "\.\./" $HTTP_LOG2 | grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+" >> $TMP
grep "//" $HTTP_LOG2 | grep -v http:// | grep -v https:// | grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+" >> $TMP
elif [ $1 = "DNS" -a $DNS_CHECK = "yes" ] ; then
SYSTEM_NAME="$1"
grep "denied" $DNS_LOG | grep -o "[0-9]\+\.[0-9]\+\.[0-9]\+\.[0-9]\+" > $TMP
else
touch $TMP
fi

cp -p $TMP $TMP2

if [ -s $WHITE_LIST ]; then
WHITE=`cat $WHITE_LIST`
grep -v "$WHITE" $TMP2 > $TMP
cp -pr $TMP $TMP2
else
touch $TMP
fi
if [ -s $BLACK_LIST ]; then
BLACK=`cat $BLACK_LIST`
grep -v "$BLACK" $TMP2 > $TMP
else
touch $TMP
fi

LIST=`cat $TMP`
for IP in $LIST
do
COUNT=`grep -w "$IP" $TMP | wc -l`
if [ $COUNT -ge $NG ] ; then
if [ -s $WHITE_LIST ]; then
if [ `grep -w "$IP" $WHITE_LIST` ] ; then
WHITE_FLAG=1
else
WHITE_FLAG=0
fi
else

WHITE_FLAG=0
fi
if [ -s $BLACK_LIST ]; then
if [ `grep -w "$IP" $BLACK_LIST` ] ; then
BLACK_FLAG=1
else


BLACK_FLAG=0
fi

else
BLACK_FLAG=0
fi

if [ $WHITE_FLAG -eq 1 -o $BLACK_FLAG -eq 1 ] ; then
:
else
echo "["$LOG_DATE"] ""[$SYSTEM_NAMEログ監視] IP をブラックリストへ登録:"$COUNT "回 ["$IP"]" >> $BR_LOG
echo $IP >> $BLACK_LIST
iptables -I INPUT -s $IP -j DROP
UP_FLAG=1
if [ $MAILMESSAGES = "yes" ] ; then
echo -e "[$SYSTEM_NAME]ログ監視にて、"$COUNT"回の不正なアクセスログを確認。\n対象ホストのIPアドレスをiptables及びブラッ クリストファイルへ追加しました。\n\nIPアドレス [$IP]"| mail -s "$0" $MAILADDRESS
fi
fi
fi
done
# IPTABLES更新時に設定を保存
if [ $UP_FLAG -eq 1 ] ; then
/etc/rc.d/init.d/iptables save
fi
# 一時ファイル削除
rm -rf $TMP $TMP2
}

# 実行
function_CORE TELNET
function_CORE SSH
function_CORE FTP
function_CORE MAIL
function_CORE HTTP
function_CORE DNS
◆一応実行権限を付与
 [root@Server ~]# chmod +x /root/brute_force_attack.sh
◆cronにて自動実行するよう設定しましょう。
 [root@Server ~]# echo "*/1 * * * * root bash /root/brute_force_attack.sh >/dev/null 2>&1" >> /etc/crontab

この場合、1分毎に監視して対処します。
変更する場合はcrontabにて設定を確認して下さい。

終わり。