PHP 2022年03月22日 19:42   編集
PHP/用語集作成 PHP/掲示板PHPにブルートフォース攻撃対策処理を追加しましたが、他にも使えるかもしれないと思ったので、対策処理部分をモジュールにしました。
login_ver1.05.zip (38Download)
ver.1.01		2021.07.27	メール送信機能を追加。function send_mail追加
ver.1.02 2021.07.28 メール送信のルールを整理。ロックディレクトリの大文字小文字を識別するように修正。
ver.1.03 2021.08.06 関数外で指定した変数が反映されない場合があるのを修正。
ver.1.04 2021.08.10 utf-8以外の文字コードのPHPファイルから呼び出す場合、IDやパスワードが日本語だとうまく動作しないのを修正。
ver.1.05 2022.03.22 若干修正。
総当たり攻撃はユーザー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 = '';
で指定します。
戻る

bbs.phpのヘルプ

掲示板を作成する
■ファイルアップロード、返信、過去ログ生成、隠しパラメータ送信によるスパム投稿対策、スライドロックによるスパム投稿対策
オプションは[[bbs('lock=1|max_log=100|item=thread')]]のように指定

指定できるオプション

form (現在の設定はform=up)
form=up(フォームを上に表示) form=down(フォームを下に表示)
item (現在の設定はitem=time)
デフォルトの記事表示順を指定
item=time(投稿順) item=thread(スレッドごとに表示)
max_log (現在の設定はmax_log=100)
現行ログの保存数。これを超えると過去ログに移動。
例 max_log=50
max_past (現在の設定はmax_past=100)
過去ログに保存する記事数。これを超えると過去ログファイルを新たに作成。
例 max_past=100
page_line (現在の設定はpage_line=10)
1ページに表示する記事数。これを超えると次のページに表示
例 page_line=10
lock (現在の設定はlock=1)
スライダで投稿ボタンをロックする lock=1で表示する
例 lock=1
perm_tag (現在の設定はperm_tag=)
許可するタグ。複数ある場合は;(セミコロン)で区切る。
有効になるのはタグ名だけを<>で囲った場合とその閉じタグだけ。styleなどは指定できない。
例 perm_tag=pre;h1
nameless (現在の設定はnameless=id)
投稿者名未入力で投稿した場合、表示される名前を指定。'id'にすると、日付とIPアドレスを元にしたIDを表示
例 nameless=id
titleless (現在の設定はtitleless=無題)
タイトル未入力で投稿した場合、表示されるタイトルを指定。
例 titleless=タイトルなし
hide_bbs (現在の設定はhide_bbs=1)
デフォルトでフォームと投稿内容を隠す hide_bbs=1で隠す
例 hide_bbs=1
show_text (現在の設定はshow_text=)
添付したtextファイルの内容を表示する show_text=txt;phpのように表示するテキストファイルの拡張子を指定する。複数ある場合は;(セミコロン)で区切る
例 show_text=txt;log

[1]IPアドレスを変えながら攻撃してくる場合、指定回数ごとに緊急解除ワードを挟んで試行することによって非常ドアからの連続攻撃が可能になります。
IPアドレス固定の場合は、緊急解除ワードを使ってもIPアドレスのロックは解除できません
counter:7,087