1ヶ月くらい前からだったと思うが、弊社が管理しているWebサーバにPHPを狙ったスキャニングが定期的に発生している。
ログは大体こんな感じ↓
GET /mysqladmin/scripts/setup.php HTTP/1.1 with response code(s) 404 1 responses
GET /phpMyAdmin-4/scripts/setup.php HTTP/1.1 with response code(s) 404 1 responses
GET /phpMyAdmin-2.8.8/scripts/setup.php HTTP/1.1 with response code(s) 404 1 responses
GET /phpmyadmin/scripts/setup.php HTTP/1.1 with response code(s) 404 1 responses
GET /phpMyAdmin-2.8.4/scripts/setup.php HTTP/1.1 with response code(s) 404 1 responses
GET /phpMyAdmin-2.6.5/scripts/setup.php HTTP/1.1 with response code(s) 404 1 responses
GET /PMA2005/scripts/setup.php HTTP/1.1 with response code(s) 404 1 responses
GET /phpMyAdmin-2.3.1/scripts/setup.php HTTP/1.1 with response code(s) 404 1 responses
GET /phpMyAdmin-2.6.0-rc1/scripts/setup.php HTTP/1.1 with response code(s) 404 1 responses
GET /phpMyAdmin-2.11.3/scripts/setup.php HTTP/1.1 with response code(s) 404 1 responses
GET /phpMyAdmin-2.11.10/scripts/setup.php HTTP/1.1 with response code(s) 404 1 responses
・
・
・
そもそもウチではPHPは使ってないので、不正アクセスされる可能性はないのだけど、どうやらこのスキャンボットは定期的に巡回をしているらしく、多い日には3~4回くらい回ってくる。しかも1回の巡回で100回以上もスキャンをしてくるし、サーバも何台もあるので、毎日チェックしているログが見にくくなってきた。
そこで対策をしてみることにした。
- アプリケーションレベルゲートウェイの導入
- ApacheのDOS対策モジュール
- IDS/IPSの導入
複数のサーバを管理している関係で、もっとも理想的なのが1.である。しかしながら、現在利用しているFirewallではアプリケーションレベルゲートウェイ機能がないので、あたらしくアプリケーションレベルゲートウェイの導入が必要だし、そもそもネットワーク環境を変更する必要も出てきそうなので却下。
2.については、mod_evasiveというApacheに組み込めるDOS対策モジュールがあるらしいので、実際に導入をしてみたが、攻撃の検出方法が今回のスキャニングではうまく適用されないことが判明した。
理由はこうだ。
DOS攻撃は一般的に短期間に非常に多くのパケットを投げつけることで攻撃を行うため、mod_evasiveでは単位時間(たとえば1秒間)内に異なるコンテンツへ何回アクセスしたか、もしくはリロードしたかで攻撃を検出するようになっている。
ところが、今回のPHPスキャニングでは1秒間に3~4回と、実にゆっくりとしたペースでスキャンをかけてくるので、正常なアクセスとの区別が難しく検出自体ができないのだ。
3.については、IDSとして著名なsnortあたりを使う方法を検討したのだが、IDSはその仕組み上、アタックを検出することはできるがそれを防御(遮断)する機能はない。それを実現するのがIPSになるのだが、これは1.のアプリケーションレベルゲートウェイと同様、仕組みが大掛かりになってしまう。
これは困った。いっそ、アクセスしてくるファイルをこちらで偽装し、そいつにパケットを遮断させるプログラムを組み込むかと考えたときに、fail2banの存在を知った。
fail2banを簡単に説明すると、サーバ上の各種ログファイルを監視し、予め指定したパターンに一致したものを見つけたときに、予め決めておいたアクションを起こすことができるサービスである。
アクションにはIPTablesを使ったパケットの遮断の他、管理者へのメール送信なども用意されているので、今回の目的にもうまく合致しそうである。
実際の導入作業は、こちらのサイトを参考にさせていただいた。
Fail2banでDoSアタック/DoS攻撃 対策
Pythonのバージョンが2.3.4のCentOS4に実装する際はRPMのソースからコンパイルが必要。CentOS5ではPythonが2.4以降なので、そのままバイナリが適用可能であった。
具体的な設定であるが、今回はjail.confに[php-attack]というjailを作成してみた。検出後のアクションとしてはIPTablesによるパケット遮断と、検出通知メール送信の2つを組み込んである。
# Ban attackers that try to use PHP's attack(nosuichfile.php)
[php-attack]
enabled = true
port = http
filter = php-attack
action = iptables[name=PHPAttack, port=http, protocol=tcp]
mail[name=php-attack, dest=ここに自分のメールアドレス]
logpath = /var/log/httpd/access_log←Apacheのaccess_logの場所
bantime = 600←遮断時間は600秒
maxretry = 1
実際のフィルタはfilter.dフォルダ内に、php-attack.confという名前で以下のように作成した。
# Fail2Ban configuration file
#
# Author: Katsumi Takahashi
# Version 1
#
[Definition]
# Option: failregex
# Notes.: regex to match this kind of request:
#
# 193.27.193.XXX - - [01/Aug/2010:18:07:58 +0900] "GET /nosuichfile.php HTTP/1.1" 404 ・・・
#
#failregex = ^<HOST> -.*"(GET|POST) \/nosuichfile.php HTTP\/.*$←これはヤメ
failregex = ^<HOST> -.*"(GET|POST) .*.php HTTP\/.*$
# Option: ignoreregex
# Notes.: regex to ignore. If this regex matches, the line is ignored.
# Values: TEXT
#
ignoreregex =
この中の、failregexで指定した文字列が不正アクセスの検出パターンである。今回はスキャンボットが最初にアクセスしてくるnosuichfile.phpを使って検出するようにしてみた。
2010/8/9追記
どうやら今回のボットは、途中でパケットが戻ってこないことを検出すると、IPアドレスを動的に変更して続きをスキャンしてくることが判明。そのため、phpファイルにアクセスしてきたらとりあえず全て止めてしまうようにパターンを書き換えてあります。ただし、これだとphpを使っているサイトではすべてブロックされてしまうので、正規表現に詳しい方はちゃんとパターンを作っておくと良いでしょうw。
実際にパケットを遮断するタイミングだが、仕組み上ログに書き込まれてからでないと処理はできない。
そこで、fail2banがログをチェックするタイミングが重要になるのだが、これはjail.conf内の"backend"パラメータで指定が可能なようだ。
指定できるのは"gamin"、"polling"、"auto"の3種類である。もっとも高速(と思われる)のが"gamin"で、これはファイルの変更を監視するGaminサービスが別途必要となる。"auto"の指定+Gaminがない場合、もしくは"polling"を指定した場合は、fail2banが定期的にログをチェックしながら処理を行う。
今回はとりあえずデフォルトの"auto"で運用してみた。
<結果>
Gaminについては全く知識がなかったのだが、
yum list gamin
で確認してみたところ、CentOS5ではGaminサービスがインストールされているようだ。
ただし実際にはログをチェックするまでのタイムラグが発生しているようで、結果的にスキャンのいくつか(10~20程度)は遮断されずにログに載ってきてしまった。ただ、それでも対策前に比べれば圧倒的に減っているようだ。