feat(iam): remove standalone iam:PassRole from privesc detection and add missing patterns (#8530)

This commit is contained in:
Andoni Alonso
2025-08-18 11:35:14 +02:00
committed by GitHub
parent 6918a75449
commit 2f5fce41dc
5 changed files with 33 additions and 22 deletions
@@ -362,17 +362,16 @@ class Test_iam_inline_policy_allows_privilege_escalation:
check = iam_inline_policy_allows_privilege_escalation()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert result[0].status == "PASS"
assert result[0].resource_id == f"test_role/{policy_name}"
assert result[0].resource_arn == role_arn
assert result[0].region == AWS_REGION_US_EAST_1
assert result[0].resource_tags == []
assert search(
f"Inline policy {policy_name} attached to role {role_name} allows privilege escalation using the following actions: ",
f"Inline policy {policy_name} attached to role {role_name} does not allow privilege escalation",
result[0].status_extended,
)
assert search("iam:PassRole", result[0].status_extended)
@mock_aws
def test_iam_inline_policy_allows_privilege_escalation_two_combinations(
@@ -511,17 +510,16 @@ class Test_iam_inline_policy_allows_privilege_escalation:
check = iam_inline_policy_allows_privilege_escalation()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert result[0].status == "PASS"
assert result[0].resource_id == f"test_role/{policy_name}"
assert result[0].resource_arn == role_arn
assert result[0].region == AWS_REGION_US_EAST_1
assert result[0].resource_tags == []
assert search(
f"Inline policy {policy_name} attached to role {role_name} allows privilege escalation using the following actions: ",
f"Inline policy {policy_name} attached to role {role_name} does not allow privilege escalation",
result[0].status_extended,
)
assert search("iam:PassRole", result[0].status_extended)
@mock_aws
def test_iam_inline_policy_allows_privilege_escalation_policies_combination(
@@ -322,17 +322,16 @@ class Test_iam_policy_allows_privilege_escalation:
check = iam_policy_allows_privilege_escalation()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert result[0].status == "PASS"
assert result[0].resource_id == policy_name
assert result[0].resource_arn == policy_arn
assert result[0].region == AWS_REGION_US_EAST_1
assert result[0].resource_tags == []
assert search(
f"Custom Policy {policy_arn} allows privilege escalation using the following actions: ",
f"Custom Policy {policy_arn} does not allow privilege escalation",
result[0].status_extended,
)
assert search("iam:PassRole", result[0].status_extended)
@mock_aws
def test_iam_policy_allows_privilege_escalation_iam_PassRole_using_wildcard(
@@ -375,17 +374,16 @@ class Test_iam_policy_allows_privilege_escalation:
check = iam_policy_allows_privilege_escalation()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert result[0].status == "PASS"
assert result[0].resource_id == policy_name
assert result[0].resource_arn == policy_arn
assert result[0].region == AWS_REGION_US_EAST_1
assert result[0].resource_tags == []
assert search(
f"Custom Policy {policy_arn} allows privilege escalation using the following actions: ",
f"Custom Policy {policy_arn} does not allow privilege escalation",
result[0].status_extended,
)
assert search("iam:PassRole", result[0].status_extended)
@mock_aws
def test_iam_policy_allows_privilege_escalation_two_combinations(
@@ -508,17 +506,16 @@ class Test_iam_policy_allows_privilege_escalation:
check = iam_policy_allows_privilege_escalation()
result = check.execute()
assert len(result) == 1
assert result[0].status == "FAIL"
assert result[0].status == "PASS"
assert result[0].resource_id == policy_name
assert result[0].resource_arn == policy_arn
assert result[0].region == AWS_REGION_US_EAST_1
assert result[0].resource_tags == []
assert search(
f"Custom Policy {policy_arn} allows privilege escalation using the following actions: ",
f"Custom Policy {policy_arn} does not allow privilege escalation",
result[0].status_extended,
)
assert search("iam:PassRole", result[0].status_extended)
@mock_aws
def test_iam_policy_allows_privilege_escalation_policies_combination(
@@ -52,7 +52,6 @@ class Test_PrivilegeEscalation:
assert "iam:Put*" in result
assert "iam:AddUserToGroup" in result
assert "iam:AttachRolePolicy" in result
assert "iam:PassRole" in result
assert "iam:CreateLoginProfile" in result
assert "iam:CreateAccessKey" in result
assert "iam:AttachGroupPolicy" in result
@@ -78,9 +77,9 @@ class Test_PrivilegeEscalation:
],
}
result = check_privilege_escalation(policy)
assert "iam:PassRole" in result
assert result == ""
def test_check_privilege_escalation_priv_escalation_iam_PassRole_using_wildcard(
def test_check_privilege_escalation_priv_escalation_iam_wildcard(
self,
):
policy = {
@@ -88,13 +87,16 @@ class Test_PrivilegeEscalation:
"Statement": [
{
"Effect": "Allow",
"Action": ["iam:*Role"], # Should expand to include PassRole
"Action": [
"iam:*"
], # Should expand to include multiple IAM actions
"Resource": ["*"],
}
],
}
result = check_privilege_escalation(policy)
assert "iam:PassRole" in result
# iam:* should expand to include PutUserPolicy and other privilege escalation actions
assert "iam:PutUserPolicy" in result
def test_check_privilege_escalation_priv_escalation_not_action(
self,
@@ -117,7 +119,6 @@ class Test_PrivilegeEscalation:
assert "'iam:PutGroupPolicy'" not in result
assert "iam:AddUserToGroup" in result
assert "iam:AttachRolePolicy" in result
assert "iam:PassRole" in result
assert "iam:CreateLoginProfile" in result
assert "iam:CreateAccessKey" in result
assert "iam:AttachGroupPolicy" in result