認証という行為は、システムにおける「信頼の起点(Root of Trust)」を定義するプロセスに他ならない。しかし、多くのエンジニアがOSの初期設定において、PAM(Pluggable Authentication Modules)を「単なる設定ファイルの一つ」として軽視している事実に、私は長年危機感を抱いてきた。
サイバー攻撃者は、パスワードの「文字列」を狙うのではない。彼らが狙うのは、認証プロセスにおけるメモリ上のバッファ、スタックの実行順序、そして管理者が無意識に許容した「認証の緩み」である。
今回は、Linuxサーバー要塞化の核心であるPAMを用いたパスワードポリシーの強制、そしてブルートフォース攻撃を無力化するためのpam_faillockの実装について、その低レイヤの挙動から将来的な脅威への備えまでを深く掘り下げていく。
—
1. PAMアーキテクチャの深淵:なぜ「スタック」が重要なのか
PAMは、アプリケーション(SSH、sudo、GUIログイン等)と実際の認証メカニズムを分離する抽象化レイヤである。ここで理解すべきは、PAMが「共有ライブラリ(.so)」の動的ロードによって機能し、設定ファイル内での記述順序がそのまま「評価の連鎖(Stacking)」になるという点だ。
例えば、requiredコントロールフラグは、そのモジュールが失敗しても後続のモジュールを実行し続けるが、最終的な結果は「拒否」となる。一方で、sufficientは、それ以前のrequiredが成功していれば、直ちに認証成功を返す。この評価ロジックの僅かな隙を突かれ、特定の条件下で認証をバイパスされる脆弱性(過去のCVE-2015-3238等)は、常にこの「スタックの解釈」に起因している。
2. pam_pwqualityによるエントロピーの強制
パスワードの複雑性は、単なる文字種の混在ではない。真の目的は、攻撃者のGPUクラスターによるオフライン・ブルートフォース計算における「計算コスト」を最大化することにある。
現代の攻撃者は、LLM(大規模言語モデル)を用いて、人間が作りがちな「意味のある単語の組み合わせ」を優先的に試行する。これに対抗するためには、pam_pwqualityを用いた厳格なエントロピー制御が不可欠だ。
実践的な設定例:/etc/security/pwquality.conf
単に「12文字以上」とするのではなく、辞書攻撃への耐性と履歴管理を徹底する。
# /etc/security/pwquality.conf の設定例
# 最小文字数は14文字以上を推奨(計算量的複雑性の確保)
minlen = 14
# 新しいパスワードに含まれるべき最小の文字クラス(英大、英小、数字、記号)数
minclass = 4
# 同一文字の連続制限(aaa などの繰り返しを阻止)
maxrepeat = 2
# 同種の文字クラスの連続制限
maxsequence = 3
# ユーザー名(逆読み含む)が含まれていないかのチェック
usercheck = 1
# 辞書ファイルとの照合(クラッキングツールで使われる単語を排除)
dictcheck = 1
# 過去のパスワードとの類似性(変更部分が少なすぎるのを防ぐ)
difok = 5
ここで重要なのは difok だ。これは「古いパスワードと最低何文字異なっている必要があるか」を定義する。メモリ上での文字列比較ロジックにおいて、ハッシュ化される前の生パスワードがどのように扱われるかを意識し、推測可能な微修正を許さない設計にする必要がある。
3. ブルートフォースへの物理的制約:pam_faillock の真価
かつては pam_tally2 が主流だったが、現在はより堅牢で、プロセスの再起動を跨いで状態を保持できる pam_faillock への移行が必須となっている。
攻撃者が数百万通りのパスワードを数秒で試行しようとする際、OSレイヤで「試行回数の閾値」を超えた瞬間に、そのアカウントをカーネルレベルの認証フローから切り離す。これが pam_faillock の役割だ。
認証スタックへの組み込み例
/etc/pam.d/system-auth または password-auth において、設定順序は極めてクリティカルである。
# auth セクションの冒頭に記述することで、無駄な処理をさせずに即座に拒否する
auth required pam_env.so
auth required pam_faillock.so preauth silent audit deny=5 unlock_time=900
auth sufficient pam_unix.so nullok try_first_pass
auth [default=die] pam_faillock.so authfail audit deny=5 unlock_time=900
auth required pam_deny.so
# account セクションでロック状態を確認
account required pam_faillock.so
パラメータの技術的背景
preauth: 実際のパスワード照合を行う前に、既にロックされていないかを確認する。これにより、無駄なハッシュ計算(CPUリソースの消費)を防ぎ、DoS攻撃耐性を高める。audit: 監査ログ(/var/log/audit/audit.log)に詳細を記録する。SOC(Security Operation Center)での分析において、このフラグがないログは無価値に近い。unlock_time=900: 15分間の冷却期間。これは攻撃者の自動化スクリプトの効率を著しく低下させる。
4. 監査とフォレンジック:攻撃者の足跡を辿る
設定して終わりではない。PAMの挙動は常に監視対象とするべきだ。攻撃者はしばしば、PAMの設定ファイルを書き換えてバックドアを作成しようとする。
faillock コマンドを用いた現在のロック状況の確認は、インシデントハンドリングの基本だ。
# 特定ユーザーの失敗回数を確認
faillock --user <username>
# 特定ユーザーのロックを手動で解除(正当なユーザーが締め出された場合)
faillock --user <username> --reset
また、/var/log/secure(または auth.log)において、pam_faillock が吐き出すメッセージを監視することで、分散型ブルートフォース攻撃の予兆を検知できる。単一IPからの攻撃ではなく、ボットネットを用いた「スロー・ブルートフォース(数時間に1回だけ試行する手法)」を検知するには、SIEM側での相関分析が必要となる。
5. 次世代の脅威:耐量子暗号とAIプロンプトインジェクションへの視点
我々セキュリティアーキテクトが次に備えるべきは、耐量子暗号(PQC)への移行と、認証フロントエンドにおけるAIの悪用だ。
1. パスワードハッシュの計算コスト: 現在の sha512(libcrypt)は強力だが、量子コンピュータの実用化を見据え、より計算コストの高い yescrypt への移行が始まっている。PAMの設定においても、ハッシュアルゴリズムの選択は未来の安全性を左右する。
2. 生成AIによるソーシャルエンジニアリング: パスワードポリシーが厳格になればなるほど、攻撃者は「人間」という脆弱性を突く。パスワードリセットのワークフロー(PAMが直接関与しない部分)にAIを用いた詐称が介入するリスクを考慮し、PAMでの多要素認証(MFA)モジュール(pam_google_authenticator.so 等)の併用を標準構成とすべきだ。
結論
PAMによるパスワードポリシーの強制は、インフラセキュリティにおける「衛生管理」である。しかし、その中身は高度な条件分岐と共有ライブラリの連鎖で構成された精密機械だ。
pam_pwquality でエントロピーを担保し、pam_faillock で物理的な試行回数を制限する。この二段構えを、単なる設定作業としてではなく、システムのメモリ保護とリソース管理の一環として捉え直してほしい。攻撃者は常に、あなたが「デフォルトで十分だろう」と妥協したその1行を狙っている。
コメント