Analytic rule catalog
AWSCloudTrail - Privilege escalation via CRUD IAM policy
Back
| Id | e20d35a3-4fec-4c8b-81b1-fc33b41990b0 |
| Rulename | AWSCloudTrail - Privilege escalation via CRUD IAM policy |
| Description | Detects creation of inline IAM policies that grant broad IAM create, read, update, and delete capabilities. This behavior can establish or expand privileged control paths in the account and should be reviewed as potential privilege escalation. |
| 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%20Web%20Services/Analytic%20Rules/AWS_PrivilegeEscalationViaCRUDIAMPolicy.yaml |
| Version | 1.0.2 |
| Arm template | e20d35a3-4fec-4c8b-81b1-fc33b41990b0.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 "iam:Create" and (Action contains "iam:Get" or Action contains "iam:List") and Action contains "iam:Update" and Action contains "iam: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:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: AccountName
- identifier: UPNSuffix
columnName: AccountUPNSuffix
- identifier: CloudAppAccountId
columnName: RecipientAccountId
- entityType: IP
fieldMappings:
- identifier: Address
columnName: SourceIpAddress
name: AWSCloudTrail - Privilege escalation via CRUD IAM policy
kind: Scheduled
OriginalUri: https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Amazon%20Web%20Services/Analytic%20Rules/AWS_PrivilegeEscalationViaCRUDIAMPolicy.yaml
triggerOperator: gt
status: Available
queryPeriod: 1d
requiredDataConnectors:
- connectorId: AWS
dataTypes:
- AWSCloudTrail
tactics:
- PrivilegeEscalation
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 "iam:Create" and (Action contains "iam:Get" or Action contains "iam:List") and Action contains "iam:Update" and Action contains "iam: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
description: |
Detects creation of inline IAM policies that grant broad IAM create, read, update, and delete capabilities.
This behavior can establish or expand privileged control paths in the account and should be reviewed as potential
privilege escalation.
severity: Medium
id: e20d35a3-4fec-4c8b-81b1-fc33b41990b0
customDetails:
UserIdentityArn: UserIdentityArn
EventName: EventName
PolicyName: PolicyName
RecipientAccountId: RecipientAccountId
triggerThreshold: 0
queryFrequency: 1d
alertDetailsOverride:
alertDescriptionFormat: Detected {{EventName}} Event, updating inline IAM escalation policy {{PolicyName}} in account {{RecipientAccountId}}.
alertDisplayNameFormat: AWS IAM privilege escalation policy update by {{AccountName}}
version: 1.0.2
relevantTechniques:
- T1098.003
{
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
"contentVersion": "1.0.0.0",
"parameters": {
"workspace": {
"type": "String"
}
},
"resources": [
{
"apiVersion": "2024-01-01-preview",
"id": "[concat(resourceId('Microsoft.OperationalInsights/workspaces/providers', parameters('workspace'), 'Microsoft.SecurityInsights'),'/alertRules/e20d35a3-4fec-4c8b-81b1-fc33b41990b0')]",
"kind": "Scheduled",
"name": "[concat(parameters('workspace'),'/Microsoft.SecurityInsights/e20d35a3-4fec-4c8b-81b1-fc33b41990b0')]",
"properties": {
"alertDetailsOverride": {
"alertDescriptionFormat": "Detected {{EventName}} Event, updating inline IAM escalation policy {{PolicyName}} in account {{RecipientAccountId}}.",
"alertDisplayNameFormat": "AWS IAM privilege escalation policy update by {{AccountName}}"
},
"alertRuleTemplateName": "e20d35a3-4fec-4c8b-81b1-fc33b41990b0",
"customDetails": {
"EventName": "EventName",
"PolicyName": "PolicyName",
"RecipientAccountId": "RecipientAccountId",
"UserIdentityArn": "UserIdentityArn"
},
"description": "Detects creation of inline IAM policies that grant broad IAM create, read, update, and delete capabilities.\nThis behavior can establish or expand privileged control paths in the account and should be reviewed as potential\nprivilege escalation.\n",
"displayName": "AWSCloudTrail - Privilege escalation via CRUD IAM policy",
"enabled": true,
"entityMappings": [
{
"entityType": "Account",
"fieldMappings": [
{
"columnName": "AccountName",
"identifier": "Name"
},
{
"columnName": "AccountUPNSuffix",
"identifier": "UPNSuffix"
},
{
"columnName": "RecipientAccountId",
"identifier": "CloudAppAccountId"
}
]
},
{
"entityType": "IP",
"fieldMappings": [
{
"columnName": "SourceIpAddress",
"identifier": "Address"
}
]
}
],
"OriginalUri": "https://github.com/Azure/Azure-Sentinel/blob/master/Solutions/Amazon%20Web%20Services/Analytic%20Rules/AWS_PrivilegeEscalationViaCRUDIAMPolicy.yaml",
"query": "AWSCloudTrail\n | where EventName in (\"PutUserPolicy\",\"PutRolePolicy\",\"PutGroupPolicy\") and isempty(ErrorCode) and isempty(ErrorMessage)\n | extend PolicyName = tostring(parse_json(RequestParameters).policyName)\n | extend Statement = parse_json(tostring((parse_json(RequestParameters).policyDocument))).Statement\n | mvexpand Statement\n | extend Action = parse_json(Statement).Action , Effect = tostring(parse_json(Statement).Effect), Resource = tostring(parse_json(Statement).Resource), Condition = tostring(parse_json(Statement).Condition)\n | extend Action = tostring(Action)\n | where Effect =~ \"Allow\" and (Action contains \"iam:Create\" and (Action contains \"iam:Get\" or Action contains \"iam:List\") and Action contains \"iam:Update\" and Action contains \"iam:Delete\") and Resource == \"*\" and Condition == \"\"\n | extend UserIdentityArn = iif(isempty(UserIdentityArn), tostring(parse_json(Resources)[0].ARN), UserIdentityArn)\n | extend UserName = tostring(split(UserIdentityArn, '/')[-1])\n | extend AccountName = case( UserIdentityPrincipalid == \"Anonymous\", \"Anonymous\", isempty(UserIdentityUserName), UserName, UserIdentityUserName)\n | extend AccountName = iif(AccountName contains \"@\", tostring(split(AccountName, '@', 0)[0]), AccountName),\n AccountUPNSuffix = iif(AccountName contains \"@\", tostring(split(AccountName, '@', 1)[0]), \"\")\n | distinct TimeGenerated, EventName, PolicyName, SourceIpAddress, RecipientAccountId, AccountName, AccountUPNSuffix, UserIdentityArn, UserIdentityUserName\n",
"queryFrequency": "P1D",
"queryPeriod": "P1D",
"severity": "Medium",
"status": "Available",
"subTechniques": [
"T1098.003"
],
"suppressionDuration": "PT1H",
"suppressionEnabled": false,
"tactics": [
"PrivilegeEscalation"
],
"techniques": [
"T1098"
],
"templateVersion": "1.0.2",
"triggerOperator": "GreaterThan",
"triggerThreshold": 0
},
"type": "Microsoft.OperationalInsights/workspaces/providers/alertRules"
}
]
}