let check_actions = AWSCloudTrail
| where (EventName == "CreateKey" or EventName == "PutKeyPolicy") and isempty(ErrorCode) and isempty(ErrorMessage)
| extend state=parse_json(parse_json(replace_string(tostring(parse_json(RequestParameters)['policy']),'\\"','"')).['Statement'])
| mv-expand state
| extend Action= tostring(parse_json(state.['Action'][0])), Effect=tostring(parse_json(state.['Effect'])),
Principal=tostring(parse_json(state.['Principal']))
| where (Action == "kms:Encrypt" or Action == "kms:*") and (Effect == 'Allow') and (Principal has "*")
| distinct AwsEventId;
AWSCloudTrail
| where (EventName == "CreateKey" or EventName == "PutKeyPolicy") and isempty(ErrorCode) and isempty(ErrorMessage)
| 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]), "")
| join kind=inner (check_actions) on AwsEventId
| extend timestamp = TimeGenerated
| project-away AwsEventId1
description: |
'Detection of KMS keys where action kms:Encrypt is accessible for everyone (also outside of your organization). This is an idicator that your account is compromised and the attacker uses the encryption key to compromise another company.'
triggerThreshold: 0
queryFrequency: 1d
requiredDataConnectors:
- connectorId: AWS
dataTypes:
- AWSCloudTrail
queryPeriod: 1d
tactics:
- Impact
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Amazon Web Services/Analytic Rules/AWS_CreationofEncryptKeysWithoutMFA.yaml
severity: Medium
kind: Scheduled
name: Creating keys with encrypt policy without MFA
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: AccountUPNSuffix
- identifier: CloudAppAccountId
columnName: RecipientAccountId
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SourceIpAddress
status: Available
relevantTechniques:
- T1485
version: 1.0.2
query: |
let check_actions = AWSCloudTrail
| where (EventName == "CreateKey" or EventName == "PutKeyPolicy") and isempty(ErrorCode) and isempty(ErrorMessage)
| extend state=parse_json(parse_json(replace_string(tostring(parse_json(RequestParameters)['policy']),'\\"','"')).['Statement'])
| mv-expand state
| extend Action= tostring(parse_json(state.['Action'][0])), Effect=tostring(parse_json(state.['Effect'])),
Principal=tostring(parse_json(state.['Principal']))
| where (Action == "kms:Encrypt" or Action == "kms:*") and (Effect == 'Allow') and (Principal has "*")
| distinct AwsEventId;
AWSCloudTrail
| where (EventName == "CreateKey" or EventName == "PutKeyPolicy") and isempty(ErrorCode) and isempty(ErrorMessage)
| 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]), "")
| join kind=inner (check_actions) on AwsEventId
| extend timestamp = TimeGenerated
| project-away AwsEventId1
id: 454133a7-5427-4a7c-bdc4-0adfa84dda16
triggerOperator: gt