LDAPインジェクションの基礎を手早く解説
2023年6月1日
0 分で読めますLightweight Directory Access Protocol(LDAP)は、Webアプリケーションを保護するための認証メカニズムです。LDAPは軽量で拡張性に優れているため広く利用されています。開発者にとって魅力的な特長ですが、その一方で、LDAPデータベースには価値の高い情報が大量に保存されることも少なくありません。そのため、攻撃者にとって格好の標的となります。
アプリケーションは、LDAPデータベースに保存された情報にアクセスしたり操作したりするため、ユーザー入力をもとにLDAPクエリを構築します。本来であれば、アプリケーションはユーザー入力を検証してサニタイズする必要があります。しかし、必ずしも実施されるとは限らず、その結果、こうしたクエリがLDAPインジェクションに対して脆弱になることがあります。
この記事では、LDAPインジェクションの仕組み、この種の攻撃がもたらす潜在的な影響、そしてアプリケーションを攻撃から守るためのさまざまな方法を解説します。
LDAPインジェクションの仕組み
LDAPクエリでは、引用符、アスタリスク、角括弧、アンパサンドなどの特殊文字で構成される述語を使って、クエリの意味を制御します。こうした特殊文字はメタ文字と呼ばれます。通常、クエリを作成してサーバーに送信する前に、入力値のサニタイズと検証を行います。しかし、入力検証が不十分な安全でない環境では、攻撃者が制御文字を改変し、クエリの意図した動作を変えてしまう可能性があります。
たとえば、ログインページで、最も広く利用されているLDAP実装の1つであるOpenLDAPを使ってデータベースへのアクセスを認証するために、USERとPASSWORDの入力を求めるとします。LDAPサーバーは、以下のような検索フィルターを使って、ユーザーが入力したUSERとPASSWORDの認証情報が、アクセスを許可された組み合わせの一覧に存在するかどうかを確認します。
Active Directory Application Mode(ADAM)の関数に関する技術的な制約により、この検索クエリを2つのフィルターに分割できない点に注意してください。つまり、次のようにはできません。
OpenLDAPは最初のフィルターだけを処理し、2つ目は無視します。そのため、認証情報を正しく入力したときに検索フィルターがTRUEと評価されるよう、AND(&)演算子が必要です。
ユーザー名とパスワードの組み合わせがデータベースに存在すると仮定すると、ユーザー名に「jsmith」、パスワードに「sec87pD02」を入力すれば、認証に成功します。
しかし、攻撃者がユーザー名jsmithしか知らない場合、ログインページのUSERフィールドに次の攻撃文字列を挿入できます。
そのため、ユーザー入力をサニタイズせずにLDAP検索クエリに挿入すると、クエリは次のようになります。
つまり、攻撃者はLDAPサーバーが処理する最初のフィルターを完成させています。&演算子を使う最初のフィルターがTRUEと評価されるため、スクリプトは2つ目のフィルターにある誤ったパスワードを無視し、データベースへのアクセスを許可します。
アクティブディレクトリを検索するLDAP構文フィルターは、攻撃者の主要な標的です。悪意のある攻撃者は、文字列値を使ってLDAPサーバーに特定のクエリやその他のLDAPステートメントを実行させ、不適切な権限や設定ミスを悪用するコマンドを挿入できます。権限の設定ミスによって、攻撃者がLDAPディレクトリにアクセスし、主要なLDAPデータ構造であるディレクトリ情報ツリーを侵害するおそれがあります。また、攻撃者はLDAPステートメントや、ユーザー入力からステートメントを生成するWebアプリケーションを改変することもできます。
LDAPインジェクション攻撃による被害
LDAPインジェクションは、アプリケーションやリソースへの不正アクセスを可能にし、ディレクトリ情報を侵害する危険なセキュリティ侵害です。攻撃者はさまざまな方法でLDAP攻撃を実行でき、それぞれが深刻な被害につながる可能性があります。
認証の回避
ディレクトリサービスを利用する主な目的の1つは、ユーザーを認可および認証することです。LDAPは、LDAPに対応するリソースやアプリケーションへのユーザーアクセスを制御します。アプリケーションやリソースにアクセスするには、ユーザー名やパスワードなどのログイン認証情報を入力します。LDAPはこの情報をLDAPディレクトリ内のデータと照合し、一致すればリソースへのアクセスを許可します。
LDAP攻撃では、パスワードのチェックを回避する手口がよく使われます。攻撃者は、ユーザー名を処理した時点でクエリが終了するようにコードを注入します。これにより、正しいパスワードを入力せずに、サーバーにLDAP認証を要求できます。たとえば、&、*、|などのメタ文字を使って認証を回避できます。
ログインを回避するLDAPインジェクション攻撃は、深刻な被害をもたらす可能性があります。攻撃者が管理者アカウントにアクセスすると、データ漏えいやプライバシー侵害につながります。最終的には、システム全体の侵害、評判の低下、訴訟や罰金、事業機会の損失による金銭的損害を招くおそれがあります。
データやリソースの漏えい
LDAPインジェクションによって、攻撃者はLDAPツリーに含まれる機器やユーザーに関する機密データを開示、改変、挿入、削除できる場合があります。LDAPインジェクション攻撃は、共有リソースの提供にLDAPフィルターを使用するアプリケーションに影響します。
悪意のある攻撃者は、LDAPフィルターコードを挿入したり、LDAPクエリを使ってディレクトリ内のすべてのリソースを一覧表示したりできます。これにより、機密情報を含む企業データが侵害される可能性があります。また、ディレクトリ内の情報が削除または追加されるなど、改変されるおそれもあります。攻撃者はディレクトリ情報を入手すると、ランサムウェア攻撃で機密データを脅迫の材料にすることがあります。
LDAPインジェクションからアプリケーションを保護する方法
LDAPインジェクション攻撃を防ぐ最善の方法は、アプリケーションを保護することです。次のベストプラクティスを実践すれば、アプリケーションのセキュリティを維持し、LDAPインジェクション攻撃が発生した場合の影響を抑えられます。
ユーザー入力を検証してサニタイズする
LDAPインジェクション攻撃への主要な防御策は、入力の検証とサニタイズです。アプリケーションは、POSTおよびGETパラメーター、Cookie、HTTPヘッダーなど、LDAPクエリに含まれるすべてのユーザー入力を検証する必要があります。また、無効と思われる入力は拒否するべきです。入力フィールドでメールアドレスを求める場合は、ピリオド(.)、英字、数字、アットマーク(@)、プラス記号(+)、アンダースコア(_)、ハイフン(-)に入力を制限できます。
クライアント・サーバー型アプリケーションでは、サーバー側での入力検証が必須です。クライアント側の検証は技術的には任意ですが、非常に重要です。サーバー側の検証によって、JavaScriptを無効にしてクライアント側の検証を回避し、データベースを漏えいさせたり、データを読み取ったり改変したりする攻撃を防げます。ユーザー入力を検証しないアプリケーションは、攻撃者がアプリケーションサーバー上の任意のファイルを読み取るディレクトリトラバーサル攻撃に対して脆弱になります。
最小権限の原則とゼロトラスト認可をディレクトリアクセスに適用する
最小権限の原則(PoLP)は、リソースへのアクセスに必要な最小限の権限だけを、必要な最短期間に限ってユーザーに付与するセキュリティ対策です。この原則により、ユーザーは自身の役割や責任を果たすために必要なリソースのみを、書き込み、実行、または読み取りできます。また、LDAPサーバーに対して実行されるすべてのLDAPクエリが認可されていることを保証します。LDAPインジェクション対策では、PoLPによって、アプリケーション内でディレクトリにバインドするLDAPアカウントへのアクセスを制限します。
LDAPバインドアカウントの権限を最小限にすることで、インジェクション攻撃が成功した場合の影響を抑えられます。さらに、ゼロトラストモデルを適用して、管理者が昇格された権限を使用できる期間を定義し、制限します。パスワードに加えて、LDAPに多要素認証(MFA)を導入することも検討してください。MFAを導入すると、アプリケーションにサインインするLDAPユーザーは、パスワードと追加の認証手段を提示する必要があります。
変数やLDAP構文をエスケープする
LDAPクエリを使った攻撃を防ぐもう1つの方法は、フレームワークが提供する関数とエスケープ済みの変数を使用することです。攻撃者は&、*、!、|などの文字を悪用してLDAPインジェクション攻撃を仕掛けるため、こうした特殊文字をエスケープしてユーザー入力をサニタイズできます。RFC 2254では、LDAP検索フィルターの文字列表現におけるアサーション値のエスケープ方法が説明されています。
LDAPインジェクションを防ぐ
攻撃者は、検証されていないユーザー入力を利用し、LDAPクエリのインタープリターに任意のクエリを実行させようとします。この手法はLDAPクエリの意図された構造を改変し、攻撃者が機密性の高いユーザー情報へ不正にアクセスできるようにします。
LDAPインジェクションを防ぐには、入力を適切に検証してサニタイズし、エスケープ済みの変数を使うとともに、PoLPとゼロトラスト認可ポリシーを徹底する必要があります。これらの方法によって、LDAPバインドアカウントへのアクセスを制御し、LDAPインジェクション攻撃の影響を最小限に抑えられます。LDAPインジェクション攻撃を完全になくすことはできませんが、こうしたベストプラクティスを実践することで、アプリケーションとユーザーデータを可能な限り安全に保つことができます。
