LDAPインジェクション:なぜ今さら「枯れた技術」の盲点を突かれるのか
現場でインシデント対応をしていると、「LDAPなんて古い技術でしょ? 今さら脆弱性なんてあるの?」という言葉を耳にすることがある。だが、これこそが攻撃者が最も好む「慢心」だ。
Active DirectoryやOpenLDAPは、企業の認証基盤の心臓部だ。ここにパッチの当たっていない古いコードや、開発者が適当に書いた文字列結合のクエリが一つ残っているだけで、攻撃者は組織全体のID情報を吸い上げたり、認証をバイパスして特権を奪取したりする。今日は、LDAPインジェクションの深淵を覗き、明日から使える「実戦的な防御」を叩き込む。
—
1. 攻撃者が狙う「LDAPの盲点」
LDAPインジェクションの本質は、SQLインジェクションと同じだ。「ユーザー入力をクエリの構造の一部として解釈させてしまうこと」に尽きる。
PoC:認証を無効化する悪意ある入力
例えば、ログインフォームで以下のようなクエリが生成されているとする。
(&(uid=ユーザー入力)(userPassword=パスワード入力))
もし、ユーザー名に admin)(uid= と入力されたらどうなるか。クエリはこう変化する。
(&(uid=admin)(uid=)(userPassword=パスワード))
LDAPサーバは、最初の (uid=admin) に合致するエントリを探し、残りの条件を無視、あるいは論理的に崩壊させて認証をスルーさせる。これが「認証バイパス」の典型例だ。さらに、攻撃者はワイルドカード “ を駆使して、ディレクトリ内の全ユーザー情報を総当たりで抜き出していく。
—
2. 実践的な防御策:エスケープか、ライブラリか
ここで重要なのは「中途半端なエスケープ」をしないことだ。よくあるのが、" や ' だけを置換する手法だが、LDAPの特殊文字はそれだけではない。
鉄則:LDAP専用のエスケープ関数を使う
言語標準のライブラリには、LDAPのフィルタリングに特化したエスケープ関数が必ず用意されている。これをバイパスすることは不可能だ。
PHPでの実装例
PHPの場合、ldap_escape 関数を必ず使う。第3引数の LDAP_ESCAPE_FILTER が肝だ。
Python (python-ldap) での実装例
Pythonでも同様に、ldap.filter.filter_format を使うのがベストプラクティスだ。文字列を結合してフィルタを作るのは今すぐやめよう。
import ldap.filter
ユーザー入力を安全にフォーマットする
filter_format は自動的に特殊文字をエスケープしてくれる
user_input = “admin)(uid=”
safe_filter = ldap.filter.filter_format(‘(&(uid=%s)(status=active))’, [user_input])
結果: (&(uid=admin\29\28uid=\2a)(status=active))
攻撃コードは無効化され、安全に検索が実行される
print(f”Safe Filter: {safe_filter}”)
—
3. インフラ層での「最後の砦」:WAFとIAM
アプリ側の改修が間に合わない場合や、多層防御の観点からWAFでのブロックも検討すべきだ。
WAF (AWS WAF / ModSecurity) の設定指針
LDAPインジェクションの特徴である「閉じ括弧 ) 」や「論理演算子 &, | 」、「ワイルドカード “ 」が連続して出現するパターンを正規表現で検出する。
- ルール例 (ModSecurity風):
rx "[()&|]{2,}"
※ただし、正規ユーザーの入力にこれらの文字が含まれる可能性を考慮し、アプリケーションの要件に応じてチューニングが必要だ。
IAM・ディレクトリ権限の最小化
どれだけコードを固めても、設定ミスは起きる。LDAPサーバーへの接続アカウント(Bind DN)には、「読み取り専用」かつ「必要なツリー範囲のみ」の権限を付与すること。ドメイン管理者権限でWebアプリを動かすのは、泥棒に家の鍵を渡して歩いているようなものだ。
—
最後に:プロの視点からのアドバイス
LDAPインジェクションは、SQLインジェクションほど派手に語られないが、だからこそ「管理画面」や「社内ポータル」の脆弱性として放置されがちだ。
開発チームにはこう伝えてくれ。
「ユーザー入力を信頼するな。そして、文字列結合でフィルタを作るな。ライブラリが用意した『箱(エスケープ関数)』の中にデータを入れてから渡せ」と。
セキュリティはパズルのようなものだ。1箇所でもピースが欠ければ、そこから崩壊する。まずは今、自社のコードベースで ldap_search や ldap.search を検索し、フィルタ生成部分が文字列結合になっていないかを確認することから始めてほしい。それが、最も安上がりで、最も効果的な「現場の防御」だ。
コメント