AWSCloudTrail - Privilege escalation via CRUD DynamoDB policy
| Id | b9be2aa6-911d-4131-8658-d2a537ed49f4 |
| Rulename | AWSCloudTrail - Privilege escalation via CRUD DynamoDB policy |
| Description | Detects creation of inline IAM policies that grant broad DynamoDB create, read, update, and delete permissions. Attackers may use this access expansion to manipulate data stores and escalate influence across cloud workloads. |
| Severity | Medium |
| Tactics | PrivilegeEscalation |
| Techniques | T1098.003 |
| Required data connectors | AWS |
| 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_PrivilegeEscalationviaCRUDDynamoDB.yaml |
| Version | 1.0.2 |
| Arm template | b9be2aa6-911d-4131-8658-d2a537ed49f4.json |
AWSCloudTrail
| where EventName in ("PutUserPolicy","PutRolePolicy","PutGroupPolicy") and isempty(ErrorCode) and isempty(ErrorMessage)
| extend PolicyName = tostring(parse_json(RequestParameters).policyName)
| extend Statement = parse_json(tostring((parse_json(RequestParameters).policyDocument))).Statement
| mvexpand Statement
| extend Action = parse_json(Statement).Action , Effect = tostring(parse_json(Statement).Effect), Resource = tostring(parse_json(Statement).Resource), Condition = tostring(parse_json(Statement).Condition)
| extend Action = tostring(Action)
| where Effect =~ "Allow" and ((Action contains "dynamodb:Create" or Action contains "dynamodb:Put") and (Action contains "dynamodb:Describe" or Action contains "dynamodb:Get" or Action contains "dynamodb:Scan") and Action contains "dynamodb:Update" and Action contains "dynamodb:Delete") and Resource == "*" and Condition == ""
| 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]), "")
| distinct TimeGenerated, EventName, PolicyName, SourceIpAddress, RecipientAccountId, AccountName, AccountUPNSuffix, UserIdentityArn, UserIdentityUserName
entityMappings:
- fieldMappings:
- columnName: AccountName
identifier: Name
- columnName: AccountUPNSuffix
identifier: UPNSuffix
- columnName: RecipientAccountId
identifier: CloudAppAccountId
entityType: Account
- fieldMappings:
- columnName: SourceIpAddress
identifier: Address
entityType: IP
triggerOperator: gt
tactics:
- PrivilegeEscalation
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Amazon Web Services/Analytic Rules/AWS_PrivilegeEscalationviaCRUDDynamoDB.yaml
alertDetailsOverride:
alertDescriptionFormat: Detected {{EventName}} Event, updating inline DynamoDB escalation policy {{PolicyName}} in account {{RecipientAccountId}}.
alertDisplayNameFormat: AWS DynamoDB privilege escalation policy update by {{AccountName}}
version: 1.0.2
query: |
AWSCloudTrail
| where EventName in ("PutUserPolicy","PutRolePolicy","PutGroupPolicy") and isempty(ErrorCode) and isempty(ErrorMessage)
| extend PolicyName = tostring(parse_json(RequestParameters).policyName)
| extend Statement = parse_json(tostring((parse_json(RequestParameters).policyDocument))).Statement
| mvexpand Statement
| extend Action = parse_json(Statement).Action , Effect = tostring(parse_json(Statement).Effect), Resource = tostring(parse_json(Statement).Resource), Condition = tostring(parse_json(Statement).Condition)
| extend Action = tostring(Action)
| where Effect =~ "Allow" and ((Action contains "dynamodb:Create" or Action contains "dynamodb:Put") and (Action contains "dynamodb:Describe" or Action contains "dynamodb:Get" or Action contains "dynamodb:Scan") and Action contains "dynamodb:Update" and Action contains "dynamodb:Delete") and Resource == "*" and Condition == ""
| 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]), "")
| distinct TimeGenerated, EventName, PolicyName, SourceIpAddress, RecipientAccountId, AccountName, AccountUPNSuffix, UserIdentityArn, UserIdentityUserName
triggerThreshold: 0
relevantTechniques:
- T1098.003
queryPeriod: 1d
status: Available
severity: Medium
kind: Scheduled
customDetails:
RecipientAccountId: RecipientAccountId
EventName: EventName
UserIdentityArn: UserIdentityArn
PolicyName: PolicyName
name: AWSCloudTrail - Privilege escalation via CRUD DynamoDB policy
queryFrequency: 1d
id: b9be2aa6-911d-4131-8658-d2a537ed49f4
description: |
Detects creation of inline IAM policies that grant broad DynamoDB create, read, update, and delete permissions.
Attackers may use this access expansion to manipulate data stores and escalate influence across cloud workloads.
requiredDataConnectors:
- dataTypes:
- AWSCloudTrail
connectorId: AWS