LayerX エンジニアブログ

LayerX の エンジニアブログです。

グループ企業間で使うSlack Botと脅威ベースのリスク評価 - Entra ID編

ドーモ、読者のミナ=サン、@ken5scalです。 今回はLayerXと、Fintech事業部のメンバーが出向する三井物産デジタル・アセットマネジメント(以降、MDM)をまたがる業務システムと、それに伴うリスク評価および発見的統制についてお話したいと思います。 これにより、コンパウンドスタートアップなグループ会社をまたがって必要とされる業務のデジタル化、 そしてその初期からの安全への取り組みについて紹介していきます。

業務

先述した通り、MDMはグループ会社です。 そこにはLayerXの代表取締役社長の一人(@y_matsuwitter)も非常勤取締役として出向しています。 私自信もLayerX CTO室のマネージャーを兼任しながら出向しています。

さて、私はともかく(?)、@y_matsuwitterさんは面接・登壇・取締役会など重要なスケジュールでドチャクソ忙しいです。 LayerXとMDM側でスケジュールのバッティングが起きたら大変なことになりますので、秘書業務を任されている方がいます。

さて、MDMは金融事業会社です。それも第一種金融商品取引業です。 仮にもグループ会社とはいえ、ホイホイと他社の人員に情報を提供してはまずいのです。 今回の場合、MDM側の出向者のスケジュールという情報だけを見る必要があります。 厄介なことにMDMからの業務委託というわけでもないため、MDMアカウントを付与するのも難しく、 また、そのためにNDAをカスタマイズするのはやりすぎ....という事情がありました。

そんなこんなで、毎週、指定の出向者のMDM側カレンダーのスクショをとり、Slackコネクト上にうpる温かみのある運用が行われていました。

この暖かさをもった人間が地球さえ破壊するんだ!それを分かるんだよアムロッ!

どうした

LayerXはデジタル化したい会社であり、当然その精神をMDM出向者も受け継いでます。のでデジタル化しました。 システムの契約・テナントは全く異なるので、基本、MDM側でシステムを作り、LayerX側からの入力をバリデーションしたうえで実行する形にしました。。。。と聞くと如何にも工夫したみたいな書きっぷりですが、実体としてはApp Runner上でSlack Botアプリを実行し、Graph APIから奇々怪々なるExchangeのリクエストをどうにかしてスケジュールを取得する単純なサービスです。

業務の内容や情報の機密性からしても、リスクとしてはそこまで高くないのはおわかりでしょう。 しかし、LayerXやMDMのような(ほぼ)フルクラウドな環境における脅威情報は、 ここ1〜2年で出てきたものが多く、具体的な脅威ベースの対策についてはまだまだ知見がありません。 そういった状況では、基本的に試行錯誤以外の道はありません。 満ち満ちたる未知な状況でのリスク評価・対応の知見を積み上げるために、本システムに対して簡易なそれを実施しました。

アプリ単体でも、こういった活動を初期からすると運用時や危機時のイメージをしやすくなりますのでおすすめです。

本ブログでは、一旦Azure AD...もといEntra IDに限定し、当該アプリにおけるリスクを検知するためのログ周りについて記述します。 なお、当社ではアプリケーション管理者はPAMを、権限設定には管理者承認を必須するなどしているため、これらの検知は補助的な意味合いが強いです。

リスクを顕在化する脅威の特定

基本的に、脅威レポートを参考にします。様々なレポートから共通項を発見していきましょう。

今回は 1) 正当なアカウントを悪用し、初期アクセスをする脅威 2 ) その後、永続的なアクセス権を入手する脅威 3) より強い権限=可能なアクションの幅を広げる脅威 といったものを照会いたします。 これらを攻撃者のテクニックをナレッジベースにした「Mitre ATT&CK」にマッピングすると、その後の活動がやりやすくなります。

正当なアカウントの悪用: Azure ADのサービスプリンシパル認証

初期アクセスの王道中の王道、正当なアカウントの悪用から始めましょう。 Mitre ATT&CKでは「Valid Accounts > T1078.004 Cloud Accounts」と呼ばれるテクニックです。 この場合は、アプリケーションのクレデンシャルを何らかの方法で悪用、あるいは攻撃者が追加したものを利用されているケースを想定しています。

変更対象 テクニック イベント名 イベントに記録された変更対象のプロパティ名
ログイン T1078.004 Cloud Accounts Sign-in activity -
Federated credentials T1098.001 Additional Cloud Credentials Update application FederatedIdentityCredentials
Client secrets T1098.001 Additional Cloud Credentials
Certificates T1098.001 Additional Cloud Credentials
{
    "id": ${ID},
    "content": {
        "timestamp": "2024-02-27T10:14:50.719Z",
        "tags": [
            "sourcecategory:azure",
            "tenant:${TenantID}",
            "source:azure.activedirectory",
            "forwardername:datadog-function",
            "forwarderversion:1.0.1",
            "datadog.submission_auth:private_api_key"
        ],
        "service": "azure",
        "attributes": {
            "resourceId": "/tenants/${TenantID}/providers/Microsoft.aadiam",
            "evt": {
                "name": "Sign-in activity",
                "category": "ServicePrincipalSignInLogs"
            },
            "title": "'Sign-in activity' resulted in  initiated by  ",
            "resultSignature": "None",
            "network": {略},
            "duration": 0,
            "operationVersion": "1.0",
            "service": "azure",
            "tenantId": "${TenantID}",
            "correlationId": "${CorrelationID}",
            "Level": 4,
            "location": "JP",
            "time": "2024-02-27T10:14:50.7192373Z",
            "resultType": "0",
            "durationMs": 0,
            "properties": {
                "resourceId": "略",
                "isInteractive": false,
                "conditionalAccessStatus": "略",
                "createdDateTime": "2024-02-27T10:13:57.0489536+00:00",
                "riskLevelAggregated": "low",
                "authenticationProcessingDetails": [
                    {
                        "value": "Family: MSAL Library: MSAL.node 2.6.0 Platform: Node",
                        "key": "Azure AD App Authentication Library"
                    }
                ],
                "servicePrincipalName": "略",
                "processingTimeInMilliseconds": 0,
                "federatedCredentialId": "略",
                "isTenantRestricted": false,
                "appId": "略",
                "correlationId": "略",
                "id": "略",
                "riskState": "none",
                "servicePrincipalId": "略",
                "tokenIssuerType": "AzureAD",
                "flaggedForReview": false,
                "resourceDisplayName": "Microsoft Graph",
                "resourceServicePrincipalId": "略",
                "riskLevelDuringSignIn": "low",
                "ipAddress": "略",
                "crossTenantAccessType": "none",
                "authenticationProtocol": "none",
                "clientCredentialType": "none",
                "originalTransferMethod": "none",
                "riskDetail": "none",
                "location": {" },
                "incomingTokenType": "none",
                "signInTokenProtectionStatus": "none",
                "uniqueTokenIdentifier": "略",
                "status": {
                    "errorCode": 0
                }
            }
        }
    }
}

なお、上記のレポートにもありますが、基本的にはInitial Accessに対して重点的に予防・遅滞・隔離をするのが最もコスパがよくなると考えています。 そのため、Conditonal Access for workload identityをしっかり設定しておくのが無難かと思います。 特に今回は東京リージョンのApp Runner以外のアクセス経路は想定できないため、ネットワーク制御もいれておきたいですね。

Microsoft Entra Conditional Access for workload identities - Microsoft Entra ID | Microsoft Learn

アクセスの永続化: アプリケーションの追加

攻撃者は、MFAなどに煩わされることなく、侵害した環境へのアクセスを確立したいと考えます。 これには条件付きアクセスなどでMFAを強制されるようなユーザーではなく、アプリのアイデンティティとして機械的にリソースへアクセスできるサービスプリンシパルを作ることが望ましいです。 それをするために、新しくアプリケーションを登録します。

変更対象 テクニック イベント名 イベントに記録された変更対象のプロパティ名
ログイン T1078.004 Cloud Accounts Sign-in activity -
Service Principalの追加 T1136.003 Cloud Account Add service principal -
Federated credentials T1098.001 Additional Cloud Credentials
Client secrets T1098.001 Additional Cloud Credentials
Certificates T1098.001 Additional Cloud Credentials
{
    "id": "略",
    "content": {
        "timestamp": 1709208580221,
        "status": "info",
        "tags": [
            "sourcecategory:azure",
            "tenant:"略",
            "source:azure.activedirectory",
            "forwardername:datadog-function",
            "forwarderversion:1.0.1",
            "datadog.submission_auth:api_key"
        ],
        "service": "azure",
        "source": "azure.activedirectory",
        "attributes": {
            "resourceId": "/tenants/略/providers/Microsoft.aadiam",
            "evt": {
                "name": "Add service principal",
                "category": "AuditLogs",
                "outcome": "success"
            },
            "title": "'Add service principal' resulted in success initiated by メアド ",
            "resultSignature": "None",
            "network": {
                "ip": {略}
            },
            "duration": 0,
            "operationVersion": "1.0",
            "usr": {
                "name": "${Display Name}?",
                "id": "${UPN}?"
            },
            "service": "azure",
            "tenantId": "略",
            "correlationId": "略",
            "Level": 4,
            "time": "2024-02-29T12:09:40.2212124Z",
            "durationMs": 0,
            "properties": {
                "activityDisplayName": "Add service principal",
                "resultReason": "",
                "correlationId": "略",
                "loggedByService": "Core Directory",
                "operationType": "Add",
                "id": "Directory_略",
                "activityDateTime": "2024-02-29T12:09:40.2212124+00:00",
                "category": "ApplicationManagement",
                "targetResources": [
                    {
                        "displayName": "test",
                        "modifiedProperties": [
                            {
                                "newValue": "[true]",
                                "displayName": "AccountEnabled",
                                "oldValue": "[]"
                            },
                            {
                                "newValue": "[\"${ApplicationId}\"]",
                                "displayName": "AppPrincipalId",
                                "oldValue": "[]"
                            },
                            {
                                "newValue": "[\"test\"]",
                                "displayName": "DisplayName",
                                "oldValue": "[]"
                            },
                            {
                                "newValue": "[\"${ApplicationId}\"]",
                                "displayName": "ServicePrincipalName",
                                "oldValue": "[]"
                            },
                            {
                                "newValue": "[{\"CredentialType\":2,\"KeyStoreId\":\"略\",\"KeyGroupId\":\"略\"}]",
                                "displayName": "Credential",
                                "oldValue": "[]"
                            },
                            {
                                "newValue": "\"AccountEnabled, AppPrincipalId, DisplayName, ServicePrincipalName, Credential\"",
                                "displayName": "Included Updated Properties"
                            },
                            {
                                "newValue": "\"${ApplicationId}\"",
                                "displayName": "TargetId.ServicePrincipalNames"
                            }
                        ],
                        "id": "略",
                        "type": "ServicePrincipal"
                    }
                ],
                "additionalDetails": [略],
                "initiatedBy": {
                    "user": {
                        "ipAddress": "",
                        "id": "略"
                    }
                }
            }
        }
    }
}

アクセスの永続化: クレデンシャル追加

別の永続化(Persistence)のテクニック「T1098.001 Additional Cloud Credentials」を見てみましょう。 これは新しいアプリケーション追加ができなくとも、特定アプリケーションのオーナー権限を入手した場合などに有効です。

Service Principalにクレデンシャルを追加する場合、そのクレデンシャルのタイプによって出力されるイベント名が異なります。 また、必ずしも他のイベントと排他的でないのが特徴です。

まずは、非「証明書やシークレット」なクレデンシャル、すなわち他IdPによって払い出されたID Tokenを受けて短期的なアクセストークンを発行する「Federated credentials」を追加する場合のログをみてみましょう。

ログの通りイベント名は「Update application」で、記録された変更対象のプロパティ名(※)は 「FederatedIdentityCredentials」です。 ※ properties.targetResources[0].modifiedProperties[0].displayName

変更対象 テクニック イベント名 イベントに記録された変更対象のプロパティ名
Service Principalの追加 T1136.003 Cloud Account Add service principal -
ログイン T1078.004 Cloud Accounts Sign-in activity -
Federated credentials T1098.001 Additional Cloud Credentials Update application FederatedIdentityCredentials
Client secrets T1098.001 Additional Cloud Credentials
Certificates T1098.001 Additional Cloud Credentials
{
    "id": "id",
    "content": {
        "timestamp": "2024-02-27T12:01:08.377Z",
        "tags": [
            "sourcecategory:azure",
            "tenant:%{TENANT_ID",
            "source:azure.activedirectory",
            "forwardername:datadog-function",
            "forwarderversion:1.0.1",
            "datadog.submission_auth:private_api_key"
        ],
        "service": "azure",
        "attributes": {
            "resourceId": "/tenants/${TENANT_ID}/providers/Microsoft.aadiam",
            "evt": {
                "name": "Update application",
                "category": "AuditLogs",
                "outcome": "success"
            },
            "title": "'Update application' resulted in success initiated by メアド",
            "resultSignature": "None",
            "network": { // 略 },
            "duration": 0,
            "operationVersion": "1.0",
            "usr": {
                "name": "${DisplayNAme}?",
                "id": "${UPN}?"
            },
            "service": "azure",
            "tenantId": "${TENANT_ID}",
            "correlationId": "${CORRELATION_ID}",
            "Level": 4,
            "time": "2024-02-27T12:01:08.3775938Z",
            "durationMs": 0,
            "properties": {
                "activityDisplayName": "Update application",
                "resultReason": "",
                "correlationId": "${CORRELATION_ID}",,
                "loggedByService": "Core Directory",
                "operationType": "Update",
                "id": "なにかのID",
                "activityDateTime": "2024-02-27T12:01:08.3775938+00:00",
                "category": "ApplicationManagement",
                "targetResources": [
                    {
                        "displayName": "${APP_DISPLAY_NAME}",
                        "modifiedProperties": [
                            {
                                "newValue": "${oldValue + newValue}",
                                "displayName": "FederatedIdentityCredentials",
                                "oldValue": "${oldValue}",
                            },
                            {
                                "newValue": "\"FederatedIdentityCredentials\"",
                                "displayName": "Included Updated Properties"
                            }
                        ],
                        "id": "${なにかのID}",
                        "type": "Application"
                    }
                ],
                "additionalDetails": [略],
                "initiatedBy": {
                    "user": {略}
                }
            }
        }
    }
}

こちらは、当該アプリに、client secretや証明書を追加した際のイベントです。

イベント名は「Update application – Certificates and secrets management 」となっています。 記録された変更対象のプロパティ名(※)は 「KeyDescription」です。 なお、横着して証明書を追加した際のログのみお見せしていますが、Client Secret追加でも同じ構造になっています。

変更対象 テクニック イベント名 イベントに記録された変更対象のプロパティ名
ログイン T1078.004 Cloud Accounts Sign-in activity -
Service Principalの追加 T1136.003 Cloud Account Add service principal -
Federated credentials T1098.001 Additional Cloud Credentials Update application FederatedIdentityCredentials
Client secrets T1098.001 Additional Cloud Credentials Update application – Certificates and secrets management KeyDescription
Certificates T1098.001 Additional Cloud Credentials Update application – Certificates and secrets management KeyDescription
{
    "id": "${ID}",
    "content": {
        "timestamp": "2024-02-27T12:01:18.748Z",
        "tags": [
            "sourcecategory:azure",
            "tenant:${TENANT_ID}",
            "source:azure.activedirectory",
            "forwardername:datadog-function",
            "forwarderversion:1.0.1",
            "datadog.submission_auth:private_api_key"
        ],
        "service": "azure",
        "attributes": {
            "resourceId": "/tenants/${TENANT_ID}/providers/Microsoft.aadiam",
            "evt": {
                "name": "Update application – Certificates and secrets management ",
                "category": "AuditLogs",
                "outcome": "success"
            },
            "title": "'Update application – Certificates and secrets management ' resulted in success initiated by メアド",
            "resultSignature": "None",
            "network": {
                "ip": {略},
                "client": {geoとか}
            },
            "duration": 0,
            "operationVersion": "1.0",
            "usr": {
                "name": "${DisplayNAme}?",
                "id": "${UPN}?"
            },
            "service": "azure",
            "tenantId": "${TENANT_ID}",
            "correlationId": "${CorrelationId}",
            "Level": 4,
            "time": "2024-02-27T12:01:18.748745Z",
            "durationMs": 0,
            "properties": {
                "activityDisplayName": "Update application – Certificates and secrets management ",
                "resultReason": "",
                "correlationId": "{$CorrelationId}",
                "loggedByService": "Core Directory",
                "operationType": "Update",
                "id": "${ID}",
                "activityDateTime": "2024-02-27T12:01:18.748745+00:00",
                "category": "ApplicationManagement",
                "targetResources": [
                    {
                        "displayName": "${APP_NAME}",
                        "modifiedProperties": [
                            {
                                "newValue": ["[KeyIdentifier=${KEY_ID},KeyType=Password,KeyUsage=Verify,DisplayName=tekito]","[KeyIdentifier=${KEY_ID},KeyType=AsymmetricX509Cert,KeyUsage=Verify,DisplayName=O=Internet Widgits Pty Ltd, S=Some-State, C=AU]"],
                                "displayName": "KeyDescription",
                                "oldValue": "[]"
                            },
                            {
                                "newValue": "\"KeyDescription\"",
                                "displayName": "Included Updated Properties"
                            }
                        ],
                        "id": "${ID}",
                        "type": "Application"
                    }
                ],
                "additionalDetails": [略],
                "initiatedBy": {略}
            }
        }
    }
}

...なんでクレデンシャル追加のイベント名を、一部でのみ異なるようにしてるのかはわかりません(そういうとこやぞ)

より強い権限をえる:権限昇格 > 権限追加

権限昇格の観点から「API Permission」を追加した際のログもみてみましょう。

テクニックとしては、「T1098.003 Additional Cloud Roles」になります。 この際のイベント名は「Update application」で、変更対象として記録されるプロパティ名は「RequiredResourceAccess」です。

変更対象 テクニック イベント名 イベントに記録された変更対象のプロパティ名
ログイン T1078.004 Cloud Accounts Sign-in activity -
Service Principalの追加 T1136.003 Cloud Account Add service principal -
Federated credentials T1098.001 Additional Cloud Credentials Update application FederatedIdentityCredentials
Client secrets T1098.001 Additional Cloud Credentials Update application – Certificates and secrets management KeyDescription
Certificates T1098.001 Additional Cloud Credentials Update application – Certificates and secrets management KeyDescription
API Permission T1098.003 Additional Cloud Roles Update application RequiredResourceAccess

権限が追加された場合、特定のEntitlement ID(※)として記録されます。 ※ RequiredAppPermissions配列内の要素にあるEntitlementId

パッと見ではどのような権限かわからないので、公式ドキュメントから照合できます。

Microsoft Graph permissions reference - Microsoft Graph | Microsoft Learn

今回の場合、EntitlementIDが「8ba4a692-bc31-4128-9094-475872af8a53」なので、「Calendars.ReadBasic.All」が付与されていることがわかります。 なお、管理者からの承認がなくても本ログは出力されます。

「Update application」で、前のイベントと同じです。

{
    "id": "${ID}",
    "content": {
        "timestamp": "2024-02-27T12:04:45.149Z",
        "tags": [
            "sourcecategory:azure",
            "tenant:${TENANT_ID}",
            "source:azure.activedirectory",
            "forwardername:datadog-function",
            "forwarderversion:1.0.1",
            "datadog.submission_auth:private_api_key"
        ],
        "service": "azure",
        "attributes": {
            "resourceId": "/tenants/${TENANT_ID}/providers/Microsoft.aadiam",
            "evt": {
                "name": "Update application",
                "category": "AuditLogs",
                "outcome": "success"
            },
            "title": "'Update application' resulted in success initiated by メアド",
            "resultSignature": "None",
            "network": {略},
            "duration": 0,
            "operationVersion": "1.0",
            "usr": {
                "name": "${DisplayNAme}?",
                "id": "${UPN}?"
            },
            "service": "azure",
            "tenantId": "${TEANNT_ID}",
            "correlationId": "${Correlation_ID}",
            "Level": 4,
            "time": "2024-02-27T12:04:45.1497765Z",
            "durationMs": 0,
            "properties": {
                "activityDisplayName": "Update application",
                "resultReason": "",
                "correlationId": "${Correlation_ID}",
                "loggedByService": "Core Directory",
                "operationType": "Update",
                "id": "${ID}",
                "activityDateTime": "2024-02-27T12:04:45.1497765+00:00",
                "category": "ApplicationManagement",
                "targetResources": [
                    {
                        "displayName": "${APP_NAME}",
                        "modifiedProperties": [
                            {
                                "newValue": "[{\"ResourceAppId\":\"00000003-0000-0000-c000-000000000000\",\"RequiredAppPermissions\":[略,{\"EntitlementId\":\"8ba4a692-bc31-4128-9094-475872af8a53\",\"DirectAccessGrant\":true,\"ImpersonationAccessGrants\":[]}]",
                                "displayName": "RequiredResourceAccess",
                                "oldValue": "[{\"ResourceAppId\":\"00000003-0000-0000-c000-000000000000\",\"RequiredAppPermissions\": 略]"
                            },
                            {
                                "newValue": "\"RequiredResourceAccess\"",
                                "displayName": "Included Updated Properties"
                            }
                        ],
                        "id": "${ID}",
                        "type": "Application"
                    }
                ],
                "additionalDetails": [略],
                "initiatedBy": {略}
            }
        }
    }
}

APIコールの傾向

ある程度侵害の段階がすすみ、権限を昇格・取得されるとAPIコールをみたくなります。 残念ながら、カレンダーのスケジュール閲覧 ( getSchedule ) アクションはUnified Audit Logの対象ではありませんが、 まあ、今回の脅威ベクトルやアクターに関連したIoCで、そういった事が行われた形跡はありませんので問題ないでしょう。

learn.microsoft.com

まとめ

このように脅威レポート(landscape? インテリジェンス?)から、リスクベースなDetection Engineeringをする際のログをみていきました。 ログの構造把握やイベントルールの作成をコンソールから取得して、1からやるのは中々しんどいので、個人的にはSIEMが活躍すると思います。 次は、今後のSIEMのあり方についてブログを書く予定です。

最後に

MiroのEnterpriseにアップグレードしてくれてAWSのアイコン・ステンシルをつけるようにしてくれた @helosshi 及び、 チーム内でAADの呼称をEntraIDと呼ぶルールを定めてくれた @yuya_takeyama 、LayerX CTO室両名に、この場を借りて感謝させていただきます。