
このリポジトリには、CVE-2019-0217 の概念実証エクスプロイトと、この CVE に対して脆弱な Web サーバーをセットアップするための Dockerfile が含まれています。
Apache HTTP Server 2.4 リリース 2.4.38 以前において、スレッドサーバー上で実行されている場合の mod_auth_digest の競合状態により、有効な認証情報を持つユーザーが別のユーザー名を使用して認証し、設定されたアクセス制御の制限を迂回できる可能性があります。
クライアントが HTTP ダイジェスト認証の背後にあるリソースにアクセスしようとすると、サーバーは 401 ステータスコードとともに、おおよそ以下の形式の WWW-Authenticate ヘッダーで応答します。
Digest realm="rlm", nonce="TToc8M0jBgA=7afa4f292c97632a6c17eec458d3db31021b111f", algorithm=MD5, qop="auth"
クライアントは HA1 を計算します。HA1 は A1(つまり username:realm:password)の md5 ダイジェストであり、そこに nonce や cnonce などの他のメタデータを追加して A2 を取得します。その md5 ダイジェストが HA2 となり、クライアントはこれを response として、username、cnonce、その他のメタデータとともに Authentication ヘッダーで送信します。
'Digest username="attacker", realm="rlm", nonce="TToc8M0jBgA=7afa4f292c97632a6c17eec458d3db31021b111f", uri="/scripts/userprofile.cgi", response="bcb433e4071fa228fe0c9452a7495efd", algorithm="MD5", qop="auth", nc=00000001, cnonce="2309510923095109"
^^^^^^^^^^
以下で説明するように、上記ヘッダーの強調表示された部分を操作して、エクスプロイトが機能するために必要な競合状態を作り出すことができます。
この脆弱性はこのコミットによって修正されました。
mod_auth_digest モジュールのコード(具体的には mod_auth_digest.c の get_hash 関数)を見ると、サーバーがまず Authentication ヘッダーを解析して username= の後の引用符内にあるものを特定し、それをリクエストに関連付けられたユーザー(r->user)として扱うことが明らかです。次に、この「ユーザー」が要求されたリソースにアクセスできるかどうかを確認します。アクセスできる場合、get_hash 関数は認証ファイルから対応する HA1 を取得します。
脆弱性修正コミット以前は、このようにして取得された HA1 は conf = (digest_config_rec *) ap_get_module_config(r->per_dir_config,&auth_digest_module) 変数に格納されていましたが、これは明らかにスレッドセーフではありません。
これにより、次のエクスプロイトが可能になります。
上記の脆弱性分析のセクションに基づくと、有効な Authentication ヘッダーを持つリクエストと、偽造された Authentication ヘッダー(有効なヘッダーと同じですが、username= の値がターゲットユーザー(攻撃者がなりすまそうとするユーザー)に設定されているもの)を持つリクエストを同時に送信することで、競合状態を作り出すことができるはずです。
このエクスプロイトで使用される用語: - 攻撃者: このエクスプロイトを実行するユーザー。自分のアカウントの有効なユーザー名とパスワードを持っています。 - 被害者: 攻撃者がなりすまそうとするユーザー。被害者のユーザー名は既知ですが、パスワードは(当然ながら)不明です。
私は、一方のタイプのリクエストを送信するものともう一方のタイプのリクエストを送信するものを含む多数の Python スレッドを大量に送りつけることでこの方法を実行できましたが、信頼性が低く、成功させるには大量のリクエストが必要でした。 そのため、リクエストを確実に並列送信できる burp の turbo intruder(無料)を使用することにしました。残念ながら、turbo intruder の CLI サポートは壊れているため、エクスプロイトの一部は GUI を使用して実行する必要があります。
このリポジトリに含まれているサンプルの脆弱なサーバーを使用するには、次を実行します。
$ cd sample_vulnerable_server
$ docker build -t poc_httpd .
$ docker run -p 8038:80 poc_httpd
generate_turbo_intruder_script.py を実行し、上部の変数を設定します。
# Configuration
URL = 'http://localhost:8038/scripts/userprofile.cgi' # location to the resource protected by digest auth
ATTACKER_USERNAME = 'attacker'
ATTACKER_PASSWORD = 'known'
VICTIM_USERNAME = 'victim'
NUMBER_OF_REQUESTS = 2000 # number of concurrent requests sent to catch a glimpse of the race condition
このスクリプトは、現在のディレクトリに generated/turbo_intruder_script.py と generated/request.txt の 2 つのファイルを生成します。
次に、BurpSuite Community Edition を開き、まだインストールしていない場合は、拡張機能 -> BApp Store に移動して「Turbo Intruder」拡張機能をインストールします。
burp repeater を開きます。ターゲットのホストとポートを設定します。

generated/request.txt の内容を Request セクションに貼り付けます。

Request セクション内の任意の場所を右クリックし、「拡張機能->Turbo Intruder->Send to Turbo Intruder」を選択します。

generated/turbo_intruder_script.py の内容をスクリプトセクションに貼り付けます。

最後に、Turbo Intruder ウィンドウの下部にある Attack ボタンをクリックします。成功した結果があれば、表示された画面に表示されます。
