Techniques
Sample rules
O365 Application Available To Other Tenants
- source: splunk
- technicques:
- T1098.003
- T1098
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.
Detection logic
`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`
O365 Cross-Tenant Access Change
- source: splunk
- technicques:
- T1484.002
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.
Detection logic
`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 External Identity Policy Changed
- source: splunk
- technicques:
- T1136.003
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
.
Detection logic
`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`
O365 SharePoint Allowed Domains Policy Changed
- source: splunk
- technicques:
- T1136.003
Description
The following analytic identifies when the allowed domain settings for O365 SharePoint have been changed. With Azure AD B2B collaboration, users and administrators can invite external users to collaborate with internal users. External guest account invitations may also need access to OneDrive/SharePoint resources. These changed should be monitored by security teams as they could potentially lead to unauthorized access.
Detection logic
`o365_management_activity` Workload=SharePoint Operation=SharingPolicyChanged "ModifiedProperties{}.Name"=AllowDomainList
| eval signature_id = CorrelationId, signature=Operation, src = ClientIP, user = UserId, object_name='ModifiedProperties{}.Name', object_attrs_new = split(replace('ModifiedProperties{}.NewValue',"\.\.\.",""),","), object_attrs_old = split(replace('ModifiedProperties{}.OldValue',"\.\.\.",""),",")
| stats values(object_attrs_new) as object_attrs_new, values(object_attrs_old) as object_attrs_old, values(src) as src, count, min(_time) as firstTime, max(_time) as lastTime by user,signature,signature_id,object_name
| eval diff_add=mvmap(object_attrs_new,if(isnull(mvfind(object_attrs_old,object_attrs_new)),object_attrs_new,null))
| eval diff_remove=mvmap(object_attrs_old,if(isnull(mvfind(object_attrs_new,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")
| `security_content_ctime(firstTime)`
| `security_content_ctime(lastTime)`
| `o365_sharepoint_allowed_domains_policy_changed_filter`