MicrosoftのAIバグハンターが、約11年間見過ごされていたRustの欠陥を発見

FORGE Labは、安定版Rustに存在するメモリ安全性の欠陥も特定しました。その中には、アプリケーションが解放済みメモリにアクセスする恐れのある問題も含まれます。

Microsoftの研究者らが、Rustの標準ライブラリに約11年間見過ごされていたメモリ安全性のバグを発見しました。あわせて、完全にセーフなRustだけで書かれたアプリケーションでも未定義動作を引き起こしうる欠陥も見つかっています。発見のうち2件は安定版Rustに影響し、その中には、アプリケーションが解放済みメモリにアクセスする恐れのある別の問題も含まれます。

約11年前から存在していたこのバグは、Rustのprocess::exit関数に関するものです。MicrosoftのFORGE Labの研究者らは、子スレッドからこの関数を呼び出すと、メインスレッドがまだ動作中であるにもかかわらず、ランタイムがメインスレッドの代替シグナルスタックを削除してしまう場合があることを突き止めました。その後メインスレッドでスタックオーバーフローが発生すると、OSがシグナルを正しく配信できず、Rustが本来想定しているスタックオーバーフロー処理ではなく、セグメンテーションフォールトが起きる可能性があります。

研究者らはブログ記事で、「process::exitのシグナルスタックに関するバグは、約11年間にわたって標準ライブラリに存在していました」と記しています。Microsoftによると、研究者らが調べた条件下では、確実に悪用できる経路は見つからず、実際に悪用される可能性は低いと評価しています。

この調査では、FORGE Labが開発したAI搭載の脆弱性スキャンシステム「Hyenas」を使い、Rust標準ライブラリ内のunsafeコードを調べました。Hyenasは、Microsoftのエージェント型脆弱性発見システム「MDASH」(コードネーム)の研究版にあたります。

Microsoftによると、バグの一部はHyenasの支援によって見つかりました。その後、研究者らが該当コードを精査し、問題を再現してセキュリティへの影響を評価したうえで、Rustのメンテナーに報告しています。

Microsoftは、実際のリスクは限定的だとしています。いずれの欠陥も、悪用には特殊な条件が必要です。研究者らは、標準ライブラリのバグが「深刻な脆弱性になるのは、実在するプログラムがそのような形でAPIに到達した場合に限られます」と述べています。

Rustの安全性保証に挑むunsafeコード

Rustの所有権モデルと型システムは、CやC++などの言語にありがちなメモリ安全性の問題を防ぐよう設計されています。しかし標準ライブラリは、コンパイラが検証できない処理のために、内部でunsafeコードを使っています。

VecやStringといったコンポーネントはこうした処理を利用しつつ、セーフなAPIとして公開しています。Microsoftによると、これらのAPIには厳格な健全性(soundness)の要件が課されています。「セーフなコードからどのように使われても、未定義動作を引き起こせないこと」です。

Microsoftは今回の発見を3つに分類しました。パニックが起きないと仮定しているunsafeコード、ユーザーが提供する実装が正しく動作すると信頼しているコード、そして基盤となるシステムについて誤った前提を置いているコードです。

1つ目は、RustのMapWindows::cloneの実装に見つかったパニック安全性の問題です。この関数は、バッファの内容を完全に初期化する前にバッファを作成し、その後ユーザー提供のclone処理を呼び出して中身を埋めていました。この処理でパニックが発生すると、Rustのアンワインド機構がバッファのデストラクタを呼び出し、初期化されていないメモリにアクセスしようとする恐れがあります。Microsoftによると、報告した修正案では、初期化が完了する前に、部分的にしか初期化されていないバッファが破棄されることを防ぎます。

もう1つの発見はstr::replaceに関するものです。研究者らは、この関数がナイトリー版のPatternトレイトのカスタム実装について、誤った前提を置いている場合があると指摘しました。カスタム実装がASCII文字を想定する箇所に非ASCIIバイトを渡すと、置換処理が不正なUTF-8データを生成してしまいます。Microsoftによると、その後の文字列操作で未定義動作が引き起こされる可能性があります。

安定版Rustに影響するシステムレベルのバグ

Microsoftによると、最初の2分類の弱点は、2021年の時点で、研究チームのメンバーが開発した静的解析ツール「Rudra」によってすでに研究されていました。標準ライブラリでも2015年の早い時期からパニック安全性の問題に対処してきましたが、同様の弱点は実装の中で現れ続けています。

3つ目の分類は、Rustと基盤のOSやCライブラリとの相互作用に関するものです。研究者らはprocess::exitの問題に加えて、プロセス全体で共有される環境変数配列を扱うRustのCommandExt::exec機能にも問題を見つけました。

Microsoftによると、この関数は読み取りロックを保持したまま共有状態を変更する場合があり、他のスレッドが不整合なデータにアクセスする可能性があります。特定の条件下で並行処理が行われると、環境ポインタが解放済みメモリを指したままになる恐れがあります。

Microsoftは、process::exitとCommandExt::execの両方の発見が安定版Rustに影響すると説明しています。環境変数の問題については、execveを直接呼び出して共有配列の変更を避ける修正案が提案されており、ブログの公開時点で審査中でした。

Microsoftのチームが報告した問題のうち2件は、公開時点で未解決のままでした。ブログでは、他の研究者からの関連報告や、審査中の修正についても取り上げています。

発見をMicrosoftのセキュリティ製品に還元

Microsoftは、今回の研究成果が、複数のエージェントが連携するセキュリティシステム「Microsoft Perception」にも活用できると説明しています。同システムでは、専門化したエージェントが幅広いセキュリティ業務にまたがって動作します。これにより、エージェント型の脆弱性発見をMicrosoft Defenderに取り込むMDASHの開発改善にも役立つといいます。

たとえば、MicrosoftのWeb App Pen Test AgentはMDASHの発見結果を使って、テストの優先順位付けや稼働中のアプリケーションに対する悪用可能性の評価を行えます。さらに、修復を支援する情報も提供できると、研究者らは記しています。

研究者らは、「私たちの目標は、単にバグをより多く見つけることではありません」と述べ、意義のある問題を特定し、開発者や組織が頼る基盤ソフトウェアの安全性を高めることが目的だと説明しました。CSOがコメントを求めましたが、執筆時点でRustプロジェクトからの回答はありませんでした。

翻訳元: https://www.csoonline.com/article/4246787/microsofts-ai-bug-hunter-finds-rust-flaw-that-went-undetected-for-nearly-11-years.html

本記事は csoonline.com の記事を翻訳・要約したものです。