クラウド環境
クラウドサービス「Azure」が提供するサーバーレス環境でのマネージドIDについて分析
認証情報やシークレットを管理する目的で開発者に広く利用されているAzureの「マネージドIDサービス」について、脅威モデルに基づくセキュリティ分析を行いました。
リソースのセキュリティを確保する上で、「認証」と「認可」は重要な役割を果たします。「認証」では、セキュリティ保護されたリソースへのアクセスを要求するユーザやサービスに対し、自身を証明する認証情報の提示を要求し、さらに提示された内容が正しいものであるかを検証します。一方、「認可」では、その認証されたユーザまたはサービスが、当該リソースにアクセスする権限を持っているかを検証します。
Webアプリケーションで頻発した問題を報告する「top 10 OWASP」によると、2017年から2021年にかけて、アクセス制御の不備(Broken Access Control)が上位10件の1つとして挙げられています。トレンドマイクロでも、認証に使用される機密情報を適切に保管することの重要性について、これまで報告してきました。アクセス制御に不備があると、例えば未認可のユーザが悪意の有無によらず取り決めた権限やセキュリティ・ポリシーの範囲を超えてリソースにアクセスし、改変、削除といった操作を行ってしまう場合があります。こうしたアクセス制御の不備は、Webアプリケーションを利用する企業や組織にとって最重要の課題となっています。本稿では、この課題に対する取り組みの一環として、クラウドサービスプロバイダ(CSP:Cloud Service Provider)内で機能するAzureの「マネージドIDサービス」に関する分析結果を報告します。
「システム割り当て」と「ユーザ割り当て」によるマネージドID
AzureのマネージドIDを使用することで、CSP内で利用可能な特定のサービスを認証できます。この認証手続きは、クラウドのサービスまたはアプリケーションに対して認証用トークンを配布する形で行われます。マネージドIDは、「システム割り当てID」と「ユーザ割り当てID」という2種類に大別されます。システム割り当てIDは各リソース固有に1つずつ用意され、複数のシステム割り当てIDを同じリソースに割り当てることはできません。「ユーザ割り当てID」ではこうした制約が解消され、いわゆるユーザ・ロールのように、同じリソースに複数割り当てることが可能です。
例として、サーバーレスアプリケーションからAzureストレージアカウントにアクセスして、アプリケーションのレコードを保存するケースを考えます。マネージドIDとしては「システム割り当て」の使用を想定します。具体的には、下記の設定を行います。
- サーバーレス関数に対してマネージドIDを有効化
- サーバーレス関数のマネージドIDをストレージアカウントへのアクセス許可対象として指定
上記の設定により、ストレージへのアクセスに際して、割り当てたマネージドIDを用いた認証が可能になります。以降、最近行った調査結果をもとに、サーバーレス環境におけるマネージドIDの実装方式について技術的な視点を交えて解説します。さらに、導かれるセキュリティ面での見解について報告します。
サーバーレス環境におけるID管理
サーバーレス環境では、その機能を実現するために、特殊な.NETアプリケーション「dotnet TokenServiceContainer.dll」が稼働します。このプロセスは、localhost上でポート番号8081を開き、HTTPリクエストを受信します。認証トークンを要求するエンドポイントのURLとしてはi以下の文字列が使用されます。この際、利用するAPIのバージョンと、アクセス対象リソースをパラメータで指定する必要があります。また状況に応じて、「ユーザ割り当て」によるマネージドIDのトークンを取得する際に必要なパラメーターである「client_id」も指定します。このトークン取得に際しては、パラメータ「X-IDENTITY-HEADER」も別途指定が必要であり、その値は環境変数「IDENTITY_HEADER」または「MSI_SECRET」に格納されています。
http://localhost:8081/msi/token
トークン取得の依頼は、localhost側で受理された後、CSP内のエンドポイント側(localhostのものとは別)に回され、そこを経由して目的とするトークンが配布されます。CSP内のエンドポイントは、外部からのアクセスが可能なサブドメイン「*.identity.azure.net」の配下にあります。なおこのサブドメインはサーバーレスアプリケーションのリージョンに応じて変化します。外部アクセスが可能なことを踏まえた設計として、当該エンドポイントへのアクセスに際しては認証が必要となっており、これにはX509によるクライアント証明書が使用されます。この証明書はアプリケーションID毎に用意され(言い換えると、各サーバーレス関数には、1対1で対応するアプリケーションIDと証明書が紐づけられている)、180日間に渡って有効です。トークン取得の依頼に成功すると、1日間有効なBearer型のトークンがJSON形式で返却されます。
上記の運用方式は、CSPのサービスに期待される通りの高いセキュリティ水準を備えていると言えます。しかし、見逃されがちな危険性が一点だけあります。それは、証明書そのものです。以降に述べる通り、証明書は、環境変数の窃取を引き金として外部に流出してしまう可能性があります。
マネージドIDの証明書は、コンテナ内に暗号化された状態で格納されています。このコンテナには環境変数「CONTAINER_START_CONTEXT_SAS_URI」で指定されるURLからアクセス可能であり、復号に用いる鍵は「CONTAINER_ENCRYPTION_KEY」変数から取得が可能です。こうした環境変数を介して証明書が攻撃者に窃取された場合、トークンを取得するために公開されているサービス・エンドポイントに対する不正アクセスがCSP外部から発生し、認証に成功してしまう可能性が懸念されます。
攻撃モデルとシナリオ
上述した攻撃シナリオが実現するための前提条件として、攻撃者はまず何らかの方法で環境変数を窃取する必要があり、さらにCSPの設定としてサービスまたはアプリケーションのマネージドIDが有効で、かつ目的とするリソースにロール(アクセス許可対象のユーザやマネージドIDの設定カテゴリ)が指定されている必要があります。CSPの設定において、明示的な指定が無い限り、デフォルトでのロールが設定されていることはありません。
上記のような前提条件はあるものの、セキュリティ欠陥などによってLinuxのエンドポイントから環境変数が流出するなどの可能性を視野に含めると、子プロセスにまで引き継がれる環境変数内に機密情報を格納することは、セキュアな設計方針とは言えません。攻撃者が環境変数にアクセスして、それを手がかりに証明書として十分な情報を取得できたのであれば、トークン取得用エンドポイントは外部に公開されたも同然となります。攻撃グループはCSPサービス外からこのエンドポイントにアクセスして認証用トークンを取得し、もとのユーザが持つ全権限を掌握することが可能です。
今回の検証において、サーバーレス環境のトークン取得用サービスは、専用ユーザによって起動され稼働していることが分かりました。本来クライアント証明書は、このユーザにのみアクセス権を付与したファイルに保管されるべきではないでしょうか。上述の環境変数に保管する方式では、不正アクセスされたサーバーレス関数を経由して環境変数および証明書が流出し、外部サービスからのトークン取得に不正使用されることが懸念されます。未認可のユーザでは当該関数を実行する以上の権限は得られませんが、トークンを窃取できたのであれば、環境内でのさまざまな攻撃的活動に繋げることが可能でしょう。対策として、クライアント証明書はトークン取得用サービスユーザのセキュリティ境界内部に配備し、当該ユーザに読み込み権限のみを付与することが挙げられます。これにより、仮にセキュリティ侵害が発生した場合でも、クライアント証明書の流出やCSP外部からの不正使用、または水平移動・内部活動に繋がる攻撃を阻止することが可能になるでしょう。
システムのセキュリティ強度は、その最も弱い箇所によって決まります。CSPのサービスはそれ自体として高度なセキュリティを備えていますが、わずかな設計不備があるだけでも、ユーザによる不適切な設定と組合わさることで深刻な被害に発展する恐れがあります。アプリケーションや環境、変数の設計にあたっては、その全てにおいて、セキュリティ面を強く考慮することが望まれます。可能であるならば、環境変数には機密情報を保存しない設計を推奨します。最小権限の原則を適用するなどベストプラクティスを敢行することで、セキュリティ侵害の影響をより小さく抑え込むことが可能です。
参考記事:
• 「An Analysis of Azure Managed Identities Within Serverless Environments」
By: David Fiser
翻訳:清水 浩平(Core Technology Marketing, Trend Micro™ Research)