Windows 10の重大なDHCP脆弱性を調査して、さらに2つのセキュリティエラーが発見された方法





画像: アンスプラッシュ



CVE-2019-0726に関する以前の記事で説明したように、既知の脆弱性に関する詳細を検索すると、新しい脆弱性が発見される場合があります。 また、場合によっては、このような新しい脆弱性が複数あります。



この記事では、dhcpcore.dllライブラリの2つの関数について説明しました。さりげなく言及したUpdateDomainSearchOptionと、それが呼び出すDecodeDomainSearchListDataのより詳細な分析です。 脆弱性を検索するときはいつもそうであるように、最後に重要な結論が1つまたは2つの機能に帰着したとしても、解析のプロセスでは、はるかに多くのコードを調べる必要があります。 そして時々、目は現在のタスクに関係のない些細な事にしがみついていますが、独立した重要性を持っているか、後で役立つかもしれません。 現時点では注意を払う時間がありませんが、そのような些細なことは皮質下に置かれ、一定期間後に彼らに戻って推測を確認する機会があれば、彼らは再び意識的に現れます。



そして、今回はそれが起こりました。 サーバーからのDHCP応答で指定されたすべてのオプションの処理、特にUpdateDomainSearchOptionの呼び出しを担当するDhcpExtractFullOptions関数を調べると、256要素のスタック上の2つの配列がすぐに注目を集めます。







同時に、これらの配列の反復子の値を制限するチェックの存在は目立ちません。 その時点で別の脆弱性を分析していたため、この情報は関係ありませんでした。 したがって、後で戻るために、コード内のこの場所を覚えておくだけでした。



分析



数週間が経過し、以前に注目されていたDhcpExtractFullOptions関数を思い出します。 逆アセンブラでそれを調べ、以前は不完全だったコードをとかし、興味をそそる2つの静的配列を使用している理由を理解しようとします。



関数実行の最初の段階で、配列とその反復子はゼロになります:







この関数は、DHCPサーバーから受信したパケット内のすべてのオプションを解析し、それらから情報を収集して処理します。 さらに、分析の結果に応じて、彼女は対応するイベントをETW(Windowsのイベントトレース)サービスに書き込みます。 対象のバッファが参加するのは、イベントロギングです。 他の多くのデータと一緒に、それらはEtwEventWriteTransferプロシージャに転送されます。 ロギング用のすべてのデータを準備する作業は非常に膨大であり、検討している脆弱性にとっては重要ではないため、図を使わずに実行できます。



これらのバッファがどのように満たされるかを決定することがより重要です。 充填は、オプション解析ループで行われます。 まず、ParseDhcpv4Optionという名前の関数が、処理のために受信した現在のオプションに対して呼び出されます。これは、受信したデータに基づいてdhcp_pointersオブジェクトのフィールドを埋めるか、ハンドラーのない値を持つオプション識別子に遭遇したときに不慣れなオプションについてメモします。







ParseDhcpv4Optionから戻ると、現在のoption_tagの識別子の値が、関心のある配列の最初のall_tags配列の次の要素に書き込まれます。 関数がなじみのないオプションを満たし、それに応じてis_known_optionフラグを設定しなかった場合、識別子の値は2番目の配列の次の要素であるunknown_tagsにも書き込まれます。 当然、この記事の変数の意味のある名前は、コードを分析することによってすでに取得されています。



したがって、all_tags配列には、受信したメッセージからのすべてのオプションのタグが格納され、unknown_tags配列には、パーサーになじみのないオプションのタグのみが格納されます。 同時に、これらの配列のインデックスの値をチェックすることは完全にありません。 その結果、このようなインデックスの値は256を超える可能性があり、メモリアレイのスタックに割り当てられた制限を超えて書き込みを行うことになります。 最初のアレイをオーバーフローさせるには、DHCPサーバーから256を超えるオプション数のパケットを送信するだけで十分です。2番目のアレイにも同じことが当てはまりますが、クライアントが処理できないオプションを送信する必要があります。



運営



実用的な例を使用して、結論が正しいことを確認してみましょう。 まず、オプションタグは1バイトを占有し、配列要素はint型、つまり4バイトであることに注意してください。 したがって、4バイトごとに制御するオーバーフローが発生し、残りは上書き時にゼロにリセットされます。







仮定をテストするための最も簡単な方法は、問題の関数のセキュリティCookieを上書きすることです。これにより、セキュリティチェックに関連する例外がスローされます。 DHCPサーバーが書き換えに十分な数のオプションを送信する状況をシミュレートしてみましょう。 識別子が0xaaでサイズがゼロの0x1a0(416)オプションとします。 したがって、各オプションは2バイトを占有し、すべてのヘッダーを含む合計パケットサイズは1100-1200バイトです。 この値はイーサネットのMTU内にあるため、メッセージが断片化されないと考えられる理由があります。これにより、考えられる悪影響を回避できます。



DHCPクライアントからの要求に応じて、説明した方法で形成されたパケットを送信し、クライアントマシン上の対応するsvchost.exeプロセスで例外をキャッチします。







スタックトレースからわかるように、スタックCookieと関数からの戻りアドレスの両方が、パッケージのオプションの識別子によって書き換えられました。



もちろん、このエラーに対して有効なエクスプロイトを作成するには、攻撃者の多大な努力が必要です。 最新のシステムでは、スタック上のバ​​ッファオーバーフローは、既存のすべての防御メカニズムにより、かなり複雑で労働集約的な脆弱性です。 一方、これらのメカニズムはすべて、リターンアドレスと例外ハンドラーの上書きを防ぐこと、これを目的としないメモリ領域でのコード実行を禁止すること、またはアドレス予測を妨げることを忘れてはなりません。 たとえば、オーバーフローしたバッファとローカル変数の戻りアドレスの間のスタックに保存されているものを上書きすることに対して、何の助けにもなりません。 また、問題のDhcpExtractFullOptions関数には、この間隔に潜在的に危険な変数がいくつか含まれています。



繰り返しますが、検出されたエラーについてマイクロソフトに報告します。 短い通信とアプリケーションの分析(約1週間かかりました)の後、説明された脆弱性に対してCVE識別子が準備され、3月に修正がリリースされる予定であり、脆弱性に関する情報が既にMicrosoftで利用可能であるという回答が以前に報告されました。 エラーは文字通り表面にあり、インデックスの境界チェックを含まないバッファは常に最初に注意を引き、多くの場合自動分析ツールで検出できるため、事実は驚くべきことではありません。



3月に発表されたとおり 、識別子CVE-2019-0697を受け取った記述されたエラーを修正するためのアップデートがリリースされました 。 先に情報を報告した研究者は、1月に修正されたDHCP脆弱性CVE-2019-0547を発見したマイクロソフトの従業員と同じMitch Adair でした



Posted by Mikhail Tsvetkov、アプリケーション分析のスペシャリスト、Positive Technologies。



All Articles