
CVE-2024-38473 に対して脆弱な Apache サーバーを検出するための Nuclei テンプレート

CVE-2024-38473 に脆弱な Apache サーバを検出するために設計された Nuclei テンプレートです。まず、デフォルトの PHP-FPM 設定で Apache < 2.4.60 を実行しているサーバを特定します。次に、この脆弱性によりバイパスされる可能性のある ACL で保護された PHP ファイルをファジングします。
この Nuclei テンプレートを使用するには、リポジトリをクローンする必要があります。以下のコマンドを実行してクローンできます。
git clone https://github.com/juanschallibaum/CVE-2024-38473-Nuclei-Template
クローンしたリポジトリのディレクトリに移動します。
cd CVE-2024-38473-Nuclei-Template
単一ホストで nuclei テンプレートを実行:
nuclei -t CVE-2024-38473.yaml -u http://example.com
ホストのリストに対して nuclei テンプレートを実行:
nuclei -t CVE-2024-38473.yaml -l hosts.txt
単一ホストで、有効な .html または .php ファイルを指定して nuclei テンプレートを実行:
nuclei -t CVE-2024-38473.yaml -u http://example.com/valid.php
この方法で Nuclei を実行すると、検出率が向上する可能性があります。ホストファイルにこの形式の URL を含めて、そのリストに対してテンプレートを実行することもできます。
CVE-2024-38473 の脆弱性を簡単にテストするには、Docker を使用して脆弱な環境をセットアップできます。次の手順に従って、Nuclei テンプレートの有効性をすばやく確認します。
Docker デーモンが実行されていることを確認する: Docker デーモンがシステム上で実行されていることを確認します。実行されていない場合は、次のコマンドで起動できます。
sudo systemctl start docker
Docker コンテナを実行する: リポジトリディレクトリ内で、次の Docker コマンドを使用して、脆弱な Apache と PHP-FPM のセットアップを含むコンテナを起動します。
docker run -p 8787:80 -v "$(pwd)/test-env-webroot:/app" webdevops/php-apache:7.1
脆弱性をテストする:
手動で: Web ブラウザを開き、http://localhost:8787 に移動して、Docker コンテナ内で実行されている Apache サーバと対話します。http://localhost:8787/info.php にアクセスして脆弱性をテストします。このファイルは ACL で保護されており、ACL バイパスが成功すると、phpinfo() の出力が表示されます。

Nuclei テンプレートを使用: 次の Nuclei コマンドを実行して、テンプレートでサーバをテストします。
nuclei -t CVE-2024-38473.yaml -u http://localhost:8787
2024年8月8日、セキュリティ研究者の Orange Tsai は Black Hat USA 2024 で「Confusion Attacks: Exploiting Hidden Semantic Ambiguity in Apache HTTP Server!」と題したプレゼンテーションを行いました。このプレゼンテーションでは、Apache HTTP Server に影響する複数の脆弱性を報告しました。彼は、Apache が非常にモジュール化されたアーキテクチャを持ち、数百のモジュールで構成されており、各モジュールが request_rec と呼ばれる共有構造に対して読み取りと書き込みを行い、その構造はほぼ 100 のフィールドから構成されていることを説明しました。
このセキュリティ研究者によって報告された脆弱性の根本原因は、異なる Apache モジュールが共有構造のさまざまなフィールドを処理する方法の矛盾にあります。たとえば、mod_authz_core はフィールド r->filename をファイルとして扱いますが、mod_proxy はそれを URL として扱うため、不一致が生じ、さまざまな脆弱性が発生します。
プレゼンテーションの中で、Orange Tsai は「Filename Confusion」と呼ばれる攻撃の一種を定義しています。この攻撃の攻撃対象領域は多岐にわたりますが、このテンプレートで扱う CVE-2024-38473 は、「Filename Confusion」攻撃を適用して Apache ACL をバイパスし、制限されたファイルにアクセスする方法を示しています。
この問題は、Apache の認証モジュール mod_authz_core が r->filename 属性をファイルとして扱う一方、mod_proxy はそれを URL として扱うことに起因します。このため、デフォルト設定で PHP-FPM を使用する Apache インストールはこの脆弱性の影響を受けます。Apache と PHP-FPM を実行しているサーバで、admin.php ファイルへのアクセスを認証情報で保護するために次のような ACL が設定されていると想像してください。
<Files "admin.php">
AuthType Basic
AuthName "Admin Panel"
AuthUserFile "/etc/apache2/.htpasswd"
Require valid-user
</Files>
脆弱性により、上記のような個別のファイルを保護する ACL をバイパスすることが可能です。実際、次のリクエストを送信するだけで簡単に行えます: http://server/admin.php%3fooo.php。
これを深く理解するには、Apache が上記のようなリクエストを処理する際、mod_authz_core モジュールが共有構造の r->filename フィールドから admin.php?fooo.php という値を読み取ることを考慮する必要があります。このモジュールはこの値を要求されたファイルの名前として扱い、ACL と比較する際、admin.php?fooo.php は admin.php と異なるため一致しません。
次に、admin.php?fooo.php は .php で終わるため、リクエストは PHP-FPM によって処理されます。PHP-FPM は、Apache から受信したファイル名の ? 以降をすべて削除してから処理し、ファイルではなく URL として扱います。その結果、PHP-FPM は admin.php を直接処理します。ACL チェックは既に通過しているため、攻撃者は認証なしで admin.php にアクセスできます。
現在の Nuclei テンプレートは、ブルートフォースで保護されたファイルを発見するだけでなく、ACL で保護されたファイルのケースが検出されない場合でも、サーバが脆弱な Apache < 2.4.60 設定で PHP-FPM を使用しているかどうかを識別するロジックを含んでいます。基本的なフローでは、まずサーバに脆弱な設定があるかどうかを特定し、肯定的な場合、ACL で保護されている可能性のある一般的なファイルを特定しようと試みます。
脆弱な Apache < 2.4.60 と PHP-FPM の設定を検出する背後にあるアイデアは、2 つの基本的な前提に基づいています。
脆弱な設定では、サーバに file.php が存在する場合、http://server/file.php%3fooo.php へのリクエストは、http://server/file.php へのリクエストと同じ 200 ステータスコードと同じ本文長を返します(PHP-FPM が %3fooo.php を削除した後、要求されたファイルは同じになるため)。
脆弱な設定では、サーバに file.html が存在する場合、http://server/file.html%3fooo.php へのリクエストは 403 Access Denied を返します。これは、PHP-FPM が .php ではなく .html 拡張子のファイルをロードしようと試みるためで、デフォルトでは許可されていません。
テンプレートのフローは 7 つのリクエストグループで構成されています。これらは順番に実行する必要があり、それぞれの一致条件を満たして次のリクエストグループに進む必要があります。これにより、条件が満たされないことが既にわかっている場合に無駄に送信されるリクエストの数を最小限に抑えることができます。
テンプレートは、存在しないファイル index.phpooo.php%3fooo.php にリクエストを送信します。この目的は、index.php%3fooo.php が 200 ステータスコードを返し、index.php と同じ本文を返す場合でも、PHP-FPM が設定されていないケースの誤検知を除外することです。これは、例えば、要求されたファイルや "index" で始まるファイルを index.php に書き換えるルールがある場合に発生する可能性があります。
RewriteRule . /index.php [L]
RewriteRule ^index\.php(.*)$ index.php [L]
RewriteRule ^index(.*)$ index.php [L]
このリクエストは、上記のようなルールがサーバにある場合は 200 ステータスコードを返し、PHP-FPM が設定されている可能性がある通常の場合は 404 ステータスコードを返すはずです。このリクエストが 404 ステータスコードを返さない場合、テンプレートはこのホストでの処理を停止します。
テンプレートは、存在しないファイル foo.phpooo.php%3fooo.php にリクエストを送信します。この目的は、index.html%3fooo.php が 403 ステータスコードを返す場合でも、PHP-FPM が設定されていないケースの誤検知を除外することです。これは、例えば、URL 内の %3f 文字を禁止するルールや、.php で終わるファイルへのアクセスを制限するルールがある場合に発生する可能性があります。そのようなルールの例を以下に示します。
<FilesMatch "\.php$">
Require all denied
</FilesMatch>
RewriteCond %{REQUEST_URI} (%3f)
RewriteRule ^(.*)$ - [F]
このリクエストは、上記のようなルールがサーバにある場合は 403 ステータスコードを返し、PHP-FPM が設定されている可能性がある通常の場合は 404 ステータスコードを返すはずです。このリクエストが 404 ステータスコードを返さない場合、テンプレートはこのホストでの処理を停止します。
テンプレートは、サーバ上で利用可能ないくつかのファイルを特定するためにリクエストを送信します。まず、index.php が利用可能かどうかを特定しようとします。次に、index.html と index.htm をチェックします。最後に、ユーザーによって指定された URL に存在するファイル(存在する場合)をテストします。Nuclei が URL に有効なファイルを指定して実行された場合、従来のインデックスファイルが存在しないケースで検出効果を高めることができます。
テンプレートは、index.php%3fooo.php が 200 ステータスコードを返し、index.php と同じ本文を返す場合でも、PHP-FPM が設定されていない最後の誤検知を除外するために、存在しないファイルにリクエストを送信します。一部の Web サーバ、特に Apache ではないものは、%3f 以降をすべて無視します。そのため、index.php%3fooo.php を送信すると、サーバはそれを index.php として扱います。これらのケースを除外するために、テンプレートは index.php%3fooo.html(サーバで index.php が見つかった場合)または index.html%3fooo.html(サーバで index.html が見つかった場合)にリクエストを送信します。.html で終わるため、PHP-FPM が設定されている可能性がある通常のケースでは、PHP-FPM によって処理されず、論理的に存在しない静的ファイルとして扱われ、404 ステータスコードになります。しかし、除外したいケースでは、%3f 以降がすべて無視されるため、200 ステータスコードを返します。このリクエストが 404 ステータスコードを返さない場合、テンプレートはこのホストでの処理を停止します。
テンプレートは、脆弱な設定を特定するためにリクエストを送信します。2 つのケースがあり、少なくとも 1 つの一致条件が満たされる必要があります。
ケース 1: リクエスト #3 で index.php が見つかりました。この場合、Apache < 2.4.60 で PHP-FPM が有効でデフォルト設定の場合、%3fooo.php の部分を削除して index.php をロードし、リクエスト #3 で取得したものと同じ長さの 200 レスポンスを返すはずです。mod_php または別のハンドラが使用されている場合は、index.php%3fooo.php を完全なファイル名として扱い、404 を返します。このケースが一致するには、リクエストが 200 を返し、リクエスト #3 のレスポンスと同じ長さの本文を返す必要があります。
ケース 2: リクエスト #3 で index.html が見つかりました。この場合、Apache < 2.4.60 で PHP-FPM が有効でデフォルト設定の場合、%3fooo.php の部分を削除して index.html をロードしようと試み、403 Access Denied を返します。これは、PHP-FPM が許可されていない拡張子のファイルをロードしようとするためです。mod_php または別のハンドラが使用されている場合は、index.php%3fooo.php を完全なファイル名として扱い、404 を返します。このケースが一致するには、リクエストが 404 を返す必要があります。
テンプレートがこの時点に到達した場合、サーバに脆弱な設定があることを示します。そのため、テンプレートは、403 ステータスコードを返す可能性のある保護されたファイル、または認証が必要で 401 ステータスコードを返すファイルをファジングするためにリクエストを送信します。デフォルトでは、最も一般的で保護されている可能性のあるファイル名の一部のみを識別しようと試みます。ただし、コメントを解除すると、350 の可能な PHP ファイル名を含むカスタムワードリストを使用できます。
テンプレートは、リクエスト #6 で特定された保護されたファイルがバイパスを使用して 200 ステータスコードを返すことを検証するためにリクエストを送信します。
リクエスト #5 の一致条件のいずれかが満たされた場合、サーバがデフォルトの PHP-FPM 設定で Apache < 2.4.60 を実行していることを示します。つまり、個別のファイルを保護する ACL が存在する場合、それがバイパスされる可能性があります。ただし、これらの脆弱な設定は、保護されたファイルが特定されなくても検出できることがよくあります。デフォルトでは、テンプレートはワードリスト wordlists/potential_protected_php_files_10.php を使用して保護されたファイルをファジングします。このリストには、ACL で保護される可能性が最も高い上位 10 の PHP ファイル名が含まれています。あるいは、350 エントリのより大きなワードリスト wordlists/potential_protected_php_files_350.php も利用可能です。大きなリストに切り替えるには、テンプレートの リクエスト #6 の YAML セクションで、10 エントリのワードリストをコメントアウトし、350 エントリのリストのコメントを解除します。例:
#fuzz: wordlists/potential_protected_php_files_10.txt
fuzz: wordlists/potential_protected_php_files_350.txt
より大きなワードリストを使用すると、保護された PHP ファイルを見つける可能性が高まります。ただし、potential_protected_php_files_350.txt ワードリストには一般的でない PHP ファイル名が含まれている可能性があり、ACL で保護される可能性のあるより一般的な PHP ファイル名が欠けている可能性があります。そのため、ワードリストの改善や追加は歓迎します。さらに、より大きなカスタムワードリストを使用してさらに探索することもできます。
バイパス可能な ACL は、アプリケーションの任意のディレクトリの .htaccess ファイル内、ルートディレクトリだけでなく、異なる仮想ホストに対して設定される可能性があることに注意してください。したがって、ACL で保護されたファイルを特定する可能性を最大化するには、ディレクトリとサブドメインの徹底的な偵察を行い、異なるサブドメインとディレクトリを持つすべての特定された URL に対してテンプレートを実行することをお勧めします。
現在、リクエスト #6 のフローは、最初の ACL 保護ファイルを特定した後で停止します。しかし、他にも存在する可能性があります。これは、Nuclei で複数のファイルをファジングし、結果を保存し、それらをフォローアップリクエストで使用してバイパスが保護されたファイルへのアクセスを実際に許可するかどうかを確認する方法を見つけていないために発生します。したがって、テンプレートを変更して複数の保護されたファイルを特定し、それらが実際にバイパス可能であることを検証する方法についての提案も歓迎します。
脆弱性の報告と卓越した研究を行った功績はすべて Orange Tsai に帰属します。CVE-2024-38473 を含む Apache HTTP Server の脆弱性に関する彼の広範な研究は、セキュリティ意識の向上に大きく貢献しています。私は Juan Schallibaum が、CVE-2024-38473 のテストと検出を容易にするためにこの Nuclei テンプレートを作成した責任者のみです。
事前の相互同意なくターゲットを攻撃するためにこの Nuclei テンプレートを使用することは違法です。適用されるすべての地域、州、連邦法を遵守するのはエンドユーザーの責任です。開発者は、このテンプレートの使用に起因する誤用、損害、または法的結果について一切の責任を負いません。セキュリティテストを実施する前に、必ず明示的な許可を得てください。