PHP 2024年07月30日 02:02   編集
PHP/用語集作成 PHP/掲示板PHPにブルートフォース攻撃対策処理を追加しましたが、他にも使えるかもしれないと思ったので、対策処理部分をモジュールにしました。
login_ver.1.06.zip (12Download)
総当たり攻撃はユーザーIDを固定して複数のパスワードでの認証を試みるブルートフォースアタックと、逆にパスワードを固定して複数のユーザーIDでの認証を試みるリバースブルートフォースアタックというのがあるということなので、このモジュールでは同じIDあるいは同じパスワードで10分間にに3回ログインに失敗したら60分間ログインをロックします。 ロック期間は認証を受け付けないので、正規ユーザーもログインできなくなります。デフォルトのロック時間は60分ということにしていますが、許容回数やロック時間はオプションの引数で変更できます。

使いたいphpスクリプトにfunction部分をコピペするか、
require_once('./login.php');
などでモジュールファイルを読み込んだ上で、パスワード認証処理部分を
login('ユーザーID', '入力したパスワード', 'ハッシュされたパスワード')
に置き換えます。
function login()は認証が成功したら0、失敗したり、ロックされたらそのメッセージを返します。たとえば以下のように使用します
$check = login('ユーザーID', '入力したパスワード', 'ハッシュされたパスワード');
if (!$check) {
print "パスワードOK";
// 処理継続
} else {
// エラーメッセージを表示する場合、phpスクリプトの文字コードがutf-8以外の場合は文字コード変更の必要があります。
// たとえば使用するスクリプトの文字コードがeuc-jpの場合、
// $check = mb_convert_encoding($check, ''utf-8, 'euc-jp');
// を追加します。
print $check;
// 処理中断
}
login()の引数は、ユーザーID照合するパスワード暗号化された(ハッシュ化された)パスワードが必須です。
以下オプションで、ロックファイルを作成するディレクトリ(デフォルトは./login)、許容する失敗回数(デフォルトは3)、チェックする時間(秒、デフォルトは600)、ログインをロックする時間(秒、デフォルトは3600)を指定できます。

デフォルトのロック時間は短いような気もしますが、なんの対策もしていない場合、ブルートフォースが1秒間に4回攻撃できるとしたら1日に3600×24×4=34万5600回の攻撃を仕掛けられるのに対して、このモジュールで3回失敗するたびに3600秒ロックされる場合、3×24=72回しか攻撃できないことになります。「へたな鉄砲も数撃ちゃ当たる」方式のブルートフォースに対して数を抑えるということは、それなりに効果があると思います。function login()で行っている処理は、
  1. 期限の切れたロックディレクトリがあれば削除する
  2. ロックディレクトリが存在すれば処理を中断する
  3. パスワードの照合を行い、失敗したら
    1. ユーザーID、パスワード、IPアドレスのチェック用ディレクトリが存在しなければ作成
    2. ログイン失敗回数を各ディレクトリ内のカウントファイルに書き込み、失敗回数が指定回数に達するとロックディレクトリを作成
という感じです。
アカウント、パスワード、IPアドレスについて、該当するロックディレクトリがあれば、そのアクセスは拒否します。
ブルートフォース攻撃を受けてロックされたアカウント、パスワードのログ保存、閲覧もできます。

強制ロック解除

アカウントやパスワードがロックされると正規ユーザーもログインできなくなります。IPアドレスを偽装して攻撃される可能性があるので、失敗したIPアドレスだけでなくすべてのアクセスをロックしているからです。
使用しているアカウント名やパスワードがロックされたということは、それをターゲットとしたブルートフォース攻撃を受けたということなので、アカウントやパスワードの変更を促すべきですが、管理者アカウント名など簡単に変更できない場合もあるので、緊急ログイン手段も用意しました。
パスワード入力欄に緊急解除ワードを入力すると、そのIPアドレスのみ通す非常ドアを開きます。非常ドアを通して認証を受け付けるので、改めて正しいアカウント、パスワードを入力してログインします。ロックそのものは継続しているので、ブルートフォース攻撃が続いていてもそのブロックは有効なままです。非常ドアの有効期間は設定したロック時間と同じです。

緊急解除ワードは使用しているメインのスクリプトかlogin.phpで
変数$emergency_unlockに設定します。未設定の場合は'緊急解除'が使用されます。
この緊急解除ワードが攻撃側に知られると、連続攻撃が可能になる[1]ので、取り扱いには注意が必要です。

メール送信機能

メール送信機能を追加しました。指定時間内に指定回数以上攻撃がブロックされると、登録したメールアドレスに、ブロックした攻撃のログファイルを添付した警告メールが送信されます。
$send_mail = 1;
メールの送信先を
$mail_adress = '';
メールの送信元を
$from_adress = '';
で指定します。
[1]IPアドレスを変えながら攻撃してくる場合、指定回数ごとに緊急解除ワードを挟んで試行することによって非常ドアからの連続攻撃が可能になります。
IPアドレス固定の場合は、緊急解除ワードを使ってもIPアドレスのロックは解除できません
counter:36,013