terraform.lang.security.iam.no-iam-priv-esc-roles.no-iam-priv-esc-roles
semgrep
Author
unknown
Download Count*
License
Ensure that groups of actions that include iam:PassRole and could result in privilege escalation are not all allowed for the same user. These actions could result in an attacker gaining full admin access of an AWS account. Try not to use these actions in conjuction.
Run Locally
Run in CI
Defintion
rules:
- id: no-iam-priv-esc-roles
patterns:
- pattern-either:
- patterns:
- pattern-inside: |
resource $TYPE "..." {
...
policy = jsonencode({
...
Statement = [
...
]
...
})
...
}
- pattern-not-inside: |
resource $TYPE "..." {
...
policy = jsonencode({
...
Statement = [
...,
{... Effect = "Deny" ...},
...
]
...
})
...
}
- pattern: |
Action = $ACTION
- metavariable-pattern:
metavariable: $TYPE
pattern-either:
- pattern: |
"aws_iam_role_policy"
- pattern: |
"aws_iam_policy"
- pattern: |
"aws_iam_user_policy"
- pattern: |
"aws_iam_group_policy"
- patterns:
- pattern-inside: |
data aws_iam_policy_document "..." {
...
statement {
...
}
...
}
- pattern-not-inside: |
data aws_iam_policy_document "..." {
...
statement {
...
effect = "Deny"
...
}
...
}
- pattern: |
actions = $ACTION
- metavariable-pattern:
metavariable: $ACTION
pattern-either:
- patterns:
- pattern: |
[..., "sts:AssumeRole", ...]
- pattern: |
[..., "iam:UpdateAssumeRolePolicy", ...]
- patterns:
- pattern: |
[..., "iam:PassRole", ...]
- pattern: |
[..., "lambda:CreateFunction", ...]
- pattern: |
[..., "lambda:InvokeFunction", ...]
- patterns:
- pattern: |
[..., "iam:PassRole", ...]
- pattern: |
[..., "lambda:CreateFunction", ...]
- pattern: |
[..., "lambda:CreateEventSourceMapping", ...]
- pattern: |
"lambda:UpdateFunctionCode"
- patterns:
- pattern: |
[..., "iam:PassRole", ...]
- pattern: |
[..., "glue:CreateDevEndpoint", ...]
- patterns:
- pattern: |
[..., "iam:PassRole", ...]
- pattern: |
[..., "cloudformation:CreateStack", ...]
- patterns:
- pattern: |
[..., "iam:PassRole", ...]
- pattern: |
[..., "datapipeline:CreatePipeline", ...]
- pattern: |
[..., "datapipeline:PutPipelineDefinition", ...]
message: Ensure that groups of actions that include iam:PassRole and could
result in privilege escalation are not all allowed for the same user.
These actions could result in an attacker gaining full admin access of an
AWS account. Try not to use these actions in conjuction.
metadata:
references:
- https://cloudsplaining.readthedocs.io/en/latest/glossary/privilege-escalation/
- https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/
category: security
cwe:
- "CWE-269: Improper Privilege Management"
license: Commons Clause License Condition v1.0[LGPL-2.1-only]
technology:
- terraform
- aws
owasp:
- A04:2021 - Insecure Design
subcategory:
- audit
likelihood: LOW
impact: LOW
confidence: LOW
vulnerability_class:
- Improper Authorization
languages:
- hcl
severity: WARNING
Examples
no-iam-priv-esc-roles.tf
resource "aws_iam_user_policy" "lb_ro" {
name = "test"
user = aws_iam_user.lb.name
# Terraform's "jsonencode" function converts a
# Terraform expression result to valid JSON syntax.
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
# ok: no-iam-priv-esc-roles
Action = [
"std:AssumeRole",
]
Effect = "Allow"
Resource = ["arn:aws:iam::ACCOUNT-ID-WITHOUT-HYPHENS:user/${aws.username}"]
},
]
})
}
resource "aws_iam_policy" "lb_ro" {
name = "test"
user = aws_iam_user.lb.name
# Terraform's "jsonencode" function converts a
# Terraform expression result to valid JSON syntax.
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
# ok: no-iam-priv-esc-roles
Action = [
"datapipeline:CreatePipeline",
"datapipeline:PutPipelineDefinition"
]
Effect = "Allow"
Resource = ["*"]
},
]
})
}
data aws_iam_policy_document "policy" {
statement {
# ok: no-iam-priv-esc-roles
actions = ["glue:CreateDevEndpoint"]
principals {
type = "AWS"
identifiers = ["*"]
}
resources = ["*"]
}
}
resource "aws_iam_user_policy" "policy" {
name = "test_policy"
path = "/"
description = "My test policy"
# Terraform's "jsonencode" function converts a
# Terraform expression result to valid JSON syntax.
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
# ruleid: no-iam-priv-esc-roles
Action = ["lambda:CreateFunction", "lambda:CreateEventSourceMapping", "iam:PassRole"]
Effect = "Allow"
Resource = "*"
},
]
})
}
resource "aws_iam_user_policy" "policy" {
name = "test_policy"
path = "/"
description = "My test policy"
# Terraform's "jsonencode" function converts a
# Terraform expression result to valid JSON syntax.
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
# ruleid: no-iam-priv-esc-roles
Action = ["ec2:Describe", "sts:AssumeRole", "ec2:Test", "iam:UpdateAssumeRolePolicy"]
Effect = "Allow"
Resource = "arn:aws:iam::account:user/*"
},
]
})
}
resource "aws_iam_user_policy" "policy" {
name = "test_policy"
path = "/"
description = "My test policy"
# Terraform's "jsonencode" function converts a
# Terraform expression result to valid JSON syntax.
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
# ruleid: no-iam-priv-esc-roles
Action = "lambda:UpdateFunctionCode"
Effect = "Allow"
Resource = "arn:aws:iam::account:user/*"
},
]
})
}
resource "aws_iam_user_policy" "policy" {
name = "test_policy"
path = "/"
description = "My test policy"
# Terraform's "jsonencode" function converts a
# Terraform expression result to valid JSON syntax.
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
# ruleid: no-iam-priv-esc-roles
Action = ["iam:UpdateAssumeRolePolicy", "sts:AssumeRole"]
Effect = "Allow"
Resource = "arn:aws:iam::account:user/*"
},
]
})
}
resource "aws_iam_policy" "policy" {
name = "test_policy"
path = "/"
description = "My test policy"
# Terraform's "jsonencode" function converts a
# Terraform expression result to valid JSON syntax.
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
# ruleid: no-iam-priv-esc-roles
Action = ["datapipeline:PutPipelineDefinition", "datapipeline:CreatePipeline", "iam:PassRole"]
Effect = "Allow"
Resource = "arn:aws:iam::*:user/*"
},
]
})
}
resource "aws_iam_policy" "policy" {
name = "test_policy"
path = "/"
description = "My test policy"
# Terraform's "jsonencode" function converts a
# Terraform expression result to valid JSON syntax.
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
# ok: no-iam-priv-esc-roles
Action = "datapipeline:CreatePipeline"
Effect = "Allow"
Resource = "arn:aws:iam::*:user/*"
},
]
})
}
data aws_iam_policy_document "policy" {
statement {
# ruleid: no-iam-priv-esc-roles
actions = ["cloudformation:CreateStack", "iam:PassRole"]
principals {
type = "AWS"
identifiers = ["*"]
}
resources = ["*"]
}
}
Short Link: https://sg.run/jwrA