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
customDetails:
RecipientAccountId: RecipientAccountId
EventName: EventName
PolicyName: PolicyName
UserIdentityArn: UserIdentityArn
entityMappings:
- entityType: Account
fieldMappings:
- columnName: AccountName
identifier: Name
- columnName: AccountUPNSuffix
identifier: UPNSuffix
- columnName: RecipientAccountId
identifier: CloudAppAccountId
- entityType: IP
fieldMappings:
- columnName: SourceIpAddress
identifier: Address
tactics:
- PrivilegeEscalation
status: Available
queryPeriod: 1d
queryFrequency: 1d
requiredDataConnectors:
- connectorId: AWS
dataTypes:
- AWSCloudTrail
severity: Medium
relevantTechniques:
- T1098.003
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
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.
triggerOperator: gt
alertDetailsOverride:
alertDescriptionFormat: Detected {{EventName}} Event, updating inline IAM escalation policy {{PolicyName}} in account {{RecipientAccountId}}.
alertDisplayNameFormat: AWS IAM privilege escalation policy update by {{AccountName}}
id: e20d35a3-4fec-4c8b-81b1-fc33b41990b0
version: 1.0.2
triggerThreshold: 0
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
{
"$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"
}
]
}