Adversaries may be using compromised AWS credentials to attempt access and then pivoting to AzureAD using successful logons from the same IP addresses. SOC teams should proactively hunt for this behavior to detect potential lateral movement and credential reuse across cloud environments.
KQL Query
//Adjust this threshold to fit environment
let signin_threshold = 5;
//Make a list of IPs with failed AWS console logins
let aws_fails = AWSCloudTrail
| where EventName == "ConsoleLogin"
| extend LoginResult = tostring(parse_json(ResponseElements).ConsoleLogin)
| where LoginResult != "Success"
| where SourceIpAddress != "127.0.0.1"
| summarize count() by SourceIpAddress
| where count_ > signin_threshold
| summarize make_set(SourceIpAddress);
//See if any of those IPs have sucessfully logged into Azure AD.
SigninLogs
| where ResultType in ("0", "50125", "50140")
| where IPAddress in (aws_fails)
| extend Reason = "Multiple failed AWS Console logins from IP address"
| extend timestamp = TimeGenerated, AccountName = tostring(split(UserPrincipalName, "@")[0]), AccountUPNSuffix = tostring(split(UserPrincipalName, "@")[1])
id: 910124df-913c-47e3-a7cd-29e1643fa55e
name: Failed AWS Console logons but success logon to AzureAD
description: |
'Identifies a list of IP addresses with a minimum number (default of 5) of failed logon attempts to AWS Console.
Uses that list to identify any successful Microsoft Entra ID logons from these IPs within the same timeframe.'
severity: Medium
requiredDataConnectors:
- connectorId: AzureActiveDirectory
dataTypes:
- SigninLogs
- connectorId: AWS
dataTypes:
- AWSCloudTrail
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
- InitialAccess
- CredentialAccess
relevantTechniques:
- T1078
- T1110
query: |
//Adjust this threshold to fit environment
let signin_threshold = 5;
//Make a list of IPs with failed AWS console logins
let aws_fails = AWSCloudTrail
| where EventName == "ConsoleLogin"
| extend LoginResult = tostring(parse_json(ResponseElements).ConsoleLogin)
| where LoginResult != "Success"
| where SourceIpAddress != "127.0.0.1"
| summarize count() by SourceIpAddress
| where count_ > signin_threshold
| summarize make_set(SourceIpAddress);
//See if any of those IPs have sucessfully logged into Azure AD.
SigninLogs
| where ResultType in ("0", "50125", "50140")
| where IPAddress in (aws_fails)
| extend Reason = "Multiple failed AWS Console logins from IP address"
| extend timestamp = TimeGenerated, AccountName = tostring(split(UserPrincipalName, "@")[0]), AccountUPNSuffix = tostring(split(UserPrincipalName, "@")[1])
entityMappings:
- entityType: Account
fieldMappings:
- identifier: FullName
columnName: UserPrincipalName
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: AccountUPNSuffix
- entityType: Account
fieldMappings:
- identifier: AadUserId
columnName: UserId
- entityType: IP
fieldMappings:
- identifier: Address
columnName: IPAddress
version: 1.2.1
kind: Scheduled
metadata:
source:
kind: Community
author:
name: Microsoft Security Research
support:
tier: Community
categories:
domains: [ "Security - Others", "Identity" ]
| Sentinel Table | Notes |
|---|---|
SigninLogs | Ensure this data connector is enabled |
Scenario: AWS Console Access from a Known Internal IP (e.g., AWS Management Console Access from a Corporate Network)
Description: A legitimate admin accesses the AWS Console from a corporate IP that is also used for successful Azure AD logons.
Filter/Exclusion: Exclude IP addresses that are known internal network ranges (e.g., 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16) or add a custom list of trusted AWS IPs (e.g., via AWS IP ranges list).
Scenario: Scheduled Job or Automation Tool Accessing AWS Console
Description: A scheduled job or automation tool (e.g., AWS CLI, Terraform, or AWS SDK) authenticates to AWS Console and then logs into Azure AD for integration purposes.
Filter/Exclusion: Exclude logons from known automation tools (e.g., aws-cli, terraform, aws-sdk) or use a custom field to identify automation sessions (e.g., User-Agent or Client-IP).
Scenario: User Accessing AWS Console and Then Azure AD for Multi-Cloud Management
Description: A user logs into AWS Console to manage resources and then logs into Azure AD for identity management tasks.
Filter/Exclusion: Exclude logons where the user has both AWS and Azure AD access, or use a custom field to identify multi-cloud management sessions (e.g., User-Agent or Session-Context).
Scenario: Admin Task Involving AWS Console and Azure AD Sync
Description: An admin performs a task that requires both AWS Console access and Azure AD logon, such as configuring SSO or directory synchronization.
Filter/Exclusion: Exclude logons associated with known admin tasks (e