From 7d0ab42c2050cc78296dee11699d8a30a6293b74 Mon Sep 17 00:00:00 2001 From: Steven Dick <38897662+nterl0k@users.noreply.github.com> Date: Sat, 13 Apr 2024 15:34:43 -0400 Subject: [PATCH 01/27] Add files via upload --- lookups/privileged_azure_ad_roles.csv | 65 ++++++++++++++++----------- lookups/privileged_azure_ad_roles.yml | 12 ++--- 2 files changed, 45 insertions(+), 32 deletions(-) diff --git a/lookups/privileged_azure_ad_roles.csv b/lookups/privileged_azure_ad_roles.csv index d4260b6ba3..64987f909e 100644 --- a/lookups/privileged_azure_ad_roles.csv +++ b/lookups/privileged_azure_ad_roles.csv @@ -1,26 +1,39 @@ -"azureadrole","isprvilegedadrole","description" -"""Authentication Administrator""","True","Can access to view, set and reset authentication method information for any non-admin user." -"""Authentication Policy Administrator""","True","Can create and manage the authentication methods policy, tenant-wide MFA settings, password protection policy, and verifiable credentials." -"""Azure AD Joined Device Local Administrator""","True","Users assigned to this role are added to the local administrators group on Azure AD-joined devices." -"""Azure DevOps Administrator""","True","Can manage Azure DevOps policies and settings." -"""Azure Information Protection Administrator""","True","Can manage all aspects of the Azure Information Protection product." -"""Cloud Application Administrator""","True","Can create and manage all aspects of app registrations and enterprise apps except App Proxy." -"""Cloud Device Administrator""","True","Limited access to manage devices in Azure AD." -"""Compliance Administrator""","True","Can read and manage compliance configuration and reports in Azure AD and Microsoft 365." -"""Conditional Access Administrator""","True","Can manage Conditional Access capabilities." -"""Exchange Administrator""","True","Can manage all aspects of the Exchange product." -"""External Identity Provider Administrator""","True","Can configure identity providers for use in direct federation." -"""Groups Administrator""","True","Members of this role can create/manage groups, create/manage groups settings like naming and expiration policies, and view groups activity and audit reports." -"""Helpdesk Administrator""","True","Can reset passwords for non-administrators and Helpdesk Administrators." -"""Hybrid Identity Administrator""","True","Can manage AD to Azure AD cloud provisioning, Azure AD Connect, Pass-through Authentication (PTA), Password hash synchronization (PHS), Seamless Single sign-on (Seamless SSO), and federation settings." -"""Intune Administrator""","True","Can manage all aspects of the Intune product." -"""License Administrator""","True","Can manage product licenses on users and groups." -"""Network Administrator""","True","Can manage network locations and review enterprise network design insights for Microsoft 365 Software as a Service applications." -"""Password Administrator""","True","Can reset passwords for non-administrators and Password Administrators." -"""Privileged Role Administrator""","True","Can manage role assignments in Azure AD, and all aspects of Privileged Identity Management." -"""Security Administrator""","True","Can read security information and reports, and manage configuration in Azure AD and Office 365." -"""SharePoint Administrator""","True","Can manage all aspects of the SharePoint service." -"""Teams Administrator""","True","Can manage the Microsoft Teams service." -"""User Administrator""","True","Can manage all aspects of users and groups, including resetting passwords for limited admins." -"""Windows 365 Administrator""","True","Can provision and manage all aspects of Cloud PCs." - +azureadrole,azuretemplateid,isprvilegedadrole,description +*Application Administrator*,*9b895d92-2cd3-44c7-9d02-a6ac2d5ea5c3*,TRUE,"Can create and manage all aspects of app registrations and enterprise apps." +*Application Developer*,*cf1c38e5-3621-4004-a7cb-879624dced7c*,TRUE,"Can create application registrations independent of the Users can register applications setting." +*Authentication Administrator*,*c4e39bd9-1100-46d3-8c65-fb160da0071f*,TRUE,"Can access to view, set and reset authentication method information for any non-admin user." +*Authentication Extensibility Administrator*,*25a516ed-2fa0-40ea-a2d0-12923a21473a*,TRUE,"Customize sign in and sign up experiences for users by creating and managing custom authentication extensions." +*Authentication Policy Administrator*,*526716b-113d-4c15-b2c8-68e3c22b9f80*,TRUE,"Can create and manage the authentication methods policy, tenant-wide MFA settings, password protection policy, and verifiable credentials." +*Azure AD Joined Device Local Administrator*,*9f06204d-73c1-4d4c-880a-6edb90606fd8*,TRUE,"Users assigned to this role are added to the local administrators group on Azure AD-joined devices." +*Azure DevOps Administrator*,*e3973bdf-4987-49ae-837a-ba8e231c7286*,TRUE,"Can manage Azure DevOps policies and settings." +*Azure Information Protection Administrator*,*7495fdc4-34c4-4d15-a289-98788ce399fd*,TRUE,"Can manage all aspects of the Azure Information Protection product." +*B2C IEF Keyset Administrator*,*aaf43236-0c0d-4d5f-883a-6955382ac081*,TRUE,"Can manage secrets for federation and encryption in the Identity Experience Framework (IEF)." +*Cloud Application Administrator*,*158c047a-c907-4556-b7ef-446551a6b5f7*,TRUE,"Can create and manage all aspects of app registrations and enterprise apps except App Proxy." +*Cloud Device Administrator*,*7698a772-787b-4ac8-901f-60d6b08affd2*,TRUE,"Limited access to manage devices in Azure AD." +*Compliance Administrator*,*17315797-102d-40b4-93e0-432062caca18*,TRUE,"Can read and manage compliance configuration and reports in Azure AD and Microsoft 365." +*Conditional Access Administrator*,*b1be1c3e-b65d-4f19-8427-f6fa0d97feb9*,TRUE,"Can manage Conditional Access capabilities." +*Directory Synchronization Accounts*,*d29b2b05-8046-44ba-8758-1e26182fcf32*,TRUE,"Only used by Microsoft Entra Connect service." +*Directory Writers*,*9360feb5-f418-4baa-8175-e2a00bac4301*,TRUE,"Can read and write basic directory information. For granting access to applications, not intended for users." +*Domain Name Administrator*,*8329153b-31d0-4727-b945-745eb3bc5f31*,TRUE,"Can manage domain names in cloud and on-premises." +*Exchange Administrator*,*29232cdf-9323-42fd-ade2-1d097af3e4de*,TRUE,"Can manage all aspects of the Exchange product." +*External Identity Provider Administrator*,*be2f45a1-457d-42af-a067-6ec1fa63bc45*,TRUE,"Can configure identity providers for use in direct federation." +*Global Administrator*,*62e90394-69f5-4237-9190-012177145e10*,TRUE,"Can manage all aspects of Microsoft Entra ID and Microsoft services that use Microsoft Entra identities." +*Global Reader*,*f2ef992c-3afb-46b9-b7cf-a126ee74c451*,TRUE,"Can read everything that a Global Administrator can, but not update anything." +*Groups Administrator*,*fdd7a751-b60b-444a-984c-02652fe8fa1c*,TRUE,"Members of this role can create/manage groups, create/manage groups settings like naming and expiration policies, and view groups activity and audit reports." +*Helpdesk Administrator*,*729827e3-9c14-49f7-bb1b-9608f156bbb8*,TRUE,"Can reset passwords for non-administrators and Helpdesk Administrators." +*Hybrid Identity Administrator*,*8ac3fc64-6eca-42ea-9e69-59f4c7b60eb2*,TRUE,"Can manage AD to Azure AD cloud provisioning, Azure AD Connect, Pass-through Authentication (PTA), Password hash synchronization (PHS), Seamless Single sign-on (Seamless SSO), and federation settings." +*Intune Administrator*,*3a2c62db-5318-420d-8d74-23affee5d9d5*,TRUE,"Can manage all aspects of the Intune product." +*License Administrator*,*4d6ac14f-3453-41d0-bef9-a3e0c569773a*,TRUE,"Can manage product licenses on users and groups." +*Network Administrator*,*d37c8bed-0711-4417-ba38-b4abe66ce4c2*,TRUE,"Can manage network locations and review enterprise network design insights for Microsoft 365 Software as a Service applications." +*Partner Tier1 Support*,*4ba39ca4-527c-499a-b93d-d9b492c50246*,TRUE,"Do not use - not intended for general use" +*Partner Tier2 Support*,*e00e864a-17c5-4a4b-9c06-f5b95a8d5bd8*,TRUE,"Do not use - not intended for general use" +*Password Administrator*,*966707d0-3269-4727-9be2-8c3a10f19b9d*,TRUE,"Can reset passwords for non-administrators and Password Administrators." +*Privileged Authentication Administrator*,*7be44c8a-adaf-4e2a-84d6-ab2649e08a13*,TRUE,"Can access to view, set and reset authentication method information for any user (admin or non-admin)" +*Privileged Role Administrator*,*e8611ab8-c189-46e8-94e1-60213ab1f814*,TRUE,"Can manage role assignments in Azure AD, and all aspects of Privileged Identity Management." +*Security Administrator*,*194ae4cb-b126-40b2-bd5b-6091b380977d*,TRUE,"Can read security information and reports, and manage configuration in Azure AD and Office 365." +*Security Operator*,*5f2222b1-57c3-48ba-8ad5-d4759f1fde6f*,TRUE,"Creates and manages security events" +*Security Reader*,*5d6b6bb7-de71-4623-b4af-96380a352509*,TRUE,"Can read security information and reports in Microsoft Entra ID and Office 365." +*SharePoint Administrator*,*f28a1f50-f6e7-4571-818b-6a12f2af6b6c*,TRUE,"Can manage all aspects of the SharePoint service." +*Teams Administrator*,*69091246-20e8-4a56-aa4d-066075b2a7a8*,TRUE,"Can manage the Microsoft Teams service." +*User Administrator*,*fe930be7-5e62-47db-91af-98c3a49a38b1*,TRUE,"Can manage all aspects of users and groups, including resetting passwords for limited admins." +*Windows 365 Administrator*,*11451d60-acb2-45eb-a7d6-43d0f0125c13*,TRUE,"Can provision and manage all aspects of Cloud PCs." \ No newline at end of file diff --git a/lookups/privileged_azure_ad_roles.yml b/lookups/privileged_azure_ad_roles.yml index cc8e2df2ad..e0e6b6b40b 100644 --- a/lookups/privileged_azure_ad_roles.yml +++ b/lookups/privileged_azure_ad_roles.yml @@ -1,7 +1,7 @@ -description: A list of privileged Azure Active Directory roles. -filename: privileged_azure_ad_roles.csv -name: privileged_azure_ad_roles -default_match: 'false' -match_type: WILDCARD(azureadrole) -min_matches: 1 +description: A list of privileged Azure Active Directory roles, includes updates for 2024 and template IDs. +filename: privileged_azure_ad_roles.csv +name: privileged_azure_ad_roles +default_match: 'false' +match_type: WILDCARD(azureadrole),WILDCARD(azuretemplateid) +min_matches: 1 case_sensitive_match: 'false' \ No newline at end of file From 12d024d3a51a3bf412cfa9aabe166a8c4b1e533d Mon Sep 17 00:00:00 2001 From: Steven Dick <38897662+nterl0k@users.noreply.github.com> Date: Sat, 13 Apr 2024 15:36:23 -0400 Subject: [PATCH 02/27] Add files via upload --- ...application_available_to_other_tenants.yml | 64 +++++++++++++++++++ .../cloud/o365_cross_tenant_access_change.yml | 60 +++++++++++++++++ .../o365_external_guest_user_invited.yml | 63 ++++++++++++++++++ .../o365_external_identity_policy_changed.yml | 63 ++++++++++++++++++ .../cloud/o365_privileged_role_assigned.yml | 63 ++++++++++++++++++ ...ged_role_assigned_to_service_principal.yml | 64 +++++++++++++++++++ 6 files changed, 377 insertions(+) create mode 100644 detections/cloud/o365_application_available_to_other_tenants.yml create mode 100644 detections/cloud/o365_cross_tenant_access_change.yml create mode 100644 detections/cloud/o365_external_guest_user_invited.yml create mode 100644 detections/cloud/o365_external_identity_policy_changed.yml create mode 100644 detections/cloud/o365_privileged_role_assigned.yml create mode 100644 detections/cloud/o365_privileged_role_assigned_to_service_principal.yml diff --git a/detections/cloud/o365_application_available_to_other_tenants.yml b/detections/cloud/o365_application_available_to_other_tenants.yml new file mode 100644 index 0000000000..a05cc9ccb7 --- /dev/null +++ b/detections/cloud/o365_application_available_to_other_tenants.yml @@ -0,0 +1,64 @@ +name: O365 Application Available To Other Tenants +id: 942548a3-0273-47a4-8dbd-e5202437395c +version: 1 +date: '2024-04-11' +author: Steven Dick +status: production +type: TTP +description: The following analytic identifies the configuration of Azure Active Directory Applications in a manner that allows authentication from external tenants or personal accounts. This configuration can lead to inappropriate or malicious access of any data or capabilities the application is allowed to access. This detection leverages the O365 Universal Audit Log data source. +data_source: +- Office 365 Universal Audit Log +search: '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add application.","Update application.") ModifiedProperties{}.Name=AvailableToOtherTenants +| eval result = case(match(mvindex('ModifiedProperties{}.NewValue',mvfind('ModifiedProperties{}.Name',"AvailableToOtherTenants")),"false"),"removed",true(),"added"), object_name=mvindex('Target{}.ID', 3), signature=Operation, object_attrs = "AvailableToOtherTenants", user = mvindex('Actor{}.ID',0) +| search result = "added" +| stats values(ActorIpAddress) as src, count, min(_time) as firstTime, max(_time) as lastTime by signature, user, object, object_name, object_attrs, result +| `security_content_ctime(firstTime)` +| `security_content_ctime(lastTime)` +| `o365_application_available_to_other_tenants_filter`' +how_to_implement: You must install the Splunk Microsoft Office 365 Add-on and ingest Office 365 management activity events. +known_false_positives: Business approved changes by known administrators. +references: +- https://attack.mitre.org/techniques/T1098/ +- https://msrc.microsoft.com/blog/2023/03/guidance-on-potential-misconfiguration-of-authorization-of-multi-tenant-applications-that-use-azure-ad/ +- https://www.wiz.io/blog/azure-active-directory-bing-misconfiguration +tags: + analytic_story: + - Azure Active Directory Persistence + - Azure Active Directory Account Takeover + - Data Exfiltration + asset_type: Office 365 + confidence: 100 + impact: 50 + message: An Azure Application [$object_name$] was configured by [$user$] as accessible to external tenants. + mitre_attack_id: + - T1098.003 + - T1098 + observable: + - name: user + type: user + role: + - Victim + - name: object_name + type: object + role: + - Attacker + product: + - Splunk Enterprise + - Splunk Enterprise Security + - Splunk Cloud + required_fields: + - _time + - Operation + - ModifiedProperties{}.NewValue + - ModifiedProperties{}.Name + - UserId + - Workload + - Target{}.ID + risk_score: 50 + security_domain: threat +tests: +- name: True Positive Test + attack_data: + - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1098/o365_azure_workload_events/o365_azure_workload_events.log + sourcetype: o365:management:activity + source: o365 \ No newline at end of file diff --git a/detections/cloud/o365_cross_tenant_access_change.yml b/detections/cloud/o365_cross_tenant_access_change.yml new file mode 100644 index 0000000000..e71603d53b --- /dev/null +++ b/detections/cloud/o365_cross_tenant_access_change.yml @@ -0,0 +1,60 @@ +name: O365 Cross-Tenant Access Change +id: 7c0fa490-12b0-4d0b-b9f5-e101d1e0e06f +version: 1 +date: '2024-04-11' +author: Steven Dick +status: production +type: TTP +description: The following analytic identifies when cross-tenant access/synchronization policies are changed in an Azure tenant. Adversaries have been observed altering victim cross-tenant policies as a method of lateral movement or maintaining persistent access to compromised environments. These policies should be considered sensitive and monitored for changes and/or loose configuration. +data_source: +- Office 365 Universal Audit Log +search: '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add a partner to cross-tenant access setting.","Delete partner specific cross-tenant access setting.") +| stats values(Workload) as category, values(ClientIP) as src, values(ModifiedProperties{}.Name) as object_name, values(ModifiedProperties{}.NewValue) as object_attrs, count, min(_time) as firstTime, max(_time) as lastTime by Id, UserId, Operation +| rename Operation as signature, Id as signature_id, UserId as user +| `security_content_ctime(firstTime)` +| `security_content_ctime(lastTime)` +| `o365_cross_tenant_access_change_filter`' +how_to_implement: You must install the Splunk Microsoft Office 365 Add-on and ingest Office 365 management activity events. +known_false_positives: Business approved changes by known administrators. +references: +- https://attack.mitre.org/techniques/T1484/002/ +- https://thehackernews.com/2023/08/emerging-attacker-exploit-microsoft.html +- https://cyberaffairs.com/news/emerging-attacker-exploit-microsoft-cross-tenant-synchronization/ +- https://www.crowdstrike.com/blog/crowdstrike-defends-against-azure-cross-tenant-synchronization-attacks/ +tags: + analytic_story: + - Azure Active Directory Persistence + asset_type: Office 365 + confidence: 75 + impact: 75 + message: The user [$user$] changed the Azure cross-tenant access settings for $object_name$ $object_attrs$ [$signature$] + mitre_attack_id: + - T1484.002 + observable: + - name: user + type: user + role: + - Victim + - name: object_attrs + type: object + role: + - Attacker + product: + - Splunk Enterprise + - Splunk Enterprise Security + - Splunk Cloud + required_fields: + - _time + - Operation + - ModifiedProperties{}.NewValue + - ModifiedProperties{}.Name + - UserId + - Workload + risk_score: 75 + security_domain: threat +tests: +- name: True Positive Test + attack_data: + - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1098/o365_azure_workload_events/o365_azure_workload_events.log + sourcetype: o365:management:activity + source: o365 \ No newline at end of file diff --git a/detections/cloud/o365_external_guest_user_invited.yml b/detections/cloud/o365_external_guest_user_invited.yml new file mode 100644 index 0000000000..c7b74d4f95 --- /dev/null +++ b/detections/cloud/o365_external_guest_user_invited.yml @@ -0,0 +1,63 @@ +name: O365 External Guest User Invited +id: 8c6d52ec-d5f2-4b2f-8ba1-f32c047a71fa +version: 1 +date: '2024-04-11' +author: Steven Dick +status: production +type: TTP +description: The following analytic identifies the invitation of an external guest user within Azure AD. With Azure AD B2B collaboration, users and administrators can invite external users to collaborate with internal users. External guest account invitations should be monitored by security teams as they could potentially lead to unauthorized access. An example of this attack vector was described at BlackHat 2022 by security researcher Dirk-Jan during his tall `Backdooring and Hijacking Azure AD Accounts by Abusing External Identities`. This detection leverages the Universal Audit Log (UAL)/o365:management:activity sourcetype as a detection data source. +data_source: +- Office 365 Universal Audit Log +search: '`o365_management_activity` Workload=AzureActiveDirectory Operation="Add user*" ModifiedProperties{}.NewValue="[*Guest*]" ModifiedProperties{}.NewValue="[*Invitation*]" +| eval user = (mvindex('ModifiedProperties{}.NewValue',5)) +| rex field=user "(?[\\w\\.-]+@[\\w-]+\\.[\\w-]{2,4})" +| stats values(user) as user, min(_time) as firstTime, max(_time) as lastTime, count by Operation,Id,UserId +| rename Operation as signature, Id as signature_id, UserId as src_user +| `security_content_ctime(firstTime)` +| `security_content_ctime(lastTime)` +| `o365_external_guest_user_invited_filter`' +how_to_implement: You must install the Splunk Microsoft Office 365 Add-on and ingest Office 365 management activity events. +known_false_positives: Administrator may legitimately invite external guest users. Filter as needed. +references: +- https://dirkjanm.io/assets/raw/US-22-Mollema-Backdooring-and-hijacking-Azure-AD-accounts_final.pdf +- https://www.blackhat.com/us-22/briefings/schedule/#backdooring-and-hijacking-azure-ad-accounts-by-abusing-external-identities-26999 +- https://attack.mitre.org/techniques/T1136/003/ +- https://docs.microsoft.com/en-us/azure/active-directory/external-identities/b2b-quickstart-add-guest-users-portal +tags: + analytic_story: + - Azure Active Directory Persistence + asset_type: Office 365 + confidence: 50 + impact: 50 + message: Azure Guest User $user$ invited by $src_user$ + mitre_attack_id: + - T1136.003 + observable: + - name: user + type: user + role: + - Victim + - name: src_user + type: user + role: + - Victim + product: + - Splunk Enterprise + - Splunk Enterprise Security + - Splunk Cloud + required_fields: + - _time + - Operation + - ModifiedProperties{}.NewValue + - ModifiedProperties{}.Name + - UserId + - Id + - Workload + risk_score: 25 + security_domain: identity +tests: +- name: True Positive Test + attack_data: + - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1098/o365_azure_workload_events/o365_azure_workload_events.log + sourcetype: o365:management:activity + source: o365 \ No newline at end of file diff --git a/detections/cloud/o365_external_identity_policy_changed.yml b/detections/cloud/o365_external_identity_policy_changed.yml new file mode 100644 index 0000000000..3ac1da9291 --- /dev/null +++ b/detections/cloud/o365_external_identity_policy_changed.yml @@ -0,0 +1,63 @@ +name: O365 External Identity Policy Changed +id: 29af1725-7a72-4d2d-8a18-e697e79a62d3 +version: 1 +date: '2024-04-11' +author: Steven Dick +status: production +type: TTP +description: The following analytic identifies when changes are made to the external guest policies within Azure AD. With Azure AD B2B collaboration, users and administrators can invite external users to collaborate with internal users. External guest account invitations should be monitored by security teams as they could potentially lead to unauthorized access. An example of this attack vector was described at BlackHat 2022 by security researcher Dirk-Jan during his tall `Backdooring and Hijacking Azure AD Accounts by Abusing External Identities`. +data_source: +- Office 365 Universal Audit Log +search: '`o365_management_activity` Workload=AzureActiveDirectory Operation="Update policy." Target{}.ID="B2BManagementPolicy" +| eval object_attrs = mvindex('ModifiedProperties{}.NewValue',0), object_attrs_old = mvindex('ModifiedProperties{}.OldValue',0), object_name = mvindex('Target{}.ID',3), signature=Operation, user = UserId +| spath input=object_attrs_old output=B2BOld path={} +| spath input=B2BOld +| rename B2BManagementPolicy.* as B2BManagementPolicyOld.* +| spath input=object_attrs output=B2BNew path={} +| spath input=B2BNew +| eval object_attrs = 'B2BManagementPolicy.InvitationsAllowedAndBlockedDomainsPolicy.AllowedDomains{}' , object_attrs_old = 'B2BManagementPolicyOld.InvitationsAllowedAndBlockedDomainsPolicy.AllowedDomains{}' +| eval diff_add=mvmap(object_attrs,if(isnull(mvfind(object_attrs_old,object_attrs)),object_attrs,null)) +| eval diff_remove=mvmap(object_attrs_old,if(isnull(mvfind(object_attrs,object_attrs_old)),object_attrs_old,null)) +| eval result = case(isnotnull(diff_add),"Added ".mvjoin(diff_add,","),isnotnull(diff_remove),"Removed ".mvjoin(diff_remove,",")), action = case(isnotnull(diff_add),"created",isnotnull(diff_remove),"deleted") +| stats values(object_attrs) as object_attrs, values(action) as action, values(result) as result, values(B2BManagementPolicy*) as B2BManagementPolicy*, count, min(_time) as firstTime, max(_time) as lastTime by user,signature,object_name +| `security_content_ctime(firstTime)` +| `security_content_ctime(lastTime)` +| `o365_external_identity_policy_changed_filter`' +how_to_implement: You must install the Splunk Microsoft Office 365 Add-on and ingest Office 365 management activity events. +known_false_positives: Business approved changes by known administrators. +references: +- https://medium.com/tenable-techblog/roles-allowing-to-abuse-entra-id-federation-for-persistence-and-privilege-escalation-df9ca6e58360 +- https://learn.microsoft.com/en-us/entra/external-id/external-identities-overview +tags: + analytic_story: + - Azure Active Directory Persistence + asset_type: Office 365 + confidence: 100 + impact: 75 + message: User $user$ changed the external identity [$object_name$] policy - $result$ + mitre_attack_id: + - T1136.003 + observable: + - name: user + type: user + role: + - Victim + product: + - Splunk Enterprise + - Splunk Enterprise Security + - Splunk Cloud + required_fields: + - _time + - Operation + - ModifiedProperties{}.NewValue + - ModifiedProperties{}.Name + - UserId + - Workload + risk_score: 75 + security_domain: threat +tests: +- name: True Positive Test + attack_data: + - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1098/o365_azure_workload_events/o365_azure_workload_events.log + sourcetype: o365:management:activity + source: o365 \ No newline at end of file diff --git a/detections/cloud/o365_privileged_role_assigned.yml b/detections/cloud/o365_privileged_role_assigned.yml new file mode 100644 index 0000000000..8d29050d6d --- /dev/null +++ b/detections/cloud/o365_privileged_role_assigned.yml @@ -0,0 +1,63 @@ +name: O365 Privileged Role Assigned +id: db435700-4ddc-4c23-892e-49e7525d7d39 +version: 1 +date: '2024-04-11' +author: Steven Dick +status: production +type: TTP +description: The following analytic identifies the assignment of sensitive and privileged Azure Active Directory roles to an Azure AD user. Adversaries and red teams alike may assign these roles to a compromised account to establish Persistence in an Azure AD environment. This detection leverages the O365 Universal Audit Log data source. +data_source: +- Office 365 Universal Audit Log +search: '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add member to role.","Add eligible member to role.") +| eval user = ObjectId, src_user = UserId, object_name = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.DisplayName")), object_id = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.TemplateId")), signature = Operation, result = ResultStatus, category = mvindex('Target{}.ID',2) +| stats count, min(_time) as firstTime, max(_time) as lastTime by src_user, user, category, result, object_name, object_id, signature +| lookup privileged_azure_ad_roles azuretemplateid as object_id OUTPUT isprvilegedadrole +| search isprvilegedadrole="TRUE" category="User" +| `security_content_ctime(firstTime)` +| `security_content_ctime(lastTime)` +| `o365_privileged_role_assigned_filter`' +how_to_implement: You must install the Splunk Microsoft Office 365 Add-on and ingest Office 365 management activity events. +known_false_positives: Administrators will legitimately assign the privileged roles users as part of administrative tasks. Microsoft Privileged Identity Management (PIM) may cause false positives / less accurate alerting. +references: +- https://attack.mitre.org/techniques/T1098/003/ +- https://learn.microsoft.com/en-us/azure/active-directory/roles/permissions-reference +- https://learn.microsoft.com/en-us/microsoft-365/admin/add-users/about-exchange-online-admin-role?view=o365-worldwide +tags: + analytic_story: + - Azure Active Directory Persistence + asset_type: Office 365 + confidence: 100 + impact: 75 + message: A privileged Azure AD role [$object_name$] was assigned to user $user$ by $src_user$ + mitre_attack_id: + - T1098 + - T1098.003 + observable: + - name: user + type: user + role: + - Victim + - name: src_user + type: user + role: + - Victim + product: + - Splunk Enterprise + - Splunk Enterprise Security + - Splunk Cloud + required_fields: + - _time + - Operation + - ModifiedProperties{}.NewValue + - ModifiedProperties{}.Name + - UserId + - ObjectId + - Workload + risk_score: 75 + security_domain: identity +tests: +- name: True Positive Test + attack_data: + - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1098/o365_azure_workload_events/o365_azure_workload_events.log + sourcetype: o365:management:activity + source: o365 \ No newline at end of file diff --git a/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml b/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml new file mode 100644 index 0000000000..07bebd8eeb --- /dev/null +++ b/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml @@ -0,0 +1,64 @@ +name: O365 Privileged Role Assigned To Service Principal +id: 80f3fc1b-705f-4080-bf08-f61bf013b900 +version: 1 +date: '2024-04-11' +author: Steven Dick +status: production +type: TTP +description: The following analytic detects potential privilege escalation threats in Azure Active Directory (AD). This detection is important because it identifies instances where privileged roles that hold elevated permissions are assigned to service principals. This prevents unauthorized access or malicious activities, which occur when these non-human entities access Azure resources to exploit them. False positives might occur since administrators can legitimately assign privileged roles to service principals. This detection leverages the O365 Universal Audit Log data source. +data_source: +- Office 365 Universal Audit Log +search: '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add member to role.","Add eligible member to role.") +| eval user = ObjectId, src_user = UserId, object_name = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.DisplayName")), object_id = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.TemplateId")), signature = Operation, result = ResultStatus, category = mvindex('Target{}.ID',2) +| stats count, min(_time) as firstTime, max(_time) as lastTime by src_user, user, category, result, object_name, object_id, signature +| lookup privileged_azure_ad_roles azuretemplateid as object_id OUTPUT isprvilegedadrole +| search isprvilegedadrole="TRUE" category!="User" +| `security_content_ctime(firstTime)` +| `security_content_ctime(lastTime)` +| `o365_privileged_role_assigned_to_service_principal_filter`' +how_to_implement: You must install the Splunk Microsoft Office 365 Add-on and ingest Office 365 management activity events. +known_false_positives: Administrators may legitimately assign the privileged roles to Service Principals as part of administrative tasks. Filter as needed. +references: +- https://attack.mitre.org/techniques/T1098/003/ +- https://learn.microsoft.com/en-us/azure/active-directory/roles/permissions-reference +- https://learn.microsoft.com/en-us/microsoft-365/admin/add-users/about-exchange-online-admin-role?view=o365-worldwide +- https://posts.specterops.io/azure-privilege-escalation-via-service-principal-abuse-210ae2be2a5 +tags: + analytic_story: + - Azure Active Directory Privilege Escalation + asset_type: Office 365 + confidence: 100 + impact: 75 + message: A privileged Azure AD role [$object_name$] was assigned to the Service Principal $user$ initiated by $src_user$ + mitre_attack_id: + - T1098 + - T1098.003 + observable: + - name: user + type: user + role: + - Victim + - name: src_user + type: user + role: + - Victim + product: + - Splunk Enterprise + - Splunk Enterprise Security + - Splunk Cloud + required_fields: + - _time + - Operation + - ModifiedProperties{}.NewValue + - ModifiedProperties{}.Name + - UserId + - ObjectId + - Workload + risk_score: 75 + security_domain: identity +tests: +- name: True Positive Test + attack_data: + - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1098/o365_azure_workload_events/o365_azure_workload_events.log + sourcetype: o365:management:activity + source: o365 \ No newline at end of file From 2bcae0cee7f08f17935e507bab541f8a140ca219 Mon Sep 17 00:00:00 2001 From: Steven Dick <38897662+nterl0k@users.noreply.github.com> Date: Sat, 20 Apr 2024 14:26:58 -0400 Subject: [PATCH 03/27] Update o365_application_available_to_other_tenants.yml Better User / ServicePrincipal parsing from Actor field --- .../cloud/o365_application_available_to_other_tenants.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/detections/cloud/o365_application_available_to_other_tenants.yml b/detections/cloud/o365_application_available_to_other_tenants.yml index a05cc9ccb7..2131c7b46a 100644 --- a/detections/cloud/o365_application_available_to_other_tenants.yml +++ b/detections/cloud/o365_application_available_to_other_tenants.yml @@ -9,7 +9,7 @@ description: The following analytic identifies the configuration of Azure Active data_source: - Office 365 Universal Audit Log search: '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add application.","Update application.") ModifiedProperties{}.Name=AvailableToOtherTenants -| eval result = case(match(mvindex('ModifiedProperties{}.NewValue',mvfind('ModifiedProperties{}.Name',"AvailableToOtherTenants")),"false"),"removed",true(),"added"), object_name=mvindex('Target{}.ID', 3), signature=Operation, object_attrs = "AvailableToOtherTenants", user = mvindex('Actor{}.ID',0) +| eval result = case(match(mvindex('ModifiedProperties{}.NewValue',mvfind('ModifiedProperties{}.Name',"AvailableToOtherTenants")),"false"),"removed",true(),"added"), object_name=mvindex('Target{}.ID', 3), signature=Operation, object_attrs = "AvailableToOtherTenants", user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',1),true(),mvindex('Actor{}.ID',0)) | search result = "added" | stats values(ActorIpAddress) as src, count, min(_time) as firstTime, max(_time) as lastTime by signature, user, object, object_name, object_attrs, result | `security_content_ctime(firstTime)` @@ -61,4 +61,4 @@ tests: attack_data: - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1098/o365_azure_workload_events/o365_azure_workload_events.log sourcetype: o365:management:activity - source: o365 \ No newline at end of file + source: o365 From 8f4b5a98c6c023768703f76676617aadf609780a Mon Sep 17 00:00:00 2001 From: Steven Dick <38897662+nterl0k@users.noreply.github.com> Date: Sat, 20 Apr 2024 14:29:06 -0400 Subject: [PATCH 04/27] Update o365_cross_tenant_access_change.yml Better user/seviceprincipal parsing from actor field --- detections/cloud/o365_cross_tenant_access_change.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/detections/cloud/o365_cross_tenant_access_change.yml b/detections/cloud/o365_cross_tenant_access_change.yml index e71603d53b..ecebdd4bfe 100644 --- a/detections/cloud/o365_cross_tenant_access_change.yml +++ b/detections/cloud/o365_cross_tenant_access_change.yml @@ -9,8 +9,9 @@ description: The following analytic identifies when cross-tenant access/synchron data_source: - Office 365 Universal Audit Log search: '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add a partner to cross-tenant access setting.","Delete partner specific cross-tenant access setting.") -| stats values(Workload) as category, values(ClientIP) as src, values(ModifiedProperties{}.Name) as object_name, values(ModifiedProperties{}.NewValue) as object_attrs, count, min(_time) as firstTime, max(_time) as lastTime by Id, UserId, Operation -| rename Operation as signature, Id as signature_id, UserId as user +| eval user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',1),true(),mvindex('Actor{}.ID',0)) +| stats values(Workload) as category, values(ClientIP) as src, values(ModifiedProperties{}.Name) as object_name, values(ModifiedProperties{}.NewValue) as object_attrs, count, min(_time) as firstTime, max(_time) as lastTime by Id,user,Operation +| rename Operation as signature, Id as signature_id | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` | `o365_cross_tenant_access_change_filter`' @@ -57,4 +58,4 @@ tests: attack_data: - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1098/o365_azure_workload_events/o365_azure_workload_events.log sourcetype: o365:management:activity - source: o365 \ No newline at end of file + source: o365 From 7fce2ad5a0b5d11f7d86a8791b2299d4f7a94c52 Mon Sep 17 00:00:00 2001 From: Steven Dick <38897662+nterl0k@users.noreply.github.com> Date: Sat, 20 Apr 2024 14:30:11 -0400 Subject: [PATCH 05/27] Update o365_external_guest_user_invited.yml user/servicepincipal parsing update --- detections/cloud/o365_external_guest_user_invited.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/detections/cloud/o365_external_guest_user_invited.yml b/detections/cloud/o365_external_guest_user_invited.yml index c7b74d4f95..8aede148c9 100644 --- a/detections/cloud/o365_external_guest_user_invited.yml +++ b/detections/cloud/o365_external_guest_user_invited.yml @@ -8,11 +8,11 @@ type: TTP description: The following analytic identifies the invitation of an external guest user within Azure AD. With Azure AD B2B collaboration, users and administrators can invite external users to collaborate with internal users. External guest account invitations should be monitored by security teams as they could potentially lead to unauthorized access. An example of this attack vector was described at BlackHat 2022 by security researcher Dirk-Jan during his tall `Backdooring and Hijacking Azure AD Accounts by Abusing External Identities`. This detection leverages the Universal Audit Log (UAL)/o365:management:activity sourcetype as a detection data source. data_source: - Office 365 Universal Audit Log -search: '`o365_management_activity` Workload=AzureActiveDirectory Operation="Add user*" ModifiedProperties{}.NewValue="[*Guest*]" ModifiedProperties{}.NewValue="[*Invitation*]" -| eval user = (mvindex('ModifiedProperties{}.NewValue',5)) +search: '`o365_management_activity` Workload=AzureActiveDirectory AND Operation="Add user*" AND ModifiedProperties{}.NewValue="[*Guest*]" AND ModifiedProperties{}.NewValue="[*Invitation*]" +| eval user = (mvindex('ModifiedProperties{}.NewValue',5)), src_user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',1),true(),mvindex('Actor{}.ID',0)) | rex field=user "(?[\\w\\.-]+@[\\w-]+\\.[\\w-]{2,4})" -| stats values(user) as user, min(_time) as firstTime, max(_time) as lastTime, count by Operation,Id,UserId -| rename Operation as signature, Id as signature_id, UserId as src_user +| stats values(user) as user, min(_time) as firstTime, max(_time) as lastTime, count by Operation,Id,src_user +| rename Operation as signature, Id as signature_id | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` | `o365_external_guest_user_invited_filter`' @@ -60,4 +60,4 @@ tests: attack_data: - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1098/o365_azure_workload_events/o365_azure_workload_events.log sourcetype: o365:management:activity - source: o365 \ No newline at end of file + source: o365 From c8f8fb22a543453fed76d089b0945ac0c1dc7f38 Mon Sep 17 00:00:00 2001 From: Steven Dick <38897662+nterl0k@users.noreply.github.com> Date: Sat, 20 Apr 2024 14:31:42 -0400 Subject: [PATCH 06/27] Update o365_external_identity_policy_changed.yml user/servicepincipal parsing update --- detections/cloud/o365_external_identity_policy_changed.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/detections/cloud/o365_external_identity_policy_changed.yml b/detections/cloud/o365_external_identity_policy_changed.yml index 3ac1da9291..366c96be51 100644 --- a/detections/cloud/o365_external_identity_policy_changed.yml +++ b/detections/cloud/o365_external_identity_policy_changed.yml @@ -5,11 +5,11 @@ date: '2024-04-11' author: Steven Dick status: production type: TTP -description: The following analytic identifies when changes are made to the external guest policies within Azure AD. With Azure AD B2B collaboration, users and administrators can invite external users to collaborate with internal users. External guest account invitations should be monitored by security teams as they could potentially lead to unauthorized access. An example of this attack vector was described at BlackHat 2022 by security researcher Dirk-Jan during his tall `Backdooring and Hijacking Azure AD Accounts by Abusing External Identities`. +description: The following analytic identifies when changes are made to the external guest policies within Azure AD. With Azure AD B2B collaboration, users and administrators can invite external users to collaborate with internal users. This detection also attempts to highlight what may have changed. External guest account invitations should be monitored by security teams as they could potentially lead to unauthorized access. An example of this attack vector was described at BlackHat 2022 by security researcher Dirk-Jan during his tall `Backdooring and Hijacking Azure AD Accounts by Abusing External Identities`. data_source: - Office 365 Universal Audit Log search: '`o365_management_activity` Workload=AzureActiveDirectory Operation="Update policy." Target{}.ID="B2BManagementPolicy" -| eval object_attrs = mvindex('ModifiedProperties{}.NewValue',0), object_attrs_old = mvindex('ModifiedProperties{}.OldValue',0), object_name = mvindex('Target{}.ID',3), signature=Operation, user = UserId +| eval object_attrs = mvindex('ModifiedProperties{}.NewValue',0), object_attrs_old = mvindex('ModifiedProperties{}.OldValue',0), object_name = mvindex('Target{}.ID',3), signature=Operation, user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',1),true(),mvindex('Actor{}.ID',0)) | spath input=object_attrs_old output=B2BOld path={} | spath input=B2BOld | rename B2BManagementPolicy.* as B2BManagementPolicyOld.* @@ -60,4 +60,4 @@ tests: attack_data: - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1098/o365_azure_workload_events/o365_azure_workload_events.log sourcetype: o365:management:activity - source: o365 \ No newline at end of file + source: o365 From fdeb58ce9ea84317c6d730183dfbce58a45b07ef Mon Sep 17 00:00:00 2001 From: Steven Dick <38897662+nterl0k@users.noreply.github.com> Date: Sat, 20 Apr 2024 14:32:28 -0400 Subject: [PATCH 07/27] Update o365_privileged_role_assigned.yml user/servicepincipal parsing update --- detections/cloud/o365_privileged_role_assigned.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/detections/cloud/o365_privileged_role_assigned.yml b/detections/cloud/o365_privileged_role_assigned.yml index 8d29050d6d..6eb9f09fa4 100644 --- a/detections/cloud/o365_privileged_role_assigned.yml +++ b/detections/cloud/o365_privileged_role_assigned.yml @@ -9,7 +9,7 @@ description: The following analytic identifies the assignment of sensitive and p data_source: - Office 365 Universal Audit Log search: '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add member to role.","Add eligible member to role.") -| eval user = ObjectId, src_user = UserId, object_name = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.DisplayName")), object_id = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.TemplateId")), signature = Operation, result = ResultStatus, category = mvindex('Target{}.ID',2) +| eval user = ObjectId, src_user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',1),true(),mvindex('Actor{}.ID',0)), object_name = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.DisplayName")), object_id = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.TemplateId")), signature = Operation, result = ResultStatus, category = mvindex('Target{}.ID',2) | stats count, min(_time) as firstTime, max(_time) as lastTime by src_user, user, category, result, object_name, object_id, signature | lookup privileged_azure_ad_roles azuretemplateid as object_id OUTPUT isprvilegedadrole | search isprvilegedadrole="TRUE" category="User" @@ -60,4 +60,4 @@ tests: attack_data: - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1098/o365_azure_workload_events/o365_azure_workload_events.log sourcetype: o365:management:activity - source: o365 \ No newline at end of file + source: o365 From 0dae8e9b564ce42541f512625933d954722644f4 Mon Sep 17 00:00:00 2001 From: Steven Dick <38897662+nterl0k@users.noreply.github.com> Date: Sat, 20 Apr 2024 14:34:34 -0400 Subject: [PATCH 08/27] Update o365_privileged_role_assigned_to_service_principal.yml user/servicepincipal parsing update --- .../o365_privileged_role_assigned_to_service_principal.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml b/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml index 07bebd8eeb..589d66b32d 100644 --- a/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml +++ b/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml @@ -9,7 +9,7 @@ description: The following analytic detects potential privilege escalation threa data_source: - Office 365 Universal Audit Log search: '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add member to role.","Add eligible member to role.") -| eval user = ObjectId, src_user = UserId, object_name = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.DisplayName")), object_id = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.TemplateId")), signature = Operation, result = ResultStatus, category = mvindex('Target{}.ID',2) +| eval user = ObjectId, src_user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',1),true(),mvindex('Actor{}.ID',0)), object_name = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.DisplayName")), object_id = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.TemplateId")), signature = Operation, result = ResultStatus, category = mvindex('Target{}.ID',2) | stats count, min(_time) as firstTime, max(_time) as lastTime by src_user, user, category, result, object_name, object_id, signature | lookup privileged_azure_ad_roles azuretemplateid as object_id OUTPUT isprvilegedadrole | search isprvilegedadrole="TRUE" category!="User" @@ -61,4 +61,4 @@ tests: attack_data: - data: https://media.githubusercontent.com/media/splunk/attack_data/master/datasets/attack_techniques/T1098/o365_azure_workload_events/o365_azure_workload_events.log sourcetype: o365:management:activity - source: o365 \ No newline at end of file + source: o365 From e5db5a12df1f67d442a5c2c79a2eefbc3b6394b5 Mon Sep 17 00:00:00 2001 From: Steven Dick <38897662+nterl0k@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:47:42 -0400 Subject: [PATCH 09/27] Update o365_application_available_to_other_tenants.yml Update for better ServicePrincipal GUID --- .../cloud/o365_application_available_to_other_tenants.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detections/cloud/o365_application_available_to_other_tenants.yml b/detections/cloud/o365_application_available_to_other_tenants.yml index 2131c7b46a..ab56e77215 100644 --- a/detections/cloud/o365_application_available_to_other_tenants.yml +++ b/detections/cloud/o365_application_available_to_other_tenants.yml @@ -9,7 +9,7 @@ description: The following analytic identifies the configuration of Azure Active data_source: - Office 365 Universal Audit Log search: '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add application.","Update application.") ModifiedProperties{}.Name=AvailableToOtherTenants -| eval result = case(match(mvindex('ModifiedProperties{}.NewValue',mvfind('ModifiedProperties{}.Name',"AvailableToOtherTenants")),"false"),"removed",true(),"added"), object_name=mvindex('Target{}.ID', 3), signature=Operation, object_attrs = "AvailableToOtherTenants", user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',1),true(),mvindex('Actor{}.ID',0)) +| eval result = case(match(mvindex('ModifiedProperties{}.NewValue',mvfind('ModifiedProperties{}.Name',"AvailableToOtherTenants")),"false"),"removed",true(),"added"), object_name=mvindex('Target{}.ID', 3), signature=Operation, object_attrs = "AvailableToOtherTenants", user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)) | search result = "added" | stats values(ActorIpAddress) as src, count, min(_time) as firstTime, max(_time) as lastTime by signature, user, object, object_name, object_attrs, result | `security_content_ctime(firstTime)` From 1b28384657141f1e02d74fb427870929f19e07fd Mon Sep 17 00:00:00 2001 From: Steven Dick <38897662+nterl0k@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:48:03 -0400 Subject: [PATCH 10/27] Update o365_cross_tenant_access_change.yml Update for better ServicePrincipal GUID --- detections/cloud/o365_cross_tenant_access_change.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detections/cloud/o365_cross_tenant_access_change.yml b/detections/cloud/o365_cross_tenant_access_change.yml index ecebdd4bfe..6401427b3e 100644 --- a/detections/cloud/o365_cross_tenant_access_change.yml +++ b/detections/cloud/o365_cross_tenant_access_change.yml @@ -9,7 +9,7 @@ description: The following analytic identifies when cross-tenant access/synchron data_source: - Office 365 Universal Audit Log search: '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add a partner to cross-tenant access setting.","Delete partner specific cross-tenant access setting.") -| eval user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',1),true(),mvindex('Actor{}.ID',0)) +| eval user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)) | stats values(Workload) as category, values(ClientIP) as src, values(ModifiedProperties{}.Name) as object_name, values(ModifiedProperties{}.NewValue) as object_attrs, count, min(_time) as firstTime, max(_time) as lastTime by Id,user,Operation | rename Operation as signature, Id as signature_id | `security_content_ctime(firstTime)` From 28ed9a8320272edf643c88d637c3935057d8eb95 Mon Sep 17 00:00:00 2001 From: Steven Dick <38897662+nterl0k@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:48:30 -0400 Subject: [PATCH 11/27] Update o365_external_identity_policy_changed.yml Update for better ServicePrincipal GUID --- detections/cloud/o365_external_identity_policy_changed.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detections/cloud/o365_external_identity_policy_changed.yml b/detections/cloud/o365_external_identity_policy_changed.yml index 366c96be51..d12edbd01e 100644 --- a/detections/cloud/o365_external_identity_policy_changed.yml +++ b/detections/cloud/o365_external_identity_policy_changed.yml @@ -9,7 +9,7 @@ description: The following analytic identifies when changes are made to the exte data_source: - Office 365 Universal Audit Log search: '`o365_management_activity` Workload=AzureActiveDirectory Operation="Update policy." Target{}.ID="B2BManagementPolicy" -| eval object_attrs = mvindex('ModifiedProperties{}.NewValue',0), object_attrs_old = mvindex('ModifiedProperties{}.OldValue',0), object_name = mvindex('Target{}.ID',3), signature=Operation, user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',1),true(),mvindex('Actor{}.ID',0)) +| eval object_attrs = mvindex('ModifiedProperties{}.NewValue',0), object_attrs_old = mvindex('ModifiedProperties{}.OldValue',0), object_name = mvindex('Target{}.ID',3), signature=Operation, user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)) | spath input=object_attrs_old output=B2BOld path={} | spath input=B2BOld | rename B2BManagementPolicy.* as B2BManagementPolicyOld.* From 673d5a002bbb6bb2ab815bffac029be693dcd574 Mon Sep 17 00:00:00 2001 From: Steven Dick <38897662+nterl0k@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:49:55 -0400 Subject: [PATCH 12/27] Update o365_external_guest_user_invited.yml Update for better ServicePrincipal GUID --- detections/cloud/o365_external_guest_user_invited.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detections/cloud/o365_external_guest_user_invited.yml b/detections/cloud/o365_external_guest_user_invited.yml index 8aede148c9..f448f16236 100644 --- a/detections/cloud/o365_external_guest_user_invited.yml +++ b/detections/cloud/o365_external_guest_user_invited.yml @@ -9,7 +9,7 @@ description: The following analytic identifies the invitation of an external gue data_source: - Office 365 Universal Audit Log search: '`o365_management_activity` Workload=AzureActiveDirectory AND Operation="Add user*" AND ModifiedProperties{}.NewValue="[*Guest*]" AND ModifiedProperties{}.NewValue="[*Invitation*]" -| eval user = (mvindex('ModifiedProperties{}.NewValue',5)), src_user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',1),true(),mvindex('Actor{}.ID',0)) +| eval user = (mvindex('ModifiedProperties{}.NewValue',5)), src_user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)) | rex field=user "(?[\\w\\.-]+@[\\w-]+\\.[\\w-]{2,4})" | stats values(user) as user, min(_time) as firstTime, max(_time) as lastTime, count by Operation,Id,src_user | rename Operation as signature, Id as signature_id From 391213002c6fdccb5ccab6c2911d7f46b10a64c3 Mon Sep 17 00:00:00 2001 From: Steven Dick <38897662+nterl0k@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:50:46 -0400 Subject: [PATCH 13/27] Update o365_privileged_role_assigned.yml Update for better ServicePrincipal GUID --- detections/cloud/o365_privileged_role_assigned.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detections/cloud/o365_privileged_role_assigned.yml b/detections/cloud/o365_privileged_role_assigned.yml index 6eb9f09fa4..9b1e144831 100644 --- a/detections/cloud/o365_privileged_role_assigned.yml +++ b/detections/cloud/o365_privileged_role_assigned.yml @@ -9,7 +9,7 @@ description: The following analytic identifies the assignment of sensitive and p data_source: - Office 365 Universal Audit Log search: '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add member to role.","Add eligible member to role.") -| eval user = ObjectId, src_user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',1),true(),mvindex('Actor{}.ID',0)), object_name = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.DisplayName")), object_id = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.TemplateId")), signature = Operation, result = ResultStatus, category = mvindex('Target{}.ID',2) +| eval user = ObjectId, src_user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)), object_name = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.DisplayName")), object_id = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.TemplateId")), signature = Operation, result = ResultStatus, category = mvindex('Target{}.ID',2) | stats count, min(_time) as firstTime, max(_time) as lastTime by src_user, user, category, result, object_name, object_id, signature | lookup privileged_azure_ad_roles azuretemplateid as object_id OUTPUT isprvilegedadrole | search isprvilegedadrole="TRUE" category="User" From 54ad055b7a72354a8647f674d5430dbfbd4fadab Mon Sep 17 00:00:00 2001 From: Steven Dick <38897662+nterl0k@users.noreply.github.com> Date: Wed, 24 Apr 2024 10:51:09 -0400 Subject: [PATCH 14/27] Update o365_privileged_role_assigned_to_service_principal.yml Update for better ServicePrincipal GUID --- .../o365_privileged_role_assigned_to_service_principal.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml b/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml index 589d66b32d..9670188672 100644 --- a/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml +++ b/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml @@ -9,7 +9,7 @@ description: The following analytic detects potential privilege escalation threa data_source: - Office 365 Universal Audit Log search: '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add member to role.","Add eligible member to role.") -| eval user = ObjectId, src_user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',1),true(),mvindex('Actor{}.ID',0)), object_name = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.DisplayName")), object_id = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.TemplateId")), signature = Operation, result = ResultStatus, category = mvindex('Target{}.ID',2) +| eval user = ObjectId, src_user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)), object_name = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.DisplayName")), object_id = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.TemplateId")), signature = Operation, result = ResultStatus, category = mvindex('Target{}.ID',2) | stats count, min(_time) as firstTime, max(_time) as lastTime by src_user, user, category, result, object_name, object_id, signature | lookup privileged_azure_ad_roles azuretemplateid as object_id OUTPUT isprvilegedadrole | search isprvilegedadrole="TRUE" category!="User" From 86103ec44c0def8fa66b6521dd9abec239456665 Mon Sep 17 00:00:00 2001 From: Steven Dick <38897662+nterl0k@users.noreply.github.com> Date: Sat, 4 May 2024 12:21:04 -0400 Subject: [PATCH 15/27] Update o365_application_available_to_other_tenants.yml --- .../cloud/o365_application_available_to_other_tenants.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/detections/cloud/o365_application_available_to_other_tenants.yml b/detections/cloud/o365_application_available_to_other_tenants.yml index ab56e77215..b4a727fbf8 100644 --- a/detections/cloud/o365_application_available_to_other_tenants.yml +++ b/detections/cloud/o365_application_available_to_other_tenants.yml @@ -35,11 +35,11 @@ tags: - T1098 observable: - name: user - type: user + type: User role: - Victim - name: object_name - type: object + type: Other role: - Attacker product: From fa0e3090c1d94c66baf5f8c516dd290b10053d99 Mon Sep 17 00:00:00 2001 From: Steven Dick <38897662+nterl0k@users.noreply.github.com> Date: Sat, 4 May 2024 12:21:29 -0400 Subject: [PATCH 16/27] Update o365_cross_tenant_access_change.yml --- detections/cloud/o365_cross_tenant_access_change.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/detections/cloud/o365_cross_tenant_access_change.yml b/detections/cloud/o365_cross_tenant_access_change.yml index 6401427b3e..82698acb6c 100644 --- a/detections/cloud/o365_cross_tenant_access_change.yml +++ b/detections/cloud/o365_cross_tenant_access_change.yml @@ -33,11 +33,11 @@ tags: - T1484.002 observable: - name: user - type: user + type: User role: - Victim - name: object_attrs - type: object + type: Other role: - Attacker product: From 0312cc1318dff93290a41ee096c4fa4272715dc9 Mon Sep 17 00:00:00 2001 From: Steven Dick <38897662+nterl0k@users.noreply.github.com> Date: Sat, 4 May 2024 12:22:04 -0400 Subject: [PATCH 17/27] Update o365_external_guest_user_invited.yml --- detections/cloud/o365_external_guest_user_invited.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/detections/cloud/o365_external_guest_user_invited.yml b/detections/cloud/o365_external_guest_user_invited.yml index f448f16236..7447342eb3 100644 --- a/detections/cloud/o365_external_guest_user_invited.yml +++ b/detections/cloud/o365_external_guest_user_invited.yml @@ -34,11 +34,11 @@ tags: - T1136.003 observable: - name: user - type: user + type: User role: - Victim - name: src_user - type: user + type: User role: - Victim product: From 2037a3d6f0961a0802eae62e7c55ab361de70773 Mon Sep 17 00:00:00 2001 From: Steven Dick <38897662+nterl0k@users.noreply.github.com> Date: Sat, 4 May 2024 12:22:20 -0400 Subject: [PATCH 18/27] Update o365_external_identity_policy_changed.yml --- detections/cloud/o365_external_identity_policy_changed.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/detections/cloud/o365_external_identity_policy_changed.yml b/detections/cloud/o365_external_identity_policy_changed.yml index d12edbd01e..39c2f51df5 100644 --- a/detections/cloud/o365_external_identity_policy_changed.yml +++ b/detections/cloud/o365_external_identity_policy_changed.yml @@ -39,7 +39,7 @@ tags: - T1136.003 observable: - name: user - type: user + type: User role: - Victim product: From b1a7449413638e4c48edffaa7c802ac716890920 Mon Sep 17 00:00:00 2001 From: Steven Dick <38897662+nterl0k@users.noreply.github.com> Date: Sat, 4 May 2024 12:22:40 -0400 Subject: [PATCH 19/27] Update o365_privileged_role_assigned.yml --- detections/cloud/o365_privileged_role_assigned.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/detections/cloud/o365_privileged_role_assigned.yml b/detections/cloud/o365_privileged_role_assigned.yml index 9b1e144831..bb61f4cfa0 100644 --- a/detections/cloud/o365_privileged_role_assigned.yml +++ b/detections/cloud/o365_privileged_role_assigned.yml @@ -34,11 +34,11 @@ tags: - T1098.003 observable: - name: user - type: user + type: User role: - Victim - name: src_user - type: user + type: User role: - Victim product: From f0b2e96d56fcbb44acc6fc7753ced42f361d8f14 Mon Sep 17 00:00:00 2001 From: Steven Dick <38897662+nterl0k@users.noreply.github.com> Date: Sat, 4 May 2024 12:23:00 -0400 Subject: [PATCH 20/27] Update o365_privileged_role_assigned_to_service_principal.yml --- .../o365_privileged_role_assigned_to_service_principal.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml b/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml index 9670188672..b02d548a61 100644 --- a/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml +++ b/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml @@ -35,11 +35,11 @@ tags: - T1098.003 observable: - name: user - type: user + type: User role: - Victim - name: src_user - type: user + type: User role: - Victim product: From 6374f4068dd8b6a791b5e3928d177bbbaeaf5ba2 Mon Sep 17 00:00:00 2001 From: ljstella Date: Wed, 24 Jul 2024 16:13:58 -0500 Subject: [PATCH 21/27] Formatting search blocks and fixed tags.asset_type --- ...application_available_to_other_tenants.yml | 17 +++++----- .../cloud/o365_cross_tenant_access_change.yml | 17 +++++----- .../o365_external_guest_user_invited.yml | 19 ++++++----- .../o365_external_identity_policy_changed.yml | 33 ++++++++++--------- .../cloud/o365_privileged_role_assigned.yml | 19 ++++++----- ...ged_role_assigned_to_service_principal.yml | 19 ++++++----- 6 files changed, 65 insertions(+), 59 deletions(-) diff --git a/detections/cloud/o365_application_available_to_other_tenants.yml b/detections/cloud/o365_application_available_to_other_tenants.yml index b4a727fbf8..afe0f18efd 100644 --- a/detections/cloud/o365_application_available_to_other_tenants.yml +++ b/detections/cloud/o365_application_available_to_other_tenants.yml @@ -8,13 +8,14 @@ type: TTP description: The following analytic identifies the configuration of Azure Active Directory Applications in a manner that allows authentication from external tenants or personal accounts. This configuration can lead to inappropriate or malicious access of any data or capabilities the application is allowed to access. This detection leverages the O365 Universal Audit Log data source. data_source: - Office 365 Universal Audit Log -search: '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add application.","Update application.") ModifiedProperties{}.Name=AvailableToOtherTenants -| eval result = case(match(mvindex('ModifiedProperties{}.NewValue',mvfind('ModifiedProperties{}.Name',"AvailableToOtherTenants")),"false"),"removed",true(),"added"), object_name=mvindex('Target{}.ID', 3), signature=Operation, object_attrs = "AvailableToOtherTenants", user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)) -| search result = "added" -| stats values(ActorIpAddress) as src, count, min(_time) as firstTime, max(_time) as lastTime by signature, user, object, object_name, object_attrs, result -| `security_content_ctime(firstTime)` -| `security_content_ctime(lastTime)` -| `o365_application_available_to_other_tenants_filter`' +search: > + `o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add application.","Update application.") ModifiedProperties{}.Name=AvailableToOtherTenants + | eval result = case(match(mvindex('ModifiedProperties{}.NewValue',mvfind('ModifiedProperties{}.Name',"AvailableToOtherTenants")),"false"),"removed",true(),"added"), object_name=mvindex('Target{}.ID', 3), signature=Operation, object_attrs = "AvailableToOtherTenants", user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)) + | search result = "added" + | stats values(ActorIpAddress) as src, count, min(_time) as firstTime, max(_time) as lastTime by signature, user, object, object_name, object_attrs, result + | `security_content_ctime(firstTime)` + | `security_content_ctime(lastTime)` + | `o365_application_available_to_other_tenants_filter` how_to_implement: You must install the Splunk Microsoft Office 365 Add-on and ingest Office 365 management activity events. known_false_positives: Business approved changes by known administrators. references: @@ -26,7 +27,7 @@ tags: - Azure Active Directory Persistence - Azure Active Directory Account Takeover - Data Exfiltration - asset_type: Office 365 + asset_type: O365 Tenant confidence: 100 impact: 50 message: An Azure Application [$object_name$] was configured by [$user$] as accessible to external tenants. diff --git a/detections/cloud/o365_cross_tenant_access_change.yml b/detections/cloud/o365_cross_tenant_access_change.yml index 82698acb6c..0fbf284b52 100644 --- a/detections/cloud/o365_cross_tenant_access_change.yml +++ b/detections/cloud/o365_cross_tenant_access_change.yml @@ -8,13 +8,14 @@ type: TTP description: The following analytic identifies when cross-tenant access/synchronization policies are changed in an Azure tenant. Adversaries have been observed altering victim cross-tenant policies as a method of lateral movement or maintaining persistent access to compromised environments. These policies should be considered sensitive and monitored for changes and/or loose configuration. data_source: - Office 365 Universal Audit Log -search: '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add a partner to cross-tenant access setting.","Delete partner specific cross-tenant access setting.") -| eval user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)) -| stats values(Workload) as category, values(ClientIP) as src, values(ModifiedProperties{}.Name) as object_name, values(ModifiedProperties{}.NewValue) as object_attrs, count, min(_time) as firstTime, max(_time) as lastTime by Id,user,Operation -| rename Operation as signature, Id as signature_id -| `security_content_ctime(firstTime)` -| `security_content_ctime(lastTime)` -| `o365_cross_tenant_access_change_filter`' +search: > + '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add a partner to cross-tenant access setting.","Delete partner specific cross-tenant access setting.") + | eval user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)) + | stats values(Workload) as category, values(ClientIP) as src, values(ModifiedProperties{}.Name) as object_name, values(ModifiedProperties{}.NewValue) as object_attrs, count, min(_time) as firstTime, max(_time) as lastTime by Id,user,Operation + | rename Operation as signature, Id as signature_id + | `security_content_ctime(firstTime)` + | `security_content_ctime(lastTime)` + | `o365_cross_tenant_access_change_filter`' how_to_implement: You must install the Splunk Microsoft Office 365 Add-on and ingest Office 365 management activity events. known_false_positives: Business approved changes by known administrators. references: @@ -25,7 +26,7 @@ references: tags: analytic_story: - Azure Active Directory Persistence - asset_type: Office 365 + asset_type: O365 Tenant confidence: 75 impact: 75 message: The user [$user$] changed the Azure cross-tenant access settings for $object_name$ $object_attrs$ [$signature$] diff --git a/detections/cloud/o365_external_guest_user_invited.yml b/detections/cloud/o365_external_guest_user_invited.yml index 7447342eb3..93c9c8050f 100644 --- a/detections/cloud/o365_external_guest_user_invited.yml +++ b/detections/cloud/o365_external_guest_user_invited.yml @@ -8,14 +8,15 @@ type: TTP description: The following analytic identifies the invitation of an external guest user within Azure AD. With Azure AD B2B collaboration, users and administrators can invite external users to collaborate with internal users. External guest account invitations should be monitored by security teams as they could potentially lead to unauthorized access. An example of this attack vector was described at BlackHat 2022 by security researcher Dirk-Jan during his tall `Backdooring and Hijacking Azure AD Accounts by Abusing External Identities`. This detection leverages the Universal Audit Log (UAL)/o365:management:activity sourcetype as a detection data source. data_source: - Office 365 Universal Audit Log -search: '`o365_management_activity` Workload=AzureActiveDirectory AND Operation="Add user*" AND ModifiedProperties{}.NewValue="[*Guest*]" AND ModifiedProperties{}.NewValue="[*Invitation*]" -| eval user = (mvindex('ModifiedProperties{}.NewValue',5)), src_user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)) -| rex field=user "(?[\\w\\.-]+@[\\w-]+\\.[\\w-]{2,4})" -| stats values(user) as user, min(_time) as firstTime, max(_time) as lastTime, count by Operation,Id,src_user -| rename Operation as signature, Id as signature_id -| `security_content_ctime(firstTime)` -| `security_content_ctime(lastTime)` -| `o365_external_guest_user_invited_filter`' +search: > + '`o365_management_activity` Workload=AzureActiveDirectory AND Operation="Add user*" AND ModifiedProperties{}.NewValue="[*Guest*]" AND ModifiedProperties{}.NewValue="[*Invitation*]" + | eval user = (mvindex('ModifiedProperties{}.NewValue',5)), src_user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)) + | rex field=user "(?[\\w\\.-]+@[\\w-]+\\.[\\w-]{2,4})" + | stats values(user) as user, min(_time) as firstTime, max(_time) as lastTime, count by Operation,Id,src_user + | rename Operation as signature, Id as signature_id + | `security_content_ctime(firstTime)` + | `security_content_ctime(lastTime)` + | `o365_external_guest_user_invited_filter`' how_to_implement: You must install the Splunk Microsoft Office 365 Add-on and ingest Office 365 management activity events. known_false_positives: Administrator may legitimately invite external guest users. Filter as needed. references: @@ -26,7 +27,7 @@ references: tags: analytic_story: - Azure Active Directory Persistence - asset_type: Office 365 + asset_type: O365 Tenant confidence: 50 impact: 50 message: Azure Guest User $user$ invited by $src_user$ diff --git a/detections/cloud/o365_external_identity_policy_changed.yml b/detections/cloud/o365_external_identity_policy_changed.yml index 39c2f51df5..98f1476669 100644 --- a/detections/cloud/o365_external_identity_policy_changed.yml +++ b/detections/cloud/o365_external_identity_policy_changed.yml @@ -8,21 +8,22 @@ type: TTP description: The following analytic identifies when changes are made to the external guest policies within Azure AD. With Azure AD B2B collaboration, users and administrators can invite external users to collaborate with internal users. This detection also attempts to highlight what may have changed. External guest account invitations should be monitored by security teams as they could potentially lead to unauthorized access. An example of this attack vector was described at BlackHat 2022 by security researcher Dirk-Jan during his tall `Backdooring and Hijacking Azure AD Accounts by Abusing External Identities`. data_source: - Office 365 Universal Audit Log -search: '`o365_management_activity` Workload=AzureActiveDirectory Operation="Update policy." Target{}.ID="B2BManagementPolicy" -| eval object_attrs = mvindex('ModifiedProperties{}.NewValue',0), object_attrs_old = mvindex('ModifiedProperties{}.OldValue',0), object_name = mvindex('Target{}.ID',3), signature=Operation, user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)) -| spath input=object_attrs_old output=B2BOld path={} -| spath input=B2BOld -| rename B2BManagementPolicy.* as B2BManagementPolicyOld.* -| spath input=object_attrs output=B2BNew path={} -| spath input=B2BNew -| eval object_attrs = 'B2BManagementPolicy.InvitationsAllowedAndBlockedDomainsPolicy.AllowedDomains{}' , object_attrs_old = 'B2BManagementPolicyOld.InvitationsAllowedAndBlockedDomainsPolicy.AllowedDomains{}' -| eval diff_add=mvmap(object_attrs,if(isnull(mvfind(object_attrs_old,object_attrs)),object_attrs,null)) -| eval diff_remove=mvmap(object_attrs_old,if(isnull(mvfind(object_attrs,object_attrs_old)),object_attrs_old,null)) -| eval result = case(isnotnull(diff_add),"Added ".mvjoin(diff_add,","),isnotnull(diff_remove),"Removed ".mvjoin(diff_remove,",")), action = case(isnotnull(diff_add),"created",isnotnull(diff_remove),"deleted") -| stats values(object_attrs) as object_attrs, values(action) as action, values(result) as result, values(B2BManagementPolicy*) as B2BManagementPolicy*, count, min(_time) as firstTime, max(_time) as lastTime by user,signature,object_name -| `security_content_ctime(firstTime)` -| `security_content_ctime(lastTime)` -| `o365_external_identity_policy_changed_filter`' +search: > + '`o365_management_activity` Workload=AzureActiveDirectory Operation="Update policy." Target{}.ID="B2BManagementPolicy" + | eval object_attrs = mvindex('ModifiedProperties{}.NewValue',0), object_attrs_old = mvindex('ModifiedProperties{}.OldValue',0), object_name = mvindex('Target{}.ID',3), signature=Operation, user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)) + | spath input=object_attrs_old output=B2BOld path={} + | spath input=B2BOld + | rename B2BManagementPolicy.* as B2BManagementPolicyOld.* + | spath input=object_attrs output=B2BNew path={} + | spath input=B2BNew + | eval object_attrs = 'B2BManagementPolicy.InvitationsAllowedAndBlockedDomainsPolicy.AllowedDomains{}' , object_attrs_old = 'B2BManagementPolicyOld.InvitationsAllowedAndBlockedDomainsPolicy.AllowedDomains{}' + | eval diff_add=mvmap(object_attrs,if(isnull(mvfind(object_attrs_old,object_attrs)),object_attrs,null)) + | eval diff_remove=mvmap(object_attrs_old,if(isnull(mvfind(object_attrs,object_attrs_old)),object_attrs_old,null)) + | eval result = case(isnotnull(diff_add),"Added ".mvjoin(diff_add,","),isnotnull(diff_remove),"Removed ".mvjoin(diff_remove,",")), action = case(isnotnull(diff_add),"created",isnotnull(diff_remove),"deleted") + | stats values(object_attrs) as object_attrs, values(action) as action, values(result) as result, values(B2BManagementPolicy*) as B2BManagementPolicy*, count, min(_time) as firstTime, max(_time) as lastTime by user,signature,object_name + | `security_content_ctime(firstTime)` + | `security_content_ctime(lastTime)` + | `o365_external_identity_policy_changed_filter`' how_to_implement: You must install the Splunk Microsoft Office 365 Add-on and ingest Office 365 management activity events. known_false_positives: Business approved changes by known administrators. references: @@ -31,7 +32,7 @@ references: tags: analytic_story: - Azure Active Directory Persistence - asset_type: Office 365 + asset_type: O365 Tenant confidence: 100 impact: 75 message: User $user$ changed the external identity [$object_name$] policy - $result$ diff --git a/detections/cloud/o365_privileged_role_assigned.yml b/detections/cloud/o365_privileged_role_assigned.yml index bb61f4cfa0..bc37779a67 100644 --- a/detections/cloud/o365_privileged_role_assigned.yml +++ b/detections/cloud/o365_privileged_role_assigned.yml @@ -8,14 +8,15 @@ type: TTP description: The following analytic identifies the assignment of sensitive and privileged Azure Active Directory roles to an Azure AD user. Adversaries and red teams alike may assign these roles to a compromised account to establish Persistence in an Azure AD environment. This detection leverages the O365 Universal Audit Log data source. data_source: - Office 365 Universal Audit Log -search: '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add member to role.","Add eligible member to role.") -| eval user = ObjectId, src_user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)), object_name = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.DisplayName")), object_id = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.TemplateId")), signature = Operation, result = ResultStatus, category = mvindex('Target{}.ID',2) -| stats count, min(_time) as firstTime, max(_time) as lastTime by src_user, user, category, result, object_name, object_id, signature -| lookup privileged_azure_ad_roles azuretemplateid as object_id OUTPUT isprvilegedadrole -| search isprvilegedadrole="TRUE" category="User" -| `security_content_ctime(firstTime)` -| `security_content_ctime(lastTime)` -| `o365_privileged_role_assigned_filter`' +search: > + '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add member to role.","Add eligible member to role.") + | eval user = ObjectId, src_user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)), object_name = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.DisplayName")), object_id = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.TemplateId")), signature = Operation, result = ResultStatus, category = mvindex('Target{}.ID',2) + | stats count, min(_time) as firstTime, max(_time) as lastTime by src_user, user, category, result, object_name, object_id, signature + | lookup privileged_azure_ad_roles azuretemplateid as object_id OUTPUT isprvilegedadrole + | search isprvilegedadrole="TRUE" category="User" + | `security_content_ctime(firstTime)` + | `security_content_ctime(lastTime)` + | `o365_privileged_role_assigned_filter`' how_to_implement: You must install the Splunk Microsoft Office 365 Add-on and ingest Office 365 management activity events. known_false_positives: Administrators will legitimately assign the privileged roles users as part of administrative tasks. Microsoft Privileged Identity Management (PIM) may cause false positives / less accurate alerting. references: @@ -25,7 +26,7 @@ references: tags: analytic_story: - Azure Active Directory Persistence - asset_type: Office 365 + asset_type: O365 Tenant confidence: 100 impact: 75 message: A privileged Azure AD role [$object_name$] was assigned to user $user$ by $src_user$ diff --git a/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml b/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml index b02d548a61..b83ca5b157 100644 --- a/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml +++ b/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml @@ -8,14 +8,15 @@ type: TTP description: The following analytic detects potential privilege escalation threats in Azure Active Directory (AD). This detection is important because it identifies instances where privileged roles that hold elevated permissions are assigned to service principals. This prevents unauthorized access or malicious activities, which occur when these non-human entities access Azure resources to exploit them. False positives might occur since administrators can legitimately assign privileged roles to service principals. This detection leverages the O365 Universal Audit Log data source. data_source: - Office 365 Universal Audit Log -search: '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add member to role.","Add eligible member to role.") -| eval user = ObjectId, src_user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)), object_name = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.DisplayName")), object_id = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.TemplateId")), signature = Operation, result = ResultStatus, category = mvindex('Target{}.ID',2) -| stats count, min(_time) as firstTime, max(_time) as lastTime by src_user, user, category, result, object_name, object_id, signature -| lookup privileged_azure_ad_roles azuretemplateid as object_id OUTPUT isprvilegedadrole -| search isprvilegedadrole="TRUE" category!="User" -| `security_content_ctime(firstTime)` -| `security_content_ctime(lastTime)` -| `o365_privileged_role_assigned_to_service_principal_filter`' +search: > + '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add member to role.","Add eligible member to role.") + | eval user = ObjectId, src_user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)), object_name = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.DisplayName")), object_id = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.TemplateId")), signature = Operation, result = ResultStatus, category = mvindex('Target{}.ID',2) + | stats count, min(_time) as firstTime, max(_time) as lastTime by src_user, user, category, result, object_name, object_id, signature + | lookup privileged_azure_ad_roles azuretemplateid as object_id OUTPUT isprvilegedadrole + | search isprvilegedadrole="TRUE" category!="User" + | `security_content_ctime(firstTime)` + | `security_content_ctime(lastTime)` + | `o365_privileged_role_assigned_to_service_principal_filter`' how_to_implement: You must install the Splunk Microsoft Office 365 Add-on and ingest Office 365 management activity events. known_false_positives: Administrators may legitimately assign the privileged roles to Service Principals as part of administrative tasks. Filter as needed. references: @@ -26,7 +27,7 @@ references: tags: analytic_story: - Azure Active Directory Privilege Escalation - asset_type: Office 365 + asset_type: O365 Tenant confidence: 100 impact: 75 message: A privileged Azure AD role [$object_name$] was assigned to the Service Principal $user$ initiated by $src_user$ From a244a954392766c42d9dcb4a06f5ae9ebca6cf19 Mon Sep 17 00:00:00 2001 From: ljstella Date: Thu, 25 Jul 2024 07:16:39 -0500 Subject: [PATCH 22/27] Removing quotes around search as they're no longer needed --- detections/cloud/o365_cross_tenant_access_change.yml | 4 ++-- detections/cloud/o365_external_guest_user_invited.yml | 4 ++-- detections/cloud/o365_external_identity_policy_changed.yml | 4 ++-- detections/cloud/o365_privileged_role_assigned.yml | 4 ++-- .../o365_privileged_role_assigned_to_service_principal.yml | 4 ++-- 5 files changed, 10 insertions(+), 10 deletions(-) diff --git a/detections/cloud/o365_cross_tenant_access_change.yml b/detections/cloud/o365_cross_tenant_access_change.yml index 0fbf284b52..6f6cb2f0e1 100644 --- a/detections/cloud/o365_cross_tenant_access_change.yml +++ b/detections/cloud/o365_cross_tenant_access_change.yml @@ -9,13 +9,13 @@ description: The following analytic identifies when cross-tenant access/synchron data_source: - Office 365 Universal Audit Log search: > - '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add a partner to cross-tenant access setting.","Delete partner specific cross-tenant access setting.") + `o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add a partner to cross-tenant access setting.","Delete partner specific cross-tenant access setting.") | eval user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)) | stats values(Workload) as category, values(ClientIP) as src, values(ModifiedProperties{}.Name) as object_name, values(ModifiedProperties{}.NewValue) as object_attrs, count, min(_time) as firstTime, max(_time) as lastTime by Id,user,Operation | rename Operation as signature, Id as signature_id | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` - | `o365_cross_tenant_access_change_filter`' + | `o365_cross_tenant_access_change_filter` how_to_implement: You must install the Splunk Microsoft Office 365 Add-on and ingest Office 365 management activity events. known_false_positives: Business approved changes by known administrators. references: diff --git a/detections/cloud/o365_external_guest_user_invited.yml b/detections/cloud/o365_external_guest_user_invited.yml index 93c9c8050f..a00581e3d9 100644 --- a/detections/cloud/o365_external_guest_user_invited.yml +++ b/detections/cloud/o365_external_guest_user_invited.yml @@ -9,14 +9,14 @@ description: The following analytic identifies the invitation of an external gue data_source: - Office 365 Universal Audit Log search: > - '`o365_management_activity` Workload=AzureActiveDirectory AND Operation="Add user*" AND ModifiedProperties{}.NewValue="[*Guest*]" AND ModifiedProperties{}.NewValue="[*Invitation*]" + `o365_management_activity` Workload=AzureActiveDirectory AND Operation="Add user*" AND ModifiedProperties{}.NewValue="[*Guest*]" AND ModifiedProperties{}.NewValue="[*Invitation*]" | eval user = (mvindex('ModifiedProperties{}.NewValue',5)), src_user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)) | rex field=user "(?[\\w\\.-]+@[\\w-]+\\.[\\w-]{2,4})" | stats values(user) as user, min(_time) as firstTime, max(_time) as lastTime, count by Operation,Id,src_user | rename Operation as signature, Id as signature_id | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` - | `o365_external_guest_user_invited_filter`' + | `o365_external_guest_user_invited_filter` how_to_implement: You must install the Splunk Microsoft Office 365 Add-on and ingest Office 365 management activity events. known_false_positives: Administrator may legitimately invite external guest users. Filter as needed. references: diff --git a/detections/cloud/o365_external_identity_policy_changed.yml b/detections/cloud/o365_external_identity_policy_changed.yml index 98f1476669..a9dbb3c6f0 100644 --- a/detections/cloud/o365_external_identity_policy_changed.yml +++ b/detections/cloud/o365_external_identity_policy_changed.yml @@ -9,7 +9,7 @@ description: The following analytic identifies when changes are made to the exte data_source: - Office 365 Universal Audit Log search: > - '`o365_management_activity` Workload=AzureActiveDirectory Operation="Update policy." Target{}.ID="B2BManagementPolicy" + `o365_management_activity` Workload=AzureActiveDirectory Operation="Update policy." Target{}.ID="B2BManagementPolicy" | eval object_attrs = mvindex('ModifiedProperties{}.NewValue',0), object_attrs_old = mvindex('ModifiedProperties{}.OldValue',0), object_name = mvindex('Target{}.ID',3), signature=Operation, user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)) | spath input=object_attrs_old output=B2BOld path={} | spath input=B2BOld @@ -23,7 +23,7 @@ search: > | stats values(object_attrs) as object_attrs, values(action) as action, values(result) as result, values(B2BManagementPolicy*) as B2BManagementPolicy*, count, min(_time) as firstTime, max(_time) as lastTime by user,signature,object_name | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` - | `o365_external_identity_policy_changed_filter`' + | `o365_external_identity_policy_changed_filter` how_to_implement: You must install the Splunk Microsoft Office 365 Add-on and ingest Office 365 management activity events. known_false_positives: Business approved changes by known administrators. references: diff --git a/detections/cloud/o365_privileged_role_assigned.yml b/detections/cloud/o365_privileged_role_assigned.yml index bc37779a67..f5f626d370 100644 --- a/detections/cloud/o365_privileged_role_assigned.yml +++ b/detections/cloud/o365_privileged_role_assigned.yml @@ -9,14 +9,14 @@ description: The following analytic identifies the assignment of sensitive and p data_source: - Office 365 Universal Audit Log search: > - '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add member to role.","Add eligible member to role.") + `o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add member to role.","Add eligible member to role.") | eval user = ObjectId, src_user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)), object_name = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.DisplayName")), object_id = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.TemplateId")), signature = Operation, result = ResultStatus, category = mvindex('Target{}.ID',2) | stats count, min(_time) as firstTime, max(_time) as lastTime by src_user, user, category, result, object_name, object_id, signature | lookup privileged_azure_ad_roles azuretemplateid as object_id OUTPUT isprvilegedadrole | search isprvilegedadrole="TRUE" category="User" | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` - | `o365_privileged_role_assigned_filter`' + | `o365_privileged_role_assigned_filter` how_to_implement: You must install the Splunk Microsoft Office 365 Add-on and ingest Office 365 management activity events. known_false_positives: Administrators will legitimately assign the privileged roles users as part of administrative tasks. Microsoft Privileged Identity Management (PIM) may cause false positives / less accurate alerting. references: diff --git a/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml b/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml index b83ca5b157..ebbe154331 100644 --- a/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml +++ b/detections/cloud/o365_privileged_role_assigned_to_service_principal.yml @@ -9,14 +9,14 @@ description: The following analytic detects potential privilege escalation threa data_source: - Office 365 Universal Audit Log search: > - '`o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add member to role.","Add eligible member to role.") + `o365_management_activity` Workload=AzureActiveDirectory Operation IN ("Add member to role.","Add eligible member to role.") | eval user = ObjectId, src_user = case(match(mvindex('Actor{}.ID',-1),"User"),mvindex('Actor{}.ID',0),match(mvindex('Actor{}.ID',-1),"ServicePrincipal"),mvindex('Actor{}.ID',3),true(),mvindex('Actor{}.ID',0)), object_name = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.DisplayName")), object_id = mvindex('ModifiedProperties{}.NewValue', mvfind('ModifiedProperties{}.Name',"Role\.TemplateId")), signature = Operation, result = ResultStatus, category = mvindex('Target{}.ID',2) | stats count, min(_time) as firstTime, max(_time) as lastTime by src_user, user, category, result, object_name, object_id, signature | lookup privileged_azure_ad_roles azuretemplateid as object_id OUTPUT isprvilegedadrole | search isprvilegedadrole="TRUE" category!="User" | `security_content_ctime(firstTime)` | `security_content_ctime(lastTime)` - | `o365_privileged_role_assigned_to_service_principal_filter`' + | `o365_privileged_role_assigned_to_service_principal_filter` how_to_implement: You must install the Splunk Microsoft Office 365 Add-on and ingest Office 365 management activity events. known_false_positives: Administrators may legitimately assign the privileged roles to Service Principals as part of administrative tasks. Filter as needed. references: From 048f73d30779ede8dc28520735385f95103b1b2f Mon Sep 17 00:00:00 2001 From: ljstella Date: Thu, 25 Jul 2024 09:26:26 -0500 Subject: [PATCH 23/27] Datestamped lookup --- lookups/privileged_azure_ad_roles.yml | 4 ++-- ...ure_ad_roles.csv => privileged_azure_ad_roles20240725.csv} | 0 2 files changed, 2 insertions(+), 2 deletions(-) rename lookups/{privileged_azure_ad_roles.csv => privileged_azure_ad_roles20240725.csv} (100%) diff --git a/lookups/privileged_azure_ad_roles.yml b/lookups/privileged_azure_ad_roles.yml index e0e6b6b40b..f7f6e905a4 100644 --- a/lookups/privileged_azure_ad_roles.yml +++ b/lookups/privileged_azure_ad_roles.yml @@ -1,7 +1,7 @@ description: A list of privileged Azure Active Directory roles, includes updates for 2024 and template IDs. -filename: privileged_azure_ad_roles.csv +filename: privileged_azure_ad_roles20240725.csv name: privileged_azure_ad_roles default_match: 'false' match_type: WILDCARD(azureadrole),WILDCARD(azuretemplateid) min_matches: 1 -case_sensitive_match: 'false' \ No newline at end of file +case_sensitive_match: 'false' diff --git a/lookups/privileged_azure_ad_roles.csv b/lookups/privileged_azure_ad_roles20240725.csv similarity index 100% rename from lookups/privileged_azure_ad_roles.csv rename to lookups/privileged_azure_ad_roles20240725.csv From ca30ffcc4015eb031d785fea81f838f352596e5c Mon Sep 17 00:00:00 2001 From: ljstella Date: Wed, 7 Aug 2024 13:20:21 -0500 Subject: [PATCH 24/27] Updating lookup name --- lookups/privileged_azure_ad_roles.yml | 2 +- ..._roles20240725.csv => privileged_azure_ad_roles20240729.csv} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename lookups/{privileged_azure_ad_roles20240725.csv => privileged_azure_ad_roles20240729.csv} (100%) diff --git a/lookups/privileged_azure_ad_roles.yml b/lookups/privileged_azure_ad_roles.yml index f7f6e905a4..5cc6d7aba2 100644 --- a/lookups/privileged_azure_ad_roles.yml +++ b/lookups/privileged_azure_ad_roles.yml @@ -1,5 +1,5 @@ description: A list of privileged Azure Active Directory roles, includes updates for 2024 and template IDs. -filename: privileged_azure_ad_roles20240725.csv +filename: privileged_azure_ad_roles20240729.csv name: privileged_azure_ad_roles default_match: 'false' match_type: WILDCARD(azureadrole),WILDCARD(azuretemplateid) diff --git a/lookups/privileged_azure_ad_roles20240725.csv b/lookups/privileged_azure_ad_roles20240729.csv similarity index 100% rename from lookups/privileged_azure_ad_roles20240725.csv rename to lookups/privileged_azure_ad_roles20240729.csv From f01f6957f9d2af77edd90db33bc69553b214e3ed Mon Sep 17 00:00:00 2001 From: ljstella Date: Wed, 7 Aug 2024 13:29:34 -0500 Subject: [PATCH 25/27] Updating datestamp --- ...ad_roles20240729.csv => privileged_azure_ad_roles20240807.csv} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename lookups/{privileged_azure_ad_roles20240729.csv => privileged_azure_ad_roles20240807.csv} (100%) diff --git a/lookups/privileged_azure_ad_roles20240729.csv b/lookups/privileged_azure_ad_roles20240807.csv similarity index 100% rename from lookups/privileged_azure_ad_roles20240729.csv rename to lookups/privileged_azure_ad_roles20240807.csv From 0091d782106b332f620f9986d9eaf871f22d03f4 Mon Sep 17 00:00:00 2001 From: ljstella Date: Wed, 7 Aug 2024 13:30:26 -0500 Subject: [PATCH 26/27] Account for new name --- lookups/privileged_azure_ad_roles.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lookups/privileged_azure_ad_roles.yml b/lookups/privileged_azure_ad_roles.yml index 5cc6d7aba2..c7d76d7a9e 100644 --- a/lookups/privileged_azure_ad_roles.yml +++ b/lookups/privileged_azure_ad_roles.yml @@ -1,5 +1,5 @@ description: A list of privileged Azure Active Directory roles, includes updates for 2024 and template IDs. -filename: privileged_azure_ad_roles20240729.csv +filename: privileged_azure_ad_roles20240807.csv name: privileged_azure_ad_roles default_match: 'false' match_type: WILDCARD(azureadrole),WILDCARD(azuretemplateid) From 5f30d2989b517096cc7714f0b7b6fa04c2448509 Mon Sep 17 00:00:00 2001 From: ljstella Date: Wed, 7 Aug 2024 13:34:36 -0500 Subject: [PATCH 27/27] Remove old version --- lookups/privileged_azure_ad_roles20240729.csv | 28 ------------------- 1 file changed, 28 deletions(-) delete mode 100644 lookups/privileged_azure_ad_roles20240729.csv diff --git a/lookups/privileged_azure_ad_roles20240729.csv b/lookups/privileged_azure_ad_roles20240729.csv deleted file mode 100644 index b3c897e0e7..0000000000 --- a/lookups/privileged_azure_ad_roles20240729.csv +++ /dev/null @@ -1,28 +0,0 @@ -"azureadrole","isprvilegedadrole","description" -"""Application Administrator""","True","Can create and manage all aspects of app registrations and enterprise apps." -"""Application Developer""","True","Can create application registrations independent of the 'Users can register applications' setting." -"""Authentication Administrator""","True","Can access to view, set and reset authentication method information for any non-admin user." -"""Authentication Extensibility Administrator""","True","Customize sign in and sign up experiences for users by creating and managing custom authentication extensions." -"""B2C IEF Keyset Administrator""","True","Can manage secrets for federation and encryption in the Identity Experience Framework (IEF)." -"""Cloud Application Administrator""","True","Can create and manage all aspects of app registrations and enterprise apps except App Proxy." -"""Cloud Device Administrator""","True","Limited access to manage devices in Microsoft Entra ID." -"""Conditional Access Administrator""","True","Can manage Conditional Access capabilities." -"""Directory Synchronization Accounts""","True","Only used by Microsoft Entra Connect and Microsoft Entra Cloud Sync services." -"""Directory Writers""","True","Can read and write basic directory information. For granting access to applications, not intended for users." -"""Domain Name Administrator""","True","Can manage domain names in cloud and on-premises." -"""External Identity Provider Administrator""","True","Can configure identity providers for use in direct federation." -"""Global Administrator""","True","Can manage all aspects of Microsoft Entra ID and Microsoft services that use Microsoft Entra identities." -"""Global Reader""","True","Can read everything that a Global Administrator can, but not update anything." -"""Helpdesk Administrator""","True","Can reset passwords for non-administrators and Helpdesk Administrators." -"""Hybrid Identity Administrator""","True","Manage Active Directory to Microsoft Entra cloud provisioning, Microsoft Entra Connect, pass-through authentication (PTA), password hash synchronization (PHS), seamless single sign-on (seamless SSO), and federation settings. Does not have access to manage Microsoft Entra Connect Health." -"""Intune Administrator""","True","Can manage all aspects of the Intune product." -"""Lifecycle Workflows Administrator""","True","Create and manage all aspects of workflows and tasks associated with Lifecycle Workflows in Microsoft Entra ID." -"""Partner Tier1 Support""","True","Do not use - not intended for general use." -"""Partner Tier2 Support""","True","Do not use - not intended for general use." -"""Password Administrator""","True","Can reset passwords for non-administrators and Password Administrators." -"""Privileged Authentication Administrator""","True","Can access to view, set and reset authentication method information for any user (admin or non-admin)." -"""Privileged Role Administrator""","True","Can manage role assignments in Microsoft Entra ID, and all aspects of Privileged Identity Management." -"""Security Administrator""","True","Can read security information and reports, and manage configuration in Microsoft Entra ID and Office 365." -"""Security Operator""","True","Creates and manages security events." -"""Security Reader""","True","Can read security information and reports in Microsoft Entra ID and Office 365." -"""User Administrator""","True","Can manage all aspects of users and groups, including resetting passwords for limited admins." \ No newline at end of file