サイバー脅威
Azure Machine Learning サービスに潜むセキュリティリスク - パート3
機械学習サービス「Azure Machine Learning」のマネージドIDに紐づくトークン情報が攻撃者に盗み出され、長期的に不正利用されるリスクについて解説します。
機械学習サービス「Azure Machine Learning(AML)」に焦点を当てた前回の記事では、当該サービス上で作成した「コンピューティングインスタンス(CI)」のクラウドエージェントに潜む脆弱性について解説しました。この脆弱性が攻撃者に利用された場合、CI経由で機密情報を流出させられる可能性があります。シリーズ第3回目にあたる本稿では、AMLワークスペースで作成したマネージドIDのトークン情報が攻撃者に盗み出され、長期的に不正利用されるリスクについて解説します。
CI上でAzure CLIを利用
開発目的でクラウドサービスを利用する際に直面する課題の1つとして、アクセスキーやシークレット、パスワードなどの認証情報をいかに管理するか、という点が挙げられます。単純に認証情報をクラウド上のファイルやコードに記載しただけでは、システム侵害などの異常時に、その内容が流出する可能性があります。対策として、AzureのマネージドIDサービスでは、ファイルやコードに頼ることなく認証情報を管理する方式が提供されています(図1)。本方式において、ユーザやアプリケーションが他のリソースにアクセスする際には、マネージドIDサービスから「Entra ID」のトークンを取得し、これによって認証の手続きを行います。
マネージドIDのサポート対象はAzureの各種サービスに及び、その中にはAMLも含まれます。AMLのユーザは、「CI」や「コンピューティンググラスタ」といったコンピューティング・ターゲットに対し、「システム割り当て」または「ユーザ割り当て」のマネージドIDを設定できます。さらに、他のAzureサービスにアクセスできるように、作成したマネージドIDにRBAC(Role-Based Access Control:ロールベースのアクセスコントロール)の権限を手動で付与することも可能です。
ユーザは、CI上でAzureコマンドラインインターフェース(CLI)を用いることで、他のAzureリソースを作成、管理できます。CIの割り当て済みマネージドID、またはオーナーとしてサイン・インする際にも、Azure CLIが利用可能であり、これによってAzureの各種サービスを利用できるようになります(RBACの権限設定による)。割り当て済みマネージドIDとしてサイン・インする際には、図2のコマンド「az login –identity」を使用します。
実際にコマンド「az login --identity」を実行した際に発生する通信トラフィックを監視したところ、下図のようなリクエストデータが確認されました。
図3の通り、本リクエストは、ローカルインターフェース「127.0.0.1」のポート「46808」に送信されます。実際にCI上で当該ポート「46808」を待ち受けているプロセスを調べたところ、systemd(システムデーモン)のサービス「identityresponderd」が確認されました。本サービスは、AML上の全CIにインストールされ、「Azure Batch AI Identity Responder Daemon」という名称が付与されます。サービスの動作を調べたところ、パラメータ「EnvironmentFile」で指定されたファイルを参照し、そこから環境変数を読み取ることが確認されました。
上図のパラメータ「EnvironmentFile」に対応するファイル「/etc/environment.sso」には、図5の通り、2つの環境変数「MSI_ENDPOINT」、「MSI_SECRET」が定義されています。これらの変数は、GETリクエストの作成、送信時に使用されます。
しかし、上図の環境変数は依然としてローカル・エンドポイントを指したものです。そこで、サービス「identityresponderd」による外向き通信を分析した結果、パブリック・エンドポイントに相当する環境変数「certurl」が、ファイル「/mnt/azmnt/.nbvm」から発見されました(図6)。本サービスのバイナリは、当該エンドポイントにアクセスするために、x509証明書と秘密鍵の双方を組み合わせて利用します。
図4のサービス設定を見ると、バイナリによる標準出力や標準エラーの書き出し先ファイルとして、「syslog(システムログ)」が指定されています。こうしたログの内容は、サービスの基本的な機能や動作を知る上での有効な手がかりとなります。実際にコマンド「az login –identity」を起動してsyslogの内容を調べたところ、図7の通り、環境変数「certurl」で定義されたエンドポイントが確かに記録されていました。
以上の情報をもとに、パブリックエンドポイント宛ての最終的なリクエストデータを手動で作成しました(図8)。
上記のPOSTリクエストに対する応答として、先述した認証用の「Entra ID JWT(JSON Webトークン)」が得られました。この点から導かれるシナリオとして、仮に何らかの形でCIから証明書や秘密鍵が流出した場合、攻撃者はそれを用いることで、CIに割り当てられたIDに紐づくEntra ID JWTを盗み出すケースが考えられます。場合によっては、Azure以外の環境からIDの窃取を試みるかも知れません。さらに、環境変数「certurl」に定義されたエンドポイントのURLは、インターネット上からでも、名前解決が可能な状態となっています。こうした点も踏まえ、本攻撃シナリオについては、入念に調査を行う必要があると考えられます。
本攻撃シナリオを検証するために、実際にCIの証明書と秘密鍵を用いてEntra ID JWTの取得を試みたところ、401エラー(権限不足)が返されました。そのため、調査当初は、CIの内部からしか証明書や秘密鍵を利用できないように、適切に管理されていると想定されました。さらに、x509証明書のフィンガープリントがCI毎に異なることも確認されました。
しかし、別のサービス「dsimountagent」にも視野を広げて調査した結果、上記の想定は必ずしも正しくないことが判明しました。以降、この点について詳しく解説します。
サービス「dsimountagent」の詳細
サービス「dsimountagent」の役割は、AMLワークスペース内にある「ストレージアカウント」の共有ファイルをCI側にマウントし、その状態を維持することです。具体的には図10の通り、120秒(2分)毎に、マウントの状態をチェックします。
図11に、本サービスに関するsystemdの設定情報を示します。内容に基づくと、本サービスは、さまざまな環境変数をファイル「identityresponderd」などから取得し、先述のサービス「identityresponderd」と同様に、標準出力や標準エラーをsyslogに書き出します。共有ファイルをCI側にマウントする際には、以下の環境変数で定義されたパブリック・エンドポイントにリクエストを送り、対象ストレージアカウントのアクセスキーを取得します。
AZ_BATCHAI_XDS_ENDPOINT
このキー値のペアは、以下のファイルに保存されます。
/mnt/batch/tasks/startup/wd/dsi/dsimountagentenv
実際に、本ブログシリーズの第1回目にあたる調査では、当該ファイルからストレージアカウント用アクセスキーが平文状態で発見されました。
サービス「dsimountagent」は、先述の「identityresponderd」と同様に、x509証明書と秘密鍵を用いてパブリック・エンドポイントにアクセスします。今回は、パブリック・エンドポイントに対するリクエストの分析結果に基づき、図12のPOSTリクエストを手動で作成しました。
上図では、可読性のためにヘッダーの先頭数行を除去してあります。本POSTリクエストに対する応答データの内容を調べたところ、ストレージアカウントやkey vault(鍵データを保管する仕組み)、コンテナレジストリ、Application Insights(パフォーマンス管理ツール)のリソースIDに加え、テナントIDやサブスクリプションID、CI用VNetが外部公開されているか、などのメタデータも含まれていました。これは言わば、AMLワークスペースに対する「whoami(自端末に関する情報を取得するためのコマンド)」と見なせます。
調査中、図12に類似したリクエストが発見され、URIやエンドポイントが同じである一方、「RequestType(以降リクエストタイプを呼ぶ)」として「getworkspacesecrets」が設定されていました。応答データの中身を調べたところ、ストレージアカウントの名前、ストレージアカウント用アクセスキーの暗号化済みJWE(JSON Web Encryption)が格納されていました。本JWEは、以下の2つの環境変数によって復号可能です(図13)。
AZ_LS_ENCRYPTED_SYMMETRIC_KEY
AZ_BATCHAI_CLUSTER_PRIVATE_KEY_PEM
また、当該の2変数は、デーモン用の環境変数を取りまとめるファイル内に定義されています。
本リクエストについては、CIの外部から発信した場合でも、正常に受け付けられました。この点より、システム侵害などによって証明書や秘密鍵が流出すれば、攻撃者はそれを利用し、CIの外部からでもストレージアカウントのアクセスキーを盗み出せる可能性があります。
ストレージアカウント用アクセスキーが流出した際の対処として、当該アクセスキーを変更(ローテーション)することが挙げられます。しかし、アクセスキーの変更後も、証明書や秘密鍵が攻撃者の手にある限り、当該キーが再度盗み取られる場合があります。この点については、下記の動画から確認できます。
上記の2ケースより、POSTリクエストのキー「リクエストタイプ」を変えることで(getworkspace、getworkspacesecrets)、得られる応答データも変化することが分かりました。この点より、リクエストタイプとして指定できる値が他にも存在するか、その場合にどのような応答データが得られるか、という疑問が浮かび上がります。証明書と秘密鍵が外部に流出した場合、攻撃者はさまざまなリクエストタイプを試し、多岐にわたる情報の入手を目論む可能性があります。以降、リクエストタイプのバリエーションを分析した結果について解説します。
リクエストタイプのバリエーション
シリーズ第2回目の記事で述べた通り、サービス「dsimountagent」のバイナリには、デバッグ情報が埋め込まれていました。分析に基づくと、リクエストタイプ「getworkspace」や「getworkspacesecrets」を設定する関数(処理)は、パッケージ「hosttools」に定義されています。これらの関数は、POSTリクエストの本体を作成するために、さらに別の以下の関数を呼び出します。
generateXDSApiRequestSchema
以上を踏まえて今回は、当該関数の呼び出し元をdsimountagentやidentityresponderdなどのサービス内から洗い出し、そこから、リクエストタイプとして設定できる値のバリエーションを調べました。結果を下記に示します。
- GetAADToken
- GetACRToken
- GetACRDetails
- GetAppInsightsInstrumentationKey
- GetDsiUpdateSettings
- GenerateSAS
上記のように、調査観点から目を引く候補が複数発見されました。以降、特に「GetAADToken」を分析した結果について解説します。
割り当て済みマネージドIDのEntra IDトークンを取得
今回、リクエストタイプ「GetAADToken」を含むPOSTリクエストを、手動で作成しました(図14)。本リクエストは、システム割り当てマネージドIDの取得に使用されるものです。
ユーザ割り当てマネージドIDを対象とする場合は、図15のように、クライアントIDを含める必要があります。
応答データには、CIに割り当てられたマネージドIDのEntra ID JWTが含まれます。今回はCIの外部からリクエストを送信したにも関わらず、目的とするJWTの取得に成功しました。この結果は、マネージドIDの公式文書(図16)に記載された設計方針と相反するものです。
マネージドIDは、コード内に認証情報を載せないようにするための仕組みです。この仕組みにおいて、特定のリソースにアクセスしたいアプリケーションは、マネージドIDサービスからトークンを取得します。本来、マネージドIDサービスを利用できるのは、マネージドIDを割り当てたリソースに限定されます。例えば、マネージドIDをAzure Virtual Machine(VM)に割り当てた場合、マネージドIDサービスを利用できるのは、当該のAzure VMに限定されます。ネットワーク構成としても、外部から到達できない「169.254.169.254」などのリンクローカルIPアドレスが使用されます。
トレンドマイクロでは以前にも、サーバーレス機能「Azure Function」に同種の問題がある旨を報告し、アプリケーション用コンテナの環境変数から証明書情報が流出するリスクについて述べました。ここで攻撃者が当該の証明書を入手すれば、アプリケーション用コンテナの外部からであっても、割り当て済みマネージドIDのEntra ID JWTを取得できるようになります。
攻撃発生時におけるログの見え方
クラウド・ネイティブのログ情報は、セキュリティ・インシデントの検知や対応だけでなく、コンプライアンスや監査においても重要な役割を果たします。今回、ログの内容に基づいて正規なリクエスト(CI内部から)と不正なリクエスト(CI外部から:先述した証明書の鍵ペアを利用)を区別できるかを確認するため、実際に両方式を用いてシステム割り当てマネージドIDのEntra ID JWTを取得しました。
不正なリクエストは、CI外部のさまざまな場所から送信される可能性があります。今回は、先述の証明書と秘密鍵を用いてJWTを取得しました。正規なリクエストと不正なリクエストによって生成されたサイン・イン用ログを比較したところ、両者はほぼ同一であり、ID、関連ID、トークン識別子以外の差異は見られませんでした。
さらに、ログには送信元IPアドレスなどが記載されないため、トークンの配布依頼がどこから来たのかを具体的に知るすべがありません。IPアドレスがマネージドIDのサイン・イン用ログに記録されない点については、すでに、ログ仕様の改善要求として知られています。IPが記録されない理由として、サイン・イン処理そのものが、Azureにシークレットの管理を任せているリソース側で実行されるためと想定されます。しかし、本調査では、マネージドIDを割り当てたリソースの外部からでも、認証情報(証明書と鍵ペア)を利用できることが判明しました。
証明書と鍵ペアを無効化するには、AMLワークスペースから当該のCI自体を削除する必要があります。また、証明書と鍵ペアを変更する方法については、現状、確認されていません。こうした制約の背景には、AMLがマネージド・サービスであるという認識のもと、認証情報はMicrosoft側で管理するという方針があると考えられます。また、当該証明書の有効期間は、CIの作成から2年間とされています。
情報公開の履歴
CIが提供する各種APIに潜む本脆弱性について、トレンドマイクロでは、ゼロデイ・イニシアチブ(ZDI:Zero Day Initiative)を通してMicrosoft側に報告しました。以下に、ZDI-23-1056の報告履歴を示します。
- 2023年4月7日:ZDIが本脆弱性についてベンダー側に報告
- 2023年4月11日:ベンダーが報告を受理
- 2023年7月13日:ZDIが進捗に関する説明を依頼
- 2023年7月19日:ベンダーが本件に関する会議への参加を要請
- 2023年7月19日:ZDIが会議に参加し、本件に関する追加情報を提供
- 2023年7月20日:ベンダーが本件の影響度を「低」と分類し、30-45日以内に修正をリリースする予定であることを通知
- 2023年7月20日:ZDIがベンダーに対して本件のクローズ日を2023年8月5日とし、8月9日にはゼロデイ勧告を公表する旨を通知
トレンドマイクロは、本件についてサイバーセキュリティ会議「Black Hat USA 2023」で報告する予定でしたが、収録前の時点で、本脆弱性が依然として修正されていないことが判明しました。Microsoft側に問い合わせたところ、本脆弱性の影響度は低いと認識している旨の回答がありました。しかし、後にMicrosoft側から要請があり、この時点ですでにZDIの開示期限である90日を経過し、バグが依然として再現可能な状態でしたが、詳細情報を伏せる形での発表を行いました。
2024年1月、Microsoftより、本脆弱性が修正された旨の報告がありました。現在では、CI外部から証明書の鍵ペアを利用できないように制御されています。
まとめ
認証情報やそのライフサイクルの適切な管理は、サイバーセキュリティの鍵と言えます。AMLワークスペースでは、MLモデルやデータセット、スクリプト、ログ情報が共有ファイルやBLOBコンテナに保存されるため、ストレージアカウントの保護は特に重要です。AMLのワークスペースをデフォルト設定で作成した場合、ストレージアカウントは外部に公開され、アクセスキー経由で利用できる状態になります。
AMLストレージアカウントの保護がいかに重要であるかを示す事例として、最近におけるMSRC(Microsoft Security Response Center)の緊急措置が挙げられます。本事例では、過大な権限を持つ「共有アクセス署名(SAS:Shared Access Signature)」がMicrosoftのAI調査チームによって誤って公開されたため、38テラバイトもの機密情報が流出しかねない事態に陥りました。さらに本SASトークンには、ストレージアカウントへの書き込み権限も付与されていました(URLを用いれば、誰でも当該のストレージアカウントにアクセスし、MLモデルを含むファイルを書き換えることができる)。本事象は、信頼性の高いリポジトリに不備があったという点で、典型的なサプライチェーン型攻撃を引き起こしかねないものです。
ストレージアカウントやコンテナに対する名前の付け方を踏まえると、上述のAI調査チームが用いていたストレージアカウントは、AMLワークスペースで作成されたものと考えられます。AMLワークスペースの作成時には、ストレージアカウントの名前として、ワークスペース名の後に10桁のランダム文字を付加したものが設定されます(図18)。
さらに、問題となったストレージアカウント「robustnessws4285631339」のコンテナ名が「azureml」から始まっている点も(図19)、AMLサービスに特有の傾向です。実際にAMLワークスペースの作成時には、これと同様の名前を持つコンテナが、ストレージアカウント内にデフォルトで作成されます。
防御チーム側では、システムのセキュリティ体制を評価する際に、フレームワーク「Threat Matrix for Storage Services」や「Azure Threat Research Matrix」を活用できます。特にMLの環境については、「MITRE ATLAS」が有効です。これは、戦略やテクニックの知識ベースに相当するものであり、実際の攻撃事例や、レッドチームによる現実重視の実演例を元に作成されています。ML環境を狙った攻撃事例にスポットを当てた調査報告としては、「Compromised PyTorch Dependency Chain(PyTorchの依存関係を乱す手口)」などが挙げられます。
本稿では、クラウドリソースにおける認証情報の扱いや、そこに潜んでいるリスクについて解説しました。クラウド環境をご利用の方は、「侵害を前提とする発想」に基づき、見落としがちなケースや未知のケースに対する警戒を強めることを推奨します。セキュリティ上のベストプラクティスを実践することも有効な対策であり、仮に防御網の一角が崩された場合でも、被害の範囲を小さく抑え込めるでしょう。推奨されるベストプラクティスの例を、下記に示します。
- 仮想ネットワーク「VNet」を用いてシステムを保護する
- IDに対して最小限のカスタムロールを設定する
- 多層防御(Defense-in-Depth)の戦略を実践する
参考記事:
You Can't See Me - Achieving Stealthy Persistence in Azure Machine Learning
By: Nitesh Surana, David Fiser
翻訳:清水 浩平(Core Technology Marketing, Trend Micro™ Research)