From d2ef1a0e949c4a972941f418a48d95791a5f7b41 Mon Sep 17 00:00:00 2001 From: Shain <45466083+shainw@users.noreply.github.com> Date: Thu, 4 Apr 2024 20:31:04 -0700 Subject: [PATCH 1/2] updating entity mapping --- .../CorrelateIPC_Unfamiliar-Atypical.yaml | 14 ++-- .../Analytic Rules/ADFSDomainTrustMods.yaml | 28 ++++++-- ...ccountCreatedDeletedByNonApprovedUser.yaml | 35 +++++++--- ...ountCreatedandDeletedinShortTimeframe.yaml | 67 +++++++++++++++---- ...nPromoAfterRoleMgmtAppPermissionGrant.yaml | 41 +++++++++++- ...erAppSigninLocationIncrease-detection.yaml | 6 +- ...ionMethodsChangedforPrivilegedAccount.yaml | 40 ++++++----- .../AzureAADPowerShellAnomaly.yaml | 9 ++- .../AzureADRoleManagementPermissionGrant.yaml | 45 +++++++++---- ...urePortalSigninfromanotherAzureTenant.yaml | 4 +- 10 files changed, 220 insertions(+), 69 deletions(-) diff --git a/Solutions/Microsoft Entra ID Protection/Analytic Rules/CorrelateIPC_Unfamiliar-Atypical.yaml b/Solutions/Microsoft Entra ID Protection/Analytic Rules/CorrelateIPC_Unfamiliar-Atypical.yaml index 086e4aecd9..a17600c49b 100644 --- a/Solutions/Microsoft Entra ID Protection/Analytic Rules/CorrelateIPC_Unfamiliar-Atypical.yaml +++ b/Solutions/Microsoft Entra ID Protection/Analytic Rules/CorrelateIPC_Unfamiliar-Atypical.yaml @@ -83,15 +83,21 @@ query: | | join kind=inner Alert_AtypicalTravels on UserAccount | where abs(datetime_diff('minute', Alert_UnfamiliarSignInProps_Time, Alert_AtypicalTravels_Time)) <= TimeDeltaInMinutes | extend TimeDelta = Alert_UnfamiliarSignInProps_Time - Alert_AtypicalTravels_Time - | project UserAccount, Alert_UnfamiliarSignInProps_Name, Alert_UnfamiliarSignInProps_Severity, Alert_UnfamiliarSignInProps_Time, Alert_AtypicalTravels_Name, Alert_AtypicalTravels_Severity, Alert_AtypicalTravels_Time, TimeDelta, CurrentLocation, PreviousLocation, CurrentIPAddress, PreviousIPAddress, UserName + | project UserAccount, AadUserId, Alert_UnfamiliarSignInProps_Name, Alert_UnfamiliarSignInProps_Severity, Alert_UnfamiliarSignInProps_Time, Alert_AtypicalTravels_Name, Alert_AtypicalTravels_Severity, Alert_AtypicalTravels_Time, TimeDelta, CurrentLocation, PreviousLocation, CurrentIPAddress, PreviousIPAddress, UserName | extend UserEmailName = split(UserAccount,'@')[0], UPNSuffix = split(UserAccount,'@')[1] entityMappings: - entityType: Account fieldMappings: - - identifier: UPNSuffix - columnName: UPNSuffix + - identifier: FullName + columnName: UserAccount - identifier: Name columnName: UserEmailName + - identifier: UPNSuffix + columnName: UPNSuffix + - entityType: Account + fieldMappings: + - identifier: AadUserId + columnName: AadUserId - entityType: IP fieldMappings: - identifier: Address @@ -112,5 +118,5 @@ customDetails: PreviousLocation: PreviousLocation CurrentIPAddress: CurrentIPAddress PreviousIPAddress: PreviousIPAddress -version: 1.0.7 +version: 1.0.8 kind: Scheduled \ No newline at end of file diff --git a/Solutions/Microsoft Entra ID/Analytic Rules/ADFSDomainTrustMods.yaml b/Solutions/Microsoft Entra ID/Analytic Rules/ADFSDomainTrustMods.yaml index 5f98cee6fb..589d1dd4b4 100644 --- a/Solutions/Microsoft Entra ID/Analytic Rules/ADFSDomainTrustMods.yaml +++ b/Solutions/Microsoft Entra ID/Analytic Rules/ADFSDomainTrustMods.yaml @@ -52,19 +52,35 @@ query: | | extend UserAgent = tostring(AdditionalDetail.value) ) | extend InitiatingUserOrApp = iff(isnotempty(InitiatedBy.user.userPrincipalName),tostring(InitiatedBy.user.userPrincipalName), tostring(InitiatedBy.app.displayName)) - | extend InitiatingIpAddress = iff(isnotempty(InitiatedBy.user.ipAddress), tostring(InitiatedBy.user.ipAddress), tostring(InitiatedBy.app.ipAddress)) + | extend InitiatingAppName = tostring(InitiatedBy.app.displayName) + | extend InitiatingAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId) + | extend InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName) + | extend InitiatingAadUserId = tostring(InitiatedBy.user.id) + | extend InitiatingIpAddress = tostring(iff(isnotempty(InitiatedBy.user.ipAddress), InitiatedBy.user.ipAddress, InitiatedBy.app.ipAddress)) + | extend InitiatingAccountName = tostring(split(InitiatingUserPrincipalName, "@")[0]), InitiatingAccountUPNSuffix = tostring(split(InitiatingUserPrincipalName, "@")[1]) | project-reorder TimeGenerated, OperationName, InitiatingUserOrApp, AADOperationType, targetDisplayName, Result, InitiatingIpAddress, UserAgent, CorrelationId, TenantId, AADTenantId - | extend timestamp = TimeGenerated, Name = tostring(split(InitiatingUserOrApp,'@',0)[0]), UPNSuffix = tostring(split(InitiatingUserOrApp,'@',1)[0]) entityMappings: - entityType: Account fieldMappings: - identifier: Name - columnName: Name + columnName: InitiatingAppName + - identifier: AadUserId + columnName: InitiatingAppServicePrincipalId + - entityType: Account + fieldMappings: + - identifier: FullName + columnName: InitiatingUserPrincipalName + - identifier: Name + columnName: InitiatingAccountName - identifier: UPNSuffix - columnName: UPNSuffix + columnName: InitiatingAccountUPNSuffix + - entityType: Account + fieldMappings: + - identifier: AadUserId + columnName: InitiatingAadUserId - entityType: IP fieldMappings: - identifier: Address - columnName: InitiatingIpAddress -version: 1.0.1 + columnName: InitiatingIPAddress +version: 1.1.0 kind: Scheduled \ No newline at end of file diff --git a/Solutions/Microsoft Entra ID/Analytic Rules/AccountCreatedDeletedByNonApprovedUser.yaml b/Solutions/Microsoft Entra ID/Analytic Rules/AccountCreatedDeletedByNonApprovedUser.yaml index 7a33e2d6e0..a4ae59e052 100644 --- a/Solutions/Microsoft Entra ID/Analytic Rules/AccountCreatedDeletedByNonApprovedUser.yaml +++ b/Solutions/Microsoft Entra ID/Analytic Rules/AccountCreatedDeletedByNonApprovedUser.yaml @@ -20,27 +20,42 @@ relevantTechniques: tags: - AADSecOpsGuide query: | - // Add non-approved user principal names to the list below to search for their account creation/deletion activity + // Add non-approved user principal names or apps to the list below to search for their account creation/deletion activity // ex: dynamic(["UPN1", "upn123"]) let nonapproved_users = dynamic([]); + let nonapproved_apps = dynamic([]); AuditLogs | where OperationName =~ "Add user" or OperationName =~ "Delete user" | where Result =~ "success" - | extend InitiatingUser = tostring(InitiatedBy.user.userPrincipalName) - | where InitiatingUser has_any (nonapproved_users) - | project-reorder TimeGenerated, ResourceId, OperationName, InitiatingUser, TargetResources - | extend InitiatedUserIpAddress = tostring(InitiatedBy.user.ipAddress) - | extend Name = tostring(split(InitiatingUser,'@',0)[0]), UPNSuffix = tostring(split(InitiatingUser,'@',1)[0]) + | extend InitiatingAppName = tostring(InitiatedBy.app.displayName) + | extend InitiatingAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId) + | extend InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName) + | extend InitiatingAadUserId = tostring(InitiatedBy.user.id) + | extend InitiatingIpAddress = tostring(iff(isnotempty(InitiatedBy.user.ipAddress), InitiatedBy.user.ipAddress, InitiatedBy.app.ipAddress)) + | where InitiatingUserPrincipalName has_any (nonapproved_users) or InitiatingAppName has_any (nonapproved_apps) + | extend InitiatingAccountName = tostring(split(InitiatingUserPrincipalName, "@")[0]), InitiatingAccountUPNSuffix = tostring(split(InitiatingUserPrincipalName, "@")[1]) entityMappings: - entityType: Account fieldMappings: - identifier: Name - columnName: Name + columnName: InitiatingAppName + - identifier: AadUserId + columnName: InitiatingAppServicePrincipalId + - entityType: Account + fieldMappings: + - identifier: FullName + columnName: InitiatingUserPrincipalName + - identifier: Name + columnName: InitiatingAccountName - identifier: UPNSuffix - columnName: UPNSuffix + columnName: InitiatingAccountUPNSuffix + - entityType: Account + fieldMappings: + - identifier: AadUserId + columnName: InitiatingAadUserId - entityType: IP fieldMappings: - identifier: Address - columnName: InitiatedUserIpAddress -version: 1.0.2 + columnName: InitiatingIPAddress +version: 1.1.0 kind: Scheduled \ No newline at end of file diff --git a/Solutions/Microsoft Entra ID/Analytic Rules/AccountCreatedandDeletedinShortTimeframe.yaml b/Solutions/Microsoft Entra ID/Analytic Rules/AccountCreatedandDeletedinShortTimeframe.yaml index 23e043bcb4..ef13370708 100644 --- a/Solutions/Microsoft Entra ID/Analytic Rules/AccountCreatedandDeletedinShortTimeframe.yaml +++ b/Solutions/Microsoft Entra ID/Analytic Rules/AccountCreatedandDeletedinShortTimeframe.yaml @@ -25,15 +25,18 @@ query: | AuditLogs | where TimeGenerated > ago(queryfrequency) | where OperationName =~ "Delete user" - //extend UserPrincipalName = tostring(TargetResources[0].userPrincipalName) | mv-apply TargetResource = TargetResources on ( where TargetResource.type == "User" - | extend UserPrincipalName = extract(@'([a-f0-9]{32})?(.*)', 2, tostring(TargetResource.userPrincipalName)) + | extend TargetUserPrincipalName = extract(@'([a-f0-9]{32})?(.*)', 2, tostring(TargetResource.userPrincipalName)) ) - | extend DeletedByUser = tostring(InitiatedBy.user.userPrincipalName), DeletedByIPAddress = tostring(InitiatedBy.user.ipAddress) - | extend DeletedByApp = tostring(InitiatedBy.app.displayName) - | project Deletion_TimeGenerated = TimeGenerated, UserPrincipalName, DeletedByUser, DeletedByIPAddress, DeletedByApp, Deletion_AdditionalDetails = AdditionalDetails, Deletion_InitiatedBy = InitiatedBy, Deletion_TargetResources = TargetResources + | extend DeletedByApp = tostring(InitiatedBy.app.displayName), + DeletedByAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId), + DeletedByUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName), + DeletedByAadUserId = tostring(InitiatedBy.user.id), + DeletedByIPAddress = tostring(InitiatedBy.user.ipAddress) + | project Deletion_TimeGenerated = TimeGenerated, TargetUserPrincipalName, DeletedByApp, DeletedByAppServicePrincipalId, DeletedByUserPrincipalName, DeletedByAadUserId, DeletedByIPAddress, + Deletion_AdditionalDetails = AdditionalDetails, Deletion_InitiatedBy = InitiatedBy, Deletion_TargetResources = TargetResources | join kind=inner ( AuditLogs | where TimeGenerated > ago(queryperiod) @@ -41,26 +44,62 @@ query: | | mv-apply TargetResource = TargetResources on ( where TargetResource.type == "User" - | extend UserPrincipalName = trim(@'"',tostring(TargetResource.userPrincipalName)) + | extend TargetUserPrincipalName = trim(@'"',tostring(TargetResource.userPrincipalName)) ) | project-rename Creation_TimeGenerated = TimeGenerated - ) on UserPrincipalName + ) on TargetUserPrincipalName | extend TimeDelta = Deletion_TimeGenerated - Creation_TimeGenerated | where TimeDelta between (time(0s) .. queryperiod) - | extend CreatedByUser = tostring(InitiatedBy.user.userPrincipalName), CreatedByIPAddress = tostring(InitiatedBy.user.ipAddress) - | extend CreatedByApp = tostring(InitiatedBy.app.displayName) - | project Creation_TimeGenerated, Deletion_TimeGenerated, TimeDelta, UserPrincipalName, DeletedByUser, DeletedByIPAddress, DeletedByApp, CreatedByUser, CreatedByIPAddress, CreatedByApp, Creation_AdditionalDetails = AdditionalDetails, Creation_InitiatedBy = InitiatedBy, Creation_TargetResources = TargetResources, Deletion_AdditionalDetails, Deletion_InitiatedBy, Deletion_TargetResources - | extend timestamp = Deletion_TimeGenerated, Name = tostring(split(UserPrincipalName,'@',0)[0]), UPNSuffix = tostring(split(UserPrincipalName,'@',1)[0]) + | extend CreatedByApp = tostring(InitiatedBy.app.displayName), + CreatedByAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId), + CreatedByUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName), + CreatedByAadUserId = tostring(InitiatedBy.user.id), + CreatedByIPAddress = tostring(InitiatedBy.user.ipAddress) + | project Creation_TimeGenerated, Deletion_TimeGenerated, TimeDelta, TargetUserPrincipalName, DeletedByApp, DeletedByAppServicePrincipalId, DeletedByUserPrincipalName, DeletedByAadUserId, DeletedByIPAddress, + CreatedByApp, CreatedByAppServicePrincipalId, CreatedByUserPrincipalName, CreatedByAadUserId, CreatedByIPAddress, Creation_AdditionalDetails = AdditionalDetails, Creation_InitiatedBy = InitiatedBy, Creation_TargetResources = TargetResources, Deletion_AdditionalDetails, Deletion_InitiatedBy, Deletion_TargetResources + | extend TargetName = tostring(split(TargetUserPrincipalName,'@',0)[0]), TargetUPNSuffix = tostring(split(TargetUserPrincipalName,'@',1)[0]) + | extend CreatedByName = tostring(split(CreatedByUserPrincipalName,'@',0)[0]), CreatedByUPNSuffix = tostring(split(CreatedByUserPrincipalName,'@',1)[0]) + | extend DeletedByName = tostring(split(DeletedByUserPrincipalName,'@',0)[0]), DeletedByUPNSuffix = tostring(split(DeletedByUserPrincipalName,'@',1)[0]) entityMappings: - entityType: Account fieldMappings: + - identifier: FullName + columnName: TargetUserPrincipalName - identifier: Name - columnName: Name + columnName: TargetName - identifier: UPNSuffix - columnName: UPNSuffix + columnName: TargetUPNSuffix + - entityType: Account + fieldMappings: + - identifier: FullName + columnName: CreatedByUserPrincipalName + - identifier: Name + columnName: CreatedByName + - identifier: UPNSuffix + columnName: CreatedByUPNSuffix + - entityType: Account + fieldMappings: + - identifier: AadUserId + columnName: CreatedByAadUserId + - entityType: Account + fieldMappings: + - identifier: FullName + columnName: DeletedByUserPrincipalName + - identifier: Name + columnName: DeletedByName + - identifier: UPNSuffix + columnName: DeletedByUPNSuffix + - entityType: Account + fieldMappings: + - identifier: AadUserId + columnName: DeletedByAadUserId + - entityType: IP + fieldMappings: + - identifier: Address + columnName: CreatedByIPAddress - entityType: IP fieldMappings: - identifier: Address columnName: DeletedByIPAddress -version: 1.0.3 +version: 1.1.0 kind: Scheduled diff --git a/Solutions/Microsoft Entra ID/Analytic Rules/AdminPromoAfterRoleMgmtAppPermissionGrant.yaml b/Solutions/Microsoft Entra ID/Analytic Rules/AdminPromoAfterRoleMgmtAppPermissionGrant.yaml index 188b6014a6..30cb1807ef 100644 --- a/Solutions/Microsoft Entra ID/Analytic Rules/AdminPromoAfterRoleMgmtAppPermissionGrant.yaml +++ b/Solutions/Microsoft Entra ID/Analytic Rules/AdminPromoAfterRoleMgmtAppPermissionGrant.yaml @@ -80,17 +80,54 @@ query: | | extend TargetName = tostring(split(Target, "@")[0]), TargetUPNSuffix = tostring(split(Target, "@")[1]) - | project PermissionGrant_TimeGenerated, PermissionGrant_OperationName, PermissionGrant_Result, PermissionGrant, AppDisplayName, AppServicePrincipalId, PermissionGrant_InitiatedBy, PermissionGrant_TargetResources, PermissionGrant_AdditionalDetails, PermissionGrant_CorrelationId, RoleAssignment_TimeGenerated, RoleAssignment_OperationName, RoleAssignment_Result, RoleAssignment, TargetType, Target, TargetName, TargetUPNSuffix, TargetId, RoleAssignment_InitiatedBy, RoleAssignment_TargetResources, RoleAssignment_AdditionalDetails, RoleAssignment_CorrelationId + | project PermissionGrant_TimeGenerated, PermissionGrant_OperationName, PermissionGrant_Result, PermissionGrant, AppDisplayName, AppServicePrincipalId, PermissionGrant_InitiatedBy, PermissionGrant_TargetResources, PermissionGrant_AdditionalDetails, PermissionGrant_CorrelationId, + RoleAssignment_TimeGenerated, RoleAssignment_OperationName, RoleAssignment_Result, RoleAssignment, TargetType, Target, TargetName, TargetUPNSuffix, TargetId, RoleAssignment_InitiatedBy, RoleAssignment_TargetResources, RoleAssignment_AdditionalDetails, RoleAssignment_CorrelationId + | extend PermissionGrant_InitiatingUserPrincipalName = tostring(PermissionGrant_InitiatedBy.user.userPrincipalName) + | extend PermissionGrant_InitiatingAadUserId = tostring(PermissionGrant_InitiatedBy.user.id) + | extend PermissionGrant_InitiatingIpAddress = tostring(iff(isnotempty(PermissionGrant_InitiatedBy.user.ipAddress), PermissionGrant_InitiatedBy.user.ipAddress, PermissionGrant_InitiatedBy.app.ipAddress)) + | extend PermissionGrant_InitiatingAccountName = tostring(split(PermissionGrant_InitiatingUserPrincipalName, "@")[0]), PermissionGrant_InitiatingAccountUPNSuffix = tostring(split(PermissionGrant_InitiatingUserPrincipalName, "@")[1]) + | extend RoleAssignment_InitiatingUserPrincipalName = tostring(RoleAssignment_InitiatedBy.user.userPrincipalName) + | extend RoleAssignment_InitiatingAadUserId = tostring(RoleAssignment_InitiatedBy.user.id) + | extend RoleAssignment_InitiatingIpAddress = tostring(iff(isnotempty(RoleAssignment_InitiatedBy.user.ipAddress), RoleAssignment_InitiatedBy.user.ipAddress, RoleAssignment_InitiatedBy.app.ipAddress)) + | extend RoleAssignment_InitiatingAccountName = tostring(split(RoleAssignment_InitiatingUserPrincipalName, "@")[0]), RoleAssignment_InitiatingAccountUPNSuffix = tostring(split(RoleAssignment_InitiatingUserPrincipalName, "@")[1]) entityMappings: - entityType: Account fieldMappings: - identifier: Name columnName: AppDisplayName + - identifier: AadUserId + columnName: AppServicePrincipalId - entityType: Account fieldMappings: + - identifier: FullName + columnName: Target - identifier: Name columnName: TargetName - identifier: UPNSuffix columnName: TargetUPNSuffix -version: 1.0.4 + - entityType: Account + fieldMappings: + - identifier: FullName + columnName: PermissionGrant_InitiatingUserPrincipalName + - identifier: Name + columnName: PermissionGrant_InitiatingAccountName + - identifier: UPNSuffix + columnName: PermissionGrant_InitiatingAccountUPNSuffix + - entityType: Account + fieldMappings: + - identifier: AadUserId + columnName: PermissionGrant_InitiatingAadUserId + - entityType: Account + fieldMappings: + - identifier: FullName + columnName: RoleAssignment_InitiatingUserPrincipalName + - identifier: Name + columnName: RoleAssignment_InitiatingAccountName + - identifier: UPNSuffix + columnName: RoleAssignment_InitiatingAccountUPNSuffix + - entityType: Account + fieldMappings: + - identifier: AadUserId + columnName: RoleAssignment_InitiatingAadUserId +version: 1.1.0 kind: Scheduled diff --git a/Solutions/Microsoft Entra ID/Analytic Rules/AnomalousUserAppSigninLocationIncrease-detection.yaml b/Solutions/Microsoft Entra ID/Analytic Rules/AnomalousUserAppSigninLocationIncrease-detection.yaml index be44f97060..c9739c7cb0 100644 --- a/Solutions/Microsoft Entra ID/Analytic Rules/AnomalousUserAppSigninLocationIncrease-detection.yaml +++ b/Solutions/Microsoft Entra ID/Analytic Rules/AnomalousUserAppSigninLocationIncrease-detection.yaml @@ -44,10 +44,14 @@ query: | entityMappings: - entityType: Account fieldMappings: + - identifier: FullName + columnName: UserPrincipalName - identifier: Name columnName: Name - identifier: UPNSuffix columnName: UPNSuffix + - entityType: Account + fieldMappings: - identifier: AadUserId columnName: UserId eventGroupingSettings: @@ -60,5 +64,5 @@ alertDetailsOverride: This query over Microsoft Entra ID sign-in considers all user sign-ins for each Microsoft Entra ID application and picks out the most anomalous change in location profile for a user within an individual application. This has detected {{UserPrincipalName}} signing into {{AppDisplayName}} from {{CountOfLocations}} different locations. -version: 2.0.2 +version: 2.0.3 kind: Scheduled \ No newline at end of file diff --git a/Solutions/Microsoft Entra ID/Analytic Rules/AuthenticationMethodsChangedforPrivilegedAccount.yaml b/Solutions/Microsoft Entra ID/Analytic Rules/AuthenticationMethodsChangedforPrivilegedAccount.yaml index 024bc7e186..c6e725b201 100644 --- a/Solutions/Microsoft Entra ID/Analytic Rules/AuthenticationMethodsChangedforPrivilegedAccount.yaml +++ b/Solutions/Microsoft Entra ID/Analytic Rules/AuthenticationMethodsChangedforPrivilegedAccount.yaml @@ -36,38 +36,46 @@ query: | | where TimeGenerated > ago(queryfrequency) | where Category =~ "UserManagement" | where ActivityDisplayName in (security_info_actions) - | extend Initiator = tostring(InitiatedBy.user.userPrincipalName) - | extend IP = tostring(InitiatedBy.user.ipAddress) + | extend InitiatingAppName = tostring(InitiatedBy.app.displayName) + | extend InitiatingAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId) + | extend InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName) + | extend InitiatingAadUserId = tostring(InitiatedBy.user.id) + | extend InitiatingIpAddress = tostring(iff(isnotempty(InitiatedBy.user.ipAddress), InitiatedBy.user.ipAddress, InitiatedBy.app.ipAddress)) | mv-apply TargetResource = TargetResources on ( where TargetResource.type =~ "User" - | extend Target = tostring(TargetResource.userPrincipalName) + | extend TargetUserPrincipalName = tostring(TargetResource.userPrincipalName) ) - | where Target in~ (VIPUsers) + | where TargetUserPrincipalName in~ (VIPUsers) // Uncomment the line below if you are experiencing high volumes of Target entities. If this is uncommented, the Target column will not be mapped to an entity. //| summarize Start=min(TimeGenerated), End=max(TimeGenerated), Actions = make_set(ResultReason, MaxSize=8), Targets=make_set(Target, MaxSize=256) by Initiator, IP, Result // Comment out this line below, if line above is used. - | summarize Start=min(TimeGenerated), End=max(TimeGenerated), Actions = make_set(ResultReason, MaxSize=8) by Initiator, IP, Result, Targets = Target - | extend InitiatorName = tostring(split(Initiator,'@',0)[0]), - InitiatorUPNSuffix = tostring(split(Initiator,'@',1)[0]), - TargetName = iff(tostring(Targets) has "[", "", tostring(split(Targets,'@',0)[0])), - TargetUPNSuffix = iff(tostring(Targets) has "[", "", tostring(split(Targets,'@',1)[0])) + | summarize Start=min(TimeGenerated), End=max(TimeGenerated), Actions = make_set(ResultReason, MaxSize=8) by InitiatingAppName, InitiatingAppServicePrincipalId, + InitiatingUserPrincipalName, InitiatingAadUserId, InitiatingIpAddress, TargetUserPrincipalName, Result + | extend InitiatingAccountName = tostring(split(InitiatingUserPrincipalName, "@")[0]), InitiatingAccountUPNSuffix = tostring(split(InitiatingUserPrincipalName, "@")[1]), + TargetName = iff(tostring(TargetUserPrincipalName) has "[", "", tostring(split(TargetUserPrincipalName,'@',0)[0])), TargetUPNSuffix = iff(tostring(TargetUserPrincipalName) has "[", "", tostring(split(TargetUserPrincipalName,'@',1)[0])) entityMappings: - entityType: Account fieldMappings: - identifier: Name - columnName: InitiatorName - - identifier: UPNSuffix - columnName: InitiatorUPNSuffix + columnName: InitiatingAppName + - identifier: AadUserId + columnName: InitiatingAppServicePrincipalId - entityType: Account fieldMappings: + - identifier: FullName + columnName: InitiatingUserPrincipalName - identifier: Name - columnName: TargetName + columnName: InitiatingAccountName - identifier: UPNSuffix - columnName: TargetUPNSuffix + columnName: InitiatingAccountUPNSuffix + - entityType: Account + fieldMappings: + - identifier: AadUserId + columnName: InitiatingAadUserId - entityType: IP fieldMappings: - identifier: Address - columnName: IP -version: 1.0.9 + columnName: InitiatingIPAddress +version: 1.1.0 kind: Scheduled diff --git a/Solutions/Microsoft Entra ID/Analytic Rules/AzureAADPowerShellAnomaly.yaml b/Solutions/Microsoft Entra ID/Analytic Rules/AzureAADPowerShellAnomaly.yaml index ad4063872b..bf3036f5b2 100644 --- a/Solutions/Microsoft Entra ID/Analytic Rules/AzureAADPowerShellAnomaly.yaml +++ b/Solutions/Microsoft Entra ID/Analytic Rules/AzureAADPowerShellAnomaly.yaml @@ -34,8 +34,7 @@ query: | | where Status.errorCode == 0 // Success | project-reorder IPAddress, UserAgent, ResourceDisplayName, UserDisplayName, UserId, UserPrincipalName, Type | order by TimeGenerated desc - // New entity mapping - | extend timestamp = TimeGenerated, Name = tostring(split(UserPrincipalName,'@',0)[0]), UPNSuffix = tostring(split(UserPrincipalName,'@',1)[0]) + | extend Name = tostring(split(UserPrincipalName,'@',0)[0]), UPNSuffix = tostring(split(UserPrincipalName,'@',1)[0]) }; let aadSignin = aadFunc("SigninLogs"); let aadNonInt = aadFunc("AADNonInteractiveUserSignInLogs"); @@ -43,15 +42,19 @@ query: | entityMappings: - entityType: Account fieldMappings: + - identifier: FullName + columnName: UserPrincipalName - identifier: Name columnName: Name - identifier: UPNSuffix columnName: UPNSuffix + - entityType: Account + fieldMappings: - identifier: AadUserId columnName: UserId - entityType: IP fieldMappings: - identifier: Address columnName: IPAddress -version: 1.0.3 +version: 1.0.4 kind: Scheduled diff --git a/Solutions/Microsoft Entra ID/Analytic Rules/AzureADRoleManagementPermissionGrant.yaml b/Solutions/Microsoft Entra ID/Analytic Rules/AzureADRoleManagementPermissionGrant.yaml index c81080fffc..16a1ea1d40 100644 --- a/Solutions/Microsoft Entra ID/Analytic Rules/AzureADRoleManagementPermissionGrant.yaml +++ b/Solutions/Microsoft Entra ID/Analytic Rules/AzureADRoleManagementPermissionGrant.yaml @@ -41,28 +41,49 @@ query: | | mv-apply Property = props on ( where Property.displayName =~ "ServicePrincipal.DisplayName" - | extend AppDisplayName = trim('"',tostring(Property.newValue)) + | extend TargetAppDisplayName = trim('"',tostring(Property.newValue)) ) | mv-apply Property = props on ( where Property.displayName =~ "ServicePrincipal.ObjectID" - | extend AppServicePrincipalId = trim('"',tostring(Property.newValue)) + | extend TargetAppServicePrincipalId = trim('"',tostring(Property.newValue)) ) - | extend - Initiator = iif(isnotempty(InitiatedBy.app), tostring(InitiatedBy.app.displayName), tostring(InitiatedBy.user.userPrincipalName)), - InitiatorId = iif(isnotempty(InitiatedBy.app), tostring(InitiatedBy.app.servicePrincipalId), tostring(InitiatedBy.user.id)) - | project TimeGenerated, OperationName, Result, PermissionGrant, AppDisplayName, AppServicePrincipalId, Initiator, InitiatorId, InitiatedBy, TargetResources, AdditionalDetails, CorrelationId - | extend Name = tostring(split(Initiator,'@',0)[0]), UPNSuffix = tostring(split(Initiator,'@',1)[0]) + | extend InitiatingAppName = tostring(InitiatedBy.app.displayName) + | extend InitiatingAppServicePrincipalId = tostring(InitiatedBy.app.servicePrincipalId) + | extend InitiatingUserPrincipalName = tostring(InitiatedBy.user.userPrincipalName) + | extend InitiatingAadUserId = tostring(InitiatedBy.user.id) + | extend InitiatingIpAddress = tostring(iff(isnotempty(InitiatedBy.user.ipAddress), InitiatedBy.user.ipAddress, InitiatedBy.app.ipAddress)) + | project TimeGenerated, OperationName, Result, PermissionGrant, TargetAppDisplayName, TargetAppServicePrincipalId, InitiatingAppName, InitiatingAppServicePrincipalId, + InitiatingUserPrincipalName, InitiatingAadUserId, InitiatingIpAddress, TargetResources, AdditionalDetails, CorrelationId + | extend InitiatingAccountName = tostring(split(InitiatingUserPrincipalName, "@")[0]), InitiatingAccountUPNSuffix = tostring(split(InitiatingUserPrincipalName, "@")[1]) entityMappings: - entityType: Account fieldMappings: - identifier: Name - columnName: Name - - identifier: UPNSuffix - columnName: UPNSuffix + columnName: TargetAppDisplayName + - identifier: AadUserId + columnName: TargetAppServicePrincipalId + - entityType: Account + fieldMappings: + - identifier: Name + columnName: InitiatingAppName + - identifier: AadUserId + columnName: InitiatingAppServicePrincipalId - entityType: Account fieldMappings: + - identifier: FullName + columnName: InitiatingUserPrincipalName - identifier: Name - columnName: AppDisplayName -version: 1.0.5 + columnName: InitiatingAccountName + - identifier: UPNSuffix + columnName: InitiatingAccountUPNSuffix + - entityType: Account + fieldMappings: + - identifier: AadUserId + columnName: InitiatingAadUserId + - entityType: IP + fieldMappings: + - identifier: Address + columnName: InitiatingIPAddress +version: 1.1.0 kind: Scheduled diff --git a/Solutions/Microsoft Entra ID/Analytic Rules/AzurePortalSigninfromanotherAzureTenant.yaml b/Solutions/Microsoft Entra ID/Analytic Rules/AzurePortalSigninfromanotherAzureTenant.yaml index 84c030639b..386ef4955b 100644 --- a/Solutions/Microsoft Entra ID/Analytic Rules/AzurePortalSigninfromanotherAzureTenant.yaml +++ b/Solutions/Microsoft Entra ID/Analytic Rules/AzurePortalSigninfromanotherAzureTenant.yaml @@ -54,6 +54,8 @@ query: | entityMappings: - entityType: Account fieldMappings: + - identifier: FullName + columnName: UserPrincipalName - identifier: Name columnName: AccountName - identifier: UPNSuffix @@ -71,5 +73,5 @@ alertDetailsOverride: and the IP address the login attempt is from is an Azure IP. A threat actor who compromises an Azure tenant may look to pivot to other tenants leveraging cross-tenant delegated access in this manner. In this instance {{UserPrincipalName}} logged in at {{FirstSeen}} from IP Address {{IPAddress}}. -version: 2.0.1 +version: 2.0.2 kind: Scheduled From 83f9c8d1fd21cb27ecd7f117072aac797ec337be Mon Sep 17 00:00:00 2001 From: Shain <45466083+shainw@users.noreply.github.com> Date: Fri, 5 Apr 2024 05:30:20 -0700 Subject: [PATCH 2/2] fixing one mapping that had 4 identifiers in it, limited to 3 --- .../Analytic Rules/AzurePortalSigninfromanotherAzureTenant.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Solutions/Microsoft Entra ID/Analytic Rules/AzurePortalSigninfromanotherAzureTenant.yaml b/Solutions/Microsoft Entra ID/Analytic Rules/AzurePortalSigninfromanotherAzureTenant.yaml index 386ef4955b..3fdb318448 100644 --- a/Solutions/Microsoft Entra ID/Analytic Rules/AzurePortalSigninfromanotherAzureTenant.yaml +++ b/Solutions/Microsoft Entra ID/Analytic Rules/AzurePortalSigninfromanotherAzureTenant.yaml @@ -60,6 +60,8 @@ entityMappings: columnName: AccountName - identifier: UPNSuffix columnName: UPNSuffix + - entityType: Account + fieldMappings: - identifier: AadUserId columnName: UserId - entityType: IP