Microsoft Sentinel Analytic Rules
cloudbrothers.infoAzure Sentinel RepoToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

Failed AzureAD logons but success logon to AWS Console

Back
Id643c2025-9604-47c5-833f-7b4b9378a1f5
RulenameFailed AzureAD logons but success logon to AWS Console
DescriptionIdentifies a list of IP addresses with a minimum number (defualt of 5) of failed logon attempts to Microsoft Entra ID.

Uses that list to identify any successful AWS Console logons from these IPs within the same timeframe.
SeverityMedium
TacticsInitialAccess
CredentialAccess
TechniquesT1078
T1110
Required data connectorsAWS
AzureActiveDirectory
KindScheduled
Query frequency1d
Query period1d
Trigger threshold0
Trigger operatorgt
Source Urihttps://github.com/Azure/Azure-Sentinel/blob/master/Detections/MultipleDataSources/AADAWSConsoleCorrelation.yaml
Version1.0.5
Arm template643c2025-9604-47c5-833f-7b4b9378a1f5.json
Deploy To Azure
//Adjust this threshold to fit your environment
let signin_threshold = 5;
//Make a list of IPs with AAD signin failures above our threshold
let aadFunc = (tableName:string){
let Suspicious_signins =
table(tableName)
| where ResultType !in ("0", "50125", "50140")
| where IPAddress !in ("127.0.0.1", "::1")
| summarize count() by IPAddress
| where count_ >  signin_threshold
| summarize make_set(IPAddress);
Suspicious_signins
};
let aadSignin = aadFunc("SigninLogs");
let aadNonInt = aadFunc("AADNonInteractiveUserSignInLogs");
let Suspicious_signins =
union isfuzzy=true aadSignin, aadNonInt
| summarize make_set(set_IPAddress);
//See if any of those IPs have sucessfully logged into the AWS console
AWSCloudTrail
| where EventName =~ "ConsoleLogin"
| extend LoginResult = tostring(parse_json(ResponseElements).ConsoleLogin)
| where LoginResult =~ "Success"
| where SourceIpAddress in (Suspicious_signins)
| extend Reason = "Multiple failed AAD logins from IP address"
| extend MFAUsed = tostring(parse_json(AdditionalEventData).MFAUsed)
| extend UserIdentityArn = iif(isempty(UserIdentityArn), tostring(parse_json(Resources)[0].ARN), UserIdentityArn)
| extend UserName = tostring(split(UserIdentityArn, '/')[-1])
| extend AccountName = case( UserIdentityPrincipalid == "Anonymous", "Anonymous", isempty(UserIdentityUserName), UserName, UserIdentityUserName)
| extend AccountName = iif(AccountName contains "@", tostring(split(AccountName, '@', 0)[0]), AccountName),
  AccountUPNSuffix = iif(AccountName contains "@", tostring(split(AccountName, '@', 1)[0]), "")
| summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by Reason, LoginResult, EventTypeName, UserIdentityType, RecipientAccountId, AccountName, AccountUPNSuffix, AWSRegion, SourceIpAddress, UserAgent, MFAUsed
| extend timestamp = StartTime
description: |
  'Identifies a list of IP addresses with a minimum number (defualt of 5) of failed logon attempts to Microsoft Entra ID.
  Uses that list to identify any successful AWS Console logons from these IPs within the same timeframe.'  
kind: Scheduled
tactics:
- InitialAccess
- CredentialAccess
requiredDataConnectors:
- connectorId: AzureActiveDirectory
  dataTypes:
  - SigninLogs
- connectorId: AzureActiveDirectory
  dataTypes:
  - AADNonInteractiveUserSignInLogs
- connectorId: AWS
  dataTypes:
  - AWSCloudTrail
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Detections/MultipleDataSources/AADAWSConsoleCorrelation.yaml
severity: Medium
name: Failed AzureAD logons but success logon to AWS Console
metadata:
  support:
    tier: Community
  author:
    name: Microsoft Security Research
  categories:
    domains:
    - Security - Others
    - Identity
  source:
    kind: Community
triggerThreshold: 0
queryPeriod: 1d
query: |
  //Adjust this threshold to fit your environment
  let signin_threshold = 5;
  //Make a list of IPs with AAD signin failures above our threshold
  let aadFunc = (tableName:string){
  let Suspicious_signins =
  table(tableName)
  | where ResultType !in ("0", "50125", "50140")
  | where IPAddress !in ("127.0.0.1", "::1")
  | summarize count() by IPAddress
  | where count_ >  signin_threshold
  | summarize make_set(IPAddress);
  Suspicious_signins
  };
  let aadSignin = aadFunc("SigninLogs");
  let aadNonInt = aadFunc("AADNonInteractiveUserSignInLogs");
  let Suspicious_signins =
  union isfuzzy=true aadSignin, aadNonInt
  | summarize make_set(set_IPAddress);
  //See if any of those IPs have sucessfully logged into the AWS console
  AWSCloudTrail
  | where EventName =~ "ConsoleLogin"
  | extend LoginResult = tostring(parse_json(ResponseElements).ConsoleLogin)
  | where LoginResult =~ "Success"
  | where SourceIpAddress in (Suspicious_signins)
  | extend Reason = "Multiple failed AAD logins from IP address"
  | extend MFAUsed = tostring(parse_json(AdditionalEventData).MFAUsed)
  | extend UserIdentityArn = iif(isempty(UserIdentityArn), tostring(parse_json(Resources)[0].ARN), UserIdentityArn)
  | extend UserName = tostring(split(UserIdentityArn, '/')[-1])
  | extend AccountName = case( UserIdentityPrincipalid == "Anonymous", "Anonymous", isempty(UserIdentityUserName), UserName, UserIdentityUserName)
  | extend AccountName = iif(AccountName contains "@", tostring(split(AccountName, '@', 0)[0]), AccountName),
    AccountUPNSuffix = iif(AccountName contains "@", tostring(split(AccountName, '@', 1)[0]), "")
  | summarize StartTime = min(TimeGenerated), EndTime = max(TimeGenerated) by Reason, LoginResult, EventTypeName, UserIdentityType, RecipientAccountId, AccountName, AccountUPNSuffix, AWSRegion, SourceIpAddress, UserAgent, MFAUsed
  | extend timestamp = StartTime  
relevantTechniques:
- T1078
- T1110
id: 643c2025-9604-47c5-833f-7b4b9378a1f5
queryFrequency: 1d
entityMappings:
- entityType: Account
  fieldMappings:
  - columnName: AccountName
    identifier: Name
  - columnName: AccountUPNSuffix
    identifier: UPNSuffix
  - columnName: RecipientAccountId
    identifier: CloudAppAccountId
- entityType: IP
  fieldMappings:
  - columnName: SourceIpAddress
    identifier: Address
triggerOperator: gt
version: 1.0.5