Skip to content

機械語モデルを汚染するMLflowのゼロデイ脆弱性をContrastが発見

    
機械語モデルを汚染するMLflowのゼロデイ脆弱性をContrastが発見

ほとんどの機械語(ML)ツールは、機械学習のライフサイクル管理に使用される開発フレームワークを含め、比較的新しいものであるため、セキュリティ上の脆弱性が存在する可能性がある。

TogglzのWebコンソールで2つのCVE(クロスサイトスクリプティング[XSS] CVE-2020-28192、クロスサイトリクエストフォージェリ[CSRF] CVE-2020-28191)が見つかった後、機械学習のライフサイクル管理のための開発フレームワークであるMLflow脆弱性の可能性があると考え、MLflowを調べることにした。

その通りだった。具体的には、content-typeヘッダのチェックに失敗する、API(アプリケーションプログラミングインターフェース)の設定ミスを見つけたのだ。つまり、攻撃者は、プリフライト(リクエストを送っても安全かどうかを判断するために、リクエスト自体の前に送信されるOPTIONSメソッドのHTTPリクエスト)をトリガーせずにlocalhostに対して単純リクエストを送ることができる。これは、より適当な「application/json」コンテンツタイプを使用するのではなく、「text/plain」コンテンツタイプを使用してMLflowで実行できることが分かった。

MLを軸とする企業にとっての脅威 

この結果が、MLモデルを脅かす非常に危険な脆弱性となる。攻撃が成功すると、MLモデルとすべてのトレーニングデータの両方が攻撃者に漏洩する可能性がある。これは、MLモデルを軸としている企業にとって存続の危機である。この脆弱性が悪用された場合、攻撃者はソフトウェアを作成する企業のソースコードへの書き込みアクセスができるのと同等のアクセス/制御を手に入れることができてしまう。

このCVEは、CVE-2023-43472と指定されたが、私はこれを2023年9月5日に報告しMLflowの作成元であり現在の管理者であるDatabricksに直接メールを送った。私はDatabricksに、11月24日(金)に開催されるDefCampセキュリティカンファレンスでこの問題について講演することを伝えた。11月29日の時点で、Databricksは今週末にリリース予定の修正パッチに取り組んでいると報告していた。

このCVE は、2.6.0以降の全てのバージョンのMLflowに影響し、そしておそらく全ての2.xバージョンに影響する。

MLflowがどれくらい広く使用されているか正確にはわからないが、GitHubで獲得したスターの数を見ると、KubernetesベースのKubeflowよりも人気がある。MLflowのスターは15.9Kであるのに対して、Kubeflowは13.2Kだ。ちなみに、先日CanonicalがCharmed MLflow MLopsプラットフォームを発表した際、Canonical製品管理担当副社長のCédric Gégout氏はMLflowを「すべてのMLステージを効率化する主要なAIフレームワーク」と呼んだ。

この脆弱性について

MLflowユーザーインターフェース(http://localhost:5000/)には、REST APIが含まれている。通常、これは単純リクエスト攻撃に対して脆弱ではない。POSTリクエストは application/JSONのコンテンツタイプを使用しており、プリフライトリクエストをトリガーするため脆弱とはならない。

しかしこの場合、PIはcontent-typeヘッダをチェックしない。そのため、text/plainのコンテンツタイプでリクエストをトリガーすることもできる。

上記のRequest/Response(リクエスト/レスポンス)に見られるように、リクエストボディは有効なJSONであるが、content-typeはtext/plainである。このリクエストは予期しないタイプであることから却下されるべきだが、どうやらAPIはコンテンツタイプをチェックしていないようだ。

これを利用して、JavaScriptを制御しているWebサイトにMLflowユーザをアクセスさせることができれば(例えば、MLfLowのチュートリアルWebサイトを作成するなどで)、Default Experimentを効率的に変更し、制御下にあってグローバルに書き込み可能なS3バケットをアーティファクトの場所に設定することができる。攻撃者はそれを使って、バケットに送信されたデータをすべて盗み出すことができる。


残念ながら、このAPIにはいくつかの機能が欠けている。APIを使用して、Experimentのartifact_uriを変更したり、Default Experimentを削除したりすることはできない。しかし、新しいExperimentを作成して既存のExperiment名を変更することは可能で、その場合に新しいExperiment名を「Default」にすることができる。

この攻撃は、以下のように実行できる:

  • DefaultのExperiment名を「Old」に変更する。

  • S3バケットのartifact_uriを指定して、「Default」という名前の新しいExperimentを作成する。

  • 新しいMLFLowの実行(例、mlflow run sklearn_elasticnet_wine -P alpha=0.5, experiment-name Default)が完了すると、実行の結果がS3バケットにアップロードされる。

ペイロードはこちらから入手可能

影響

この脆弱性により、攻撃者が自分の管理下にあるWebサイトにMLFlowユーザをアクセスさせることができれば、MLモデルのシリアライズバージョンやモデルのトレーニングに使用されたデータを盗み出すことができる。

ドライブバイローカルホスト攻撃による開発環境の攻撃

この脆弱性の背景を説明すると、localhostにのみバインドされているサービスには、外部からアクセスできないという考えが広まっている。残念ながら、これは必ずしもそうではない。開発者は便宜上、開発中のサービスを、よりセキュリティの高い環境で設定する方法(できれば設定したいが!)よりも、安全性の低い方法で設定してしまう。

開発者が使用するWebサイトを侵害すること(それらのサイトで提供される広告に単にJavaScriptを挿入したり、侵害したページで開発者にWebブラウザを開かせるフィッシング攻撃を行ったり)で、Springアプリケーションフレームワークの一般的な設定ミスを悪用するか、人気のJavaフレームワーク「Quarkus」で見つけて最近公開されたCVEなど、私が見つけた既知の脆弱性などを利用すれば、localhostにバインドされたサービスでプリフライトされていないHTTPリクエストを経由して攻撃が可能になる。

金曜日のDefCampの講演で説明したように、開発者のマシンやプライベートネットワーク上の他のサービス上でリモートコード実行(RCE)を生成することが可能だ。開発者がコードベース、AWSキー、サーバ認証情報などへの書き込みアクセス権を持っていることを考えると、開発マシンへのアクセスによって、攻撃者がネットワーク上の他のリソースに移動したり、コードベースを変更したり完全に盗み出すことができる可能性が高くなる。

悪用は容易

CVE-2023-43472を悪用するのは比較的簡単だ。攻撃者は、標的を自分の制御するWebサイトにアクセスさせるだけでよい。その時点で、攻撃者はデータの保存先を自分の制御下にあるS3バケットに黙って変更できる。

グローバルに書き込み可能なS3バケットにデータを送信するように悪用して、そこからデータを盗みだすことができる。

Amazon S3バケットは、あらゆる種類のデータを保存するために使用されるが、単にクラウド上にプログラムでデータを保存する方法に過ぎない。S3バケットが攻撃者によって作成され所有されていることを考えると、攻撃者が悪用した場合の被害の範囲を制限できるAWSのセキュリティガードレールは存在しない。

MLモデルに及ぼす影響

悪用が成功した場合、データの流出以上の事態になる可能性がある。MLモデルがバケットに保存されていることを考えると、MLモデルそのものが汚染される可能性がある。このような攻撃では、攻撃者はモデルのトレーニングプールに不正なデータを挿入し、学習すべきでないことを学習させることができる。

また、被害者がモデルを読み取った場合に、変更されたmodel.pklファイルにPythonのPickleにおける脆弱性が含まれている可能性もあり、被害者のマシンで RCEが発生する可能性がある。

対策

MLflowの利用者は、新しいバージョンが利用可能になり次第、すぐにアップグレードするべきだ。

お問い合わせ

Read more:

Contrast Security Japan