Login to AWS Management Console without MFA
| Id | d25b1998-a592-4bc5-8a3a-92b39eedb1bc |
| Rulename | Login to AWS Management Console without MFA |
| Description | Multi-Factor Authentication (MFA) helps you to prevent credential compromise. This alert identifies logins to the AWS Management Console without MFA. You can limit this detection to trigger for adminsitrative accounts if you do not have MFA enabled on all accounts. This is done by looking at the eventName ConsoleLogin and if the AdditionalEventData field indicates MFA was NOT used and the ResponseElements field indicates NOT a Failure. Thereby indicating that a non-MFA login was successful. |
| Severity | Low |
| Tactics | DefenseEvasion PrivilegeEscalation Persistence InitialAccess |
| Techniques | T1078 |
| Required data connectors | AWS AWSS3 |
| Kind | Scheduled |
| Query frequency | 1d |
| Query period | 1d |
| Trigger threshold | 0 |
| Trigger operator | gt |
| Source Uri | https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Amazon Web Services/Analytic Rules/AWS_ConsoleLogonWithoutMFA.yaml |
| Version | 1.0.5 |
| Arm template | d25b1998-a592-4bc5-8a3a-92b39eedb1bc.json |
AWSCloudTrail
| where EventName =~ "ConsoleLogin"
| extend MFAUsed = tostring(parse_json(AdditionalEventData).MFAUsed), LoginResult = tostring(parse_json(ResponseElements).ConsoleLogin), indexId = indexof(tostring(UserIdentityPrincipalid),":")
| where MFAUsed !~ "Yes" and LoginResult !~ "Failure"
| where SessionIssuerUserName !contains "AWSReservedSSO"
| 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 StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated) by EventName, EventTypeName, LoginResult, MFAUsed, RecipientAccountId, AccountName, AccountUPNSuffix, UserIdentityAccountId, UserIdentityPrincipalid, UserAgent,
UserIdentityUserName, SessionMfaAuthenticated, SourceIpAddress, AWSRegion, indexId
| extend timestamp = StartTimeUtc
id: d25b1998-a592-4bc5-8a3a-92b39eedb1bc
triggerThreshold: 0
description: |
'Multi-Factor Authentication (MFA) helps you to prevent credential compromise. This alert identifies logins to the AWS Management Console without MFA.
You can limit this detection to trigger for adminsitrative accounts if you do not have MFA enabled on all accounts.
This is done by looking at the eventName ConsoleLogin and if the AdditionalEventData field indicates MFA was NOT used and the ResponseElements field indicates NOT a Failure. Thereby indicating that a non-MFA login was successful.'
requiredDataConnectors:
- connectorId: AWS
dataTypes:
- AWSCloudTrail
- connectorId: AWSS3
dataTypes:
- AWSCloudTrail
queryPeriod: 1d
version: 1.0.5
severity: Low
tactics:
- DefenseEvasion
- PrivilegeEscalation
- Persistence
- InitialAccess
queryFrequency: 1d
kind: Scheduled
entityMappings:
- entityType: Account
fieldMappings:
- columnName: AccountName
identifier: Name
- columnName: AccountUPNSuffix
identifier: UPNSuffix
- columnName: RecipientAccountId
identifier: CloudAppAccountId
- entityType: IP
fieldMappings:
- columnName: SourceIpAddress
identifier: Address
name: Login to AWS Management Console without MFA
relevantTechniques:
- T1078
triggerOperator: gt
query: |
AWSCloudTrail
| where EventName =~ "ConsoleLogin"
| extend MFAUsed = tostring(parse_json(AdditionalEventData).MFAUsed), LoginResult = tostring(parse_json(ResponseElements).ConsoleLogin), indexId = indexof(tostring(UserIdentityPrincipalid),":")
| where MFAUsed !~ "Yes" and LoginResult !~ "Failure"
| where SessionIssuerUserName !contains "AWSReservedSSO"
| 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 StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated) by EventName, EventTypeName, LoginResult, MFAUsed, RecipientAccountId, AccountName, AccountUPNSuffix, UserIdentityAccountId, UserIdentityPrincipalid, UserAgent,
UserIdentityUserName, SessionMfaAuthenticated, SourceIpAddress, AWSRegion, indexId
| extend timestamp = StartTimeUtc
status: Available
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Amazon Web Services/Analytic Rules/AWS_ConsoleLogonWithoutMFA.yaml