【実務・中級編】 PAM (Pluggable Authentication Modules) によるパスワードポリシーの強制 – インフラ・ネットワーク & クラウドセキュリティ防御ガイド

サーバーの「門番」を鉄壁にする:PAMによる認証要塞化とブルートフォースの葬り方

インフラエンジニア諸君、日々お疲れ様。OSの設定ファイルや認証周りの設定は地味だ。だが、ここが突破されれば、どんなに高級なWAFを積んでいようが、コードを難読化していようが、すべては「御用改め」だ。

今日は、Linuxサーバーの認証の心臓部である PAM (Pluggable Authentication Modules) を使い、攻撃者が最も好む「認証突破」の入り口を塞ぐ方法を解説する。教科書的な設定ではなく、現場で生き残るための「実戦的ハーデニング」の話だ。

—

1. なぜ「パスワードポリシー」は形骸化するのか

多くの現場で、パスワードポリシーは「形骸化」している。minlen=8 とだけ書いて満足していないか? それは、パスワードクラッキングツール(HashcatやJohn the Ripper)からすれば「どうぞお入りください」と言っているに等しい。

攻撃者は、辞書攻撃だけでなく、その企業のサービス名や地名を含めたパターンを数百万通り試してくる。pam_pwquality を用いて、最低限以下の基準を強制せよ。

設定ファイル: /etc/security/pwquality.conf

# パスワードの最小長(12文字以上は現代の鉄則)
minlen = 12
# クレジット(小文字、大文字、数字、記号をそれぞれ最低1文字ずつ強制)
dcredit = -1
ucredit = -1
lcredit = -1
ocredit = -1
# 辞書攻撃対策(ユーザー名や前回のパスワードと似ているものを拒否)
dictcheck = 1
# 同じ文字の連続(aaaなど)を禁止
difok = 3

現場の知見: ここでのポイントは minlen を12以上にすることだ。8文字程度では、GPUの計算能力にかかれば数分でハッシュが割れる。また、retry = 3 と設定することで、ユーザーの入力ミスを許容しつつ、不審な試行を早々に切り上げさせることも重要だ。

—

2. ブルートフォース攻撃を「無力化」する faillock

一昔前は pam_tally2 が主流だったが、今は非推奨だ。現代のLinuxディストリビューションでは pam_faillock を使うのが正解だ。こいつの真価は、攻撃者が「パスワードを当てる前に、アカウントをロックアウトして試行自体を停止させる」点にある。

設定例: /etc/pam.d/system-auth

(※ディストリビューションによりパスは異なるが、auth セクションが肝だ)

# 認証失敗を記録し、3回失敗したら10分間ロックする設定
auth required pam_faillock.so preauth silent audit deny=3 unlock_time=600
auth [default=die] pam_faillock.so authfail audit deny=3 unlock_time=600
auth sufficient pam_unix.so nullok try_first_pass
auth requisite pam_succeed_if.so uid >= 1000 quiet_success
auth required pam_faillock.so authsucc audit deny=3 unlock_time=600

注意点: 設定ミスをすると、SSHログインすらできなくなり、コンソールから復旧する羽目になる(通称:自爆)。必ず設定変更後は、現在のセッションを維持したまま、別ターミナルで ssh ログインを試すという「二段構え」でテストすること。

—

3. アプリケーション層での「認証バイパス」を防ぐ

OSを固めても、アプリケーション側の認証処理が甘ければ意味がない。特に、ログイン試行回数を制限せず、バックエンドで sleep も入れずにレスポンスを返しているWebアプリは、攻撃者の格好の練習台だ。

PHPで簡易的な「レートリミット」を実装する例を挙げておく。Redis等のキャッシュサーバーを使うのがベストだが、まずは基本からだ。

実装サンプル: PHPによるログイン試行回数制限

<?php
// セッションを利用した単純な試行制限(本番ではRedis推奨)
session_start();

$max_attempts = 5;
$lockout_time = 300; // 5分間

if (!isset($_SESSION['login_attempts'])) {
    $_SESSION['login_attempts'] = 0;
}

// ロックアウト判定
if ($_SESSION['login_attempts'] >= $max_attempts) {
    if ((time() - $_SESSION['last_attempt_time']) < $lockout_time) {
        die("セキュリティ保護のため、一時的にログインを制限しています。");
    } else {
        $_SESSION['login_attempts'] = 0; // 時間経過でリセット
    }
}

// ここで認証処理を実行
if (!$authenticated) {
    $_SESSION['login_attempts']++;
    $_SESSION['last_attempt_time'] = time();
    // 攻撃者への返答を遅延させて総当たり効率を落とす(Tarpitテクニック)
    usleep(500000); // 0.5秒のウェイト
    die("ログイン失敗");
}
?>

セキュリティの真髄: ここで重要なのは usleep による「遅延」だ。攻撃者のスクリプトは、1秒間に何千回もリクエストを送ってくる。レスポンスを0.5秒遅らせるだけで、攻撃効率は数百分の一に激減する。これはコストをかけずにできる、極めて泥臭くも強力な防御手法だ。

—

最後に:完璧なシステムなど存在しない

PAMの設定やログイン制限は、あくまで「攻撃の手間を増やす」ためのものだ。本当に恐ろしい攻撃者は、パスワードそのものではなく、セッションハイジャックやWebサーバーの脆弱性を狙ってくる。

だが、入り口を固めることは、侵入者の「足音」を大きくさせることにつながる。ログを監視し、pam_faillock が大量に反応しているアラートを見つけたら、それが「有事」の合図だ。

システムを要塞化せよ。そして、その要塞が発する警告に耳を澄ますこと。それが我々エンジニアに求められる、最低限のプロの流儀だ。

コメント

タイトルとURLをコピーしました