CodeCommitsIssuesPull requestsActionsInsightsSecurity
master

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

Detections/SigninLogs/AzurePortalSigninfromanotherAzureTenant.yaml

52lines · modecode

1id: 87210ca1-49a4-4a7d-bb4a-4988752f978c
2name: Azure Portal Signin from another Azure Tenant
3description: |
4 'This query looks for sign in attempts to the Azure Portal where the user who is signing in from another Azure tenant,
5 and the IP address the login attempt is from is an Azure IP. A threat actor who compromises an Azure tenant may look
6 to pivot to other tenants leveraging cross-tenant delegated access in this manner.'
7severity: Medium
8requiredDataConnectors:
9 - connectorId: AzureActiveDirectory
10 dataTypes:
11 - SigninLogs
12queryFrequency: 1h
13queryPeriod: 1h
14triggerOperator: gt
15triggerThreshold: 0
16tactics:
17 - InitialAccess
18relevantTechniques:
19 - T1199
20query: |
21 // Get details of current Azure Ranges (note this URL updates regularly so will need to be manually updated over time)
22 // You may find the name of the new JSON here: https://www.microsoft.com/download/details.aspx?id=56519
23 // On the downloads page, click the 'details' button, and then replace just the filename in the URL below
24 let azure_ranges = externaldata(changeNumber: string, cloud: string, values: dynamic)
25 ["https://download.microsoft.com/download/7/1/D/71D86715-5596-4529-9B13-DA13A5DE5B63/ServiceTags_Public_20220321.json"]
26 with(format='multijson')
27 | mv-expand values
28 | mv-expand values.properties.addressPrefixes
29 | mv-expand values_properties_addressPrefixes
30 | summarize by tostring(values_properties_addressPrefixes);
31 SigninLogs
32 // Limiting to Azure Portal really reduces false positives and helps focus on potential admin activity
33 | where AppDisplayName =~ "Azure Portal"
34 // Only get logons where the IP address is in an Azure range
35 | evaluate ipv4_lookup(azure_ranges, IPAddress, values_properties_addressPrefixes)
36 // Limit to where the user is external to the tenant
37 | where HomeTenantId != ResourceTenantId
38 // Further limit it to just access to the current tenant (you can drop this if you wanted to look elsewhere as well but it helps reduce FPs)
39 | where ResourceTenantId == AADTenantId
40 | summarize FirstSeen = min(TimeGenerated), LastSeen = max(TimeGenerated), make_set(ResourceDisplayName) by UserPrincipalName, IPAddress, UserAgent, Location, HomeTenantId, ResourceTenantId
41 | extend AccountCustomEntity = UserPrincipalName, IPCustomEntity = IPAddress
42entityMappings:
43 - entityType: Account
44 fieldMappings:
45 - identifier: FullName
46 columnName: AccountCustomEntity
47 - entityType: IP
48 fieldMappings:
49 - identifier: Address
50 columnName: IPCustomEntity
51version: 1.1.0
52kind: Scheduled