【実務・中級編】LDAPインジェクション:ディレクトリサービスへの不正クエリ注入 – アプリケーションセキュリティ & 安全な開発防御ガイド

LDAPインジェクション:ディレクトリサービスの「裏口」を塞ぐ技術的流儀

エンジニア諸君、日々のアラート対応とデバッグ、お疲れ様。
今日は多くの現場が「死角」にしているLDAPインジェクションについて話そう。

「うちはSQLインジェクション対策は万全だ」と胸を張るエンジニアに限って、LDAP認証のロジックを見ると、ユーザー入力をそのままフィルタ文字列に連結しているケースが驚くほど多い。Active DirectoryやOpenLDAPは、アプリケーションの「鍵」を握る心臓部だ。ここを突破されるということは、権限昇格どころか、組織全体の認証基盤を乗っ取られることを意味する。

1. なぜLDAPインジェクションは「盲点」なのか

SQLiが「データベースのデータ」を狙うのに対し、LDAPiは「認証プロセスそのもの」や「ディレクトリ構造の可視化」を狙う。攻撃者は、特殊文字を注入することでフィルタの論理演算を書き換え、認証をパスしたり、存在しないはずのユーザー情報を引き出したりする。

例えば、ログインフォームのID入力欄に )(uid= を入力されたらどうなるか。
サーバー側のコードが以下のような単純な連結を行っていれば、LDAPクエリはこう変化する。

// 悪意のある入力後のフィルタ文字列
(&(uid=)(uid=)(userPassword=password))

結果として、パスワード認証をバイパスして先頭のユーザーでログインできてしまう。これが、LDAPiが「認証バイパスの特効薬」と呼ばれる所以だ。

2. 「エスケープすればいい」という甘い考えを捨てる

多くの初心者は「特殊文字を置換すれば大丈夫だろう」と考えるが、それは泥沼への入り口だ。LDAPの仕様は複雑で、検索フィルターのコンテキストによってエスケープすべき文字は変わる。

鉄則:自作の置換関数は100%バグる。必ず言語標準や著名なライブラリが提供するエスケープ関数を使うこと。

以下に、実務で即戦力となるセキュアな実装例を記す。

3. 実践:言語別のセキュアなフィルタ実装

Pythonでの実装例(ldap3ライブラリを使用)

PythonでLDAPを扱うなら、ldap3が業界標準だ。ここにはescape_filter_charsという強力な武器がある。

from ldap3.utils.conv import escape_filter_chars

def get_ldap_filter(username, password):
# ユーザー入力を安全にエスケープする
safe_username = escape_filter_chars(username)

# フィルタを構築。連結ではなくテンプレートに安全な値を流し込む
# 注意:パスワードも同様にエスケープを検討すべきだが、
# 本来はLDAPにバインド(認証)する際、フィルタでパスワードを比較する設計自体を見直すべきだ
return f”(&(uid={safe_username})(objectClass=person))”

JavaScript (Node.js) での実装例

ldapjsを使用する場合、ライブラリ側でエスケープを徹底するのが基本だ。

const ldap = require(‘ldapjs’);

// ユーザー入力をLDAPフィルタ用にエスケープする関数
function escapeLDAP(input) {
return input.replace(/[\\() \0]/g, (char) => {
return ‘\\’ + char.charCodeAt(0).toString(16).padStart(2, ‘0’);
});
}

const username = req.body.username;
const filter = (&(uid=${escapeLDAP(username)})(objectClass=person));
// あとはこのフィルタをsearchオプションに渡すだけ

4. アプリの外側で叩き落とす:WAFの役割

コード修正が間に合わないレガシーなシステムや、多層防御を構築したい場合、WAF(AWS WAF等)で不正なパターンを事前に遮断するのも有効だ。

AWS WAFのルール設定(Regex Pattern Setのヒント):
LDAPインジェクションを狙う文字列には、 や ( ) が多用される。以下の正規表現をベースに、アプリケーションの入力仕様に合わせてチューニングしてほしい。

  • パターン: \(\s[\\!&|]
  • 解説: ( で始まり、直後にスペースや論理演算子(&, |, !, “)が続くパターンは、LDAPフィルタの構造を破壊しようとする攻撃の兆候だ。

5. チーフからの最後のアドバイス

技術的な対策は上記で完璧だが、最も重要なのは「そもそもLDAPフィルタにユーザー入力を直接埋め込まない設計」にすることだ。

最近のアーキテクチャでは、直接LDAPを叩くのではなく、IDプロバイダー(IdP)や認可サービス(OAuth 2.0 / OIDC)を介する設計が主流だ。アプリケーションが直接LDAPを操作する機会を最小限に減らすことが、最大の防御になる。

「動けばいい」コードは、明日には脆弱性の温床に変わる。我々エンジニアの仕事は、コードを動かすことではなく、そのコードが「攻撃者の挑戦を跳ね返し続けること」にある。

現場からは以上だ。各自のプロジェクトで、今すぐフィルタの連結箇所をgrepしてみてくれ。もし「怪しい」と思ったら、すぐにリファクタリングに着手すること。健闘を祈る。

コメント

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