HTTPサーバのログ解析からアタックを検出する簡易ツールを作ってみた

Webサイトを運用しているとアタックや如何わしいアクセスを調べたいときがあります。簡単にHTTPサーバのアクセスログから短い間隔で大量にアクセスしているホストを、諸々のコマンドで操作するのは面倒なので、簡単に検出できるツールがあると便利です。
探してみたところ簡単に扱えそうなものがなかったので、Rubyベースで作ってみました。

Detect HTTP Attack

https://github.com/tilfin/detect-http-attack

Ruby 1.9 系で動きます。依存するライブラリはないので、直ぐにコマンドラインで実行できます。標準入出力で処理しているのシェルのパイプラインに組み合わせることができます。

準備
$ git clone https://github.com/tilfin/detect-http-attack.git
$ cd detect-http-attack
$ ./detect_http_attack.rb --help                                       
Usage: detect_http_attack [options]
    -ltsv                            Log type is LTSV
    -n                               notify when detecting attack
    -s COUNT                         Specify minimum sequential count
    -i SECONDS                       Specify maximum interval seconds
    -f CONFFILE                      Specify configuration file
対応するログフォーマット
  • Apache, Nginx Combined Log (Common Logもそのまま無いフィールドが空になる)
  • LTSV format (引数に -ltsv を付加) http://ltsv.org/
使い方

引数で検出する最大のアクセス間隔(秒)と、その間隔で連続した回数を引数で渡すと、それに適合するアクセスを標準出力します。

例えば、2秒以内の間隔で5回以上連続でアクセスがあった場合を検出するときは次のようにします。(デフォルトは3秒以内の間隔で8回以上連続で検出)

./detect-http-attack.rb -s 2 -i 5 < /var/log/apache/access_log
10.128.192.255   7   Mozilla/3.0 (windows)
2012-12-20T08:25:28+09:00       200     /admin/phpmyadmin/scripts/setup.php     -
2012-12-20T08:25:28+09:00       200     /wp-content/plugins/wp-phpmyadmin/phpmyadmin/scripts/setup.php  -
2012-12-20T08:25:28+09:00       200     /mysql/scripts/setup.php        -
2012-12-20T08:25:28+09:00       200     /phpmyadmin2/scripts/setup.php  -
2012-12-20T08:25:28+09:00       200     /pma/scripts/setup.php  -
2012-12-20T08:25:28+09:00       200     /phpmyadmin/scripts/setup.php   -
2012-12-20T08:25:28+09:00       200     /myadmin/scripts/setup.php      -
2012-12-20T08:25:28+09:00       200     /phpMyAdmin/scripts/setup.php   -

通常は、ホストごとにブロックで出力しますが、-n フラグを付けると標準エラーに検出したアクセス毎に出力します。ターミナルで下記のように実行すれば、検出したアタックを適宜表示しつつ、まとめた結果をファイルに書き出すことができます。

$ tail -f /var/log/nginx/access.log | ./detect-http-attack.rb -n > /tmp/detect.log
設定

detect_http_attack.conf で設定します。判定から除外するアクセスは、ホストとURLパスそしてユーザーエージェント(User-Agent)を条件に指定できます。

# Excluded hosts (comma-separated)
exc_hosts=127.0.0.1

# Excluded User-Agent (regular expression with ignored case)
exc_ua_match=bot|google

# Excluded path (regular expression)
exc_path_match=\.(js|css|jpg|gif|png|ico)$

ホストはカンマ区切りのリストで、ユーザーエージェントとパスは正規表現のマッチになります。
出力フォーマットに関してもこのファイルでテンプレートを設定できます。head, body, foot の3つで1アタックのログを構成しています。serr で -n フラグ指定時の通知用フォーマットを定義できます。

とりあえず自分で使うには十分なところまで来たので公開しました。LTSVは流行に乗って対応(出力をLTSVにするときの設定もconfにコメントアウトしてあります。)