mirror of
https://github.com/prowler-cloud/prowler.git
synced 2026-07-04 19:21:51 +00:00
feat(iam): add AWS Bedrock AgentCore privilege escalation paths (#11726)
This commit is contained in:
@@ -22,6 +22,7 @@ All notable changes to the **Prowler SDK** are documented in this file.
|
||||
- CIS Google Cloud Platform Foundation Benchmark v5.0.0 compliance framework for the GCP provider [(#11714)](https://github.com/prowler-cloud/prowler/pull/11714)
|
||||
- CIS Kubernetes Benchmark v2.0.1 compliance framework for the Kubernetes provider [(#11722)](https://github.com/prowler-cloud/prowler/pull/11722)
|
||||
- CIS GitHub Benchmark v1.2.0 compliance framework for the GitHub provider [(#11719)](https://github.com/prowler-cloud/prowler/pull/11719)
|
||||
- AWS Bedrock AgentCore privilege escalation paths in the IAM privilege escalation checks, covering Runtime, Harness, Code Interpreter and Custom Browser [(#11726)](https://github.com/prowler-cloud/prowler/pull/11726)
|
||||
- `--scan-secrets-validate` flag and `aws.secrets_validate` configuration option to optionally validate the secrets discovered by the secret-scanning checks against the provider APIs; secrets confirmed to be live are reported as critical [(#11694)](https://github.com/prowler-cloud/prowler/pull/11694)
|
||||
|
||||
### 🔄 Changed
|
||||
|
||||
@@ -19,6 +19,7 @@ from prowler.providers.aws.services.iam.lib.policy import get_effective_actions
|
||||
# - https://github.com/RhinoSecurityLabs/Security-Research/blob/master/tools/aws-pentest-tools/aws_escalate.py
|
||||
# - https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/
|
||||
# - https://github.com/DataDog/pathfinding.cloud (AWS IAM Privilege Escalation Path Library)
|
||||
# - https://www.beyondtrust.com/blog/entry/aws-agentcore-privilege-escalation (AWS Bedrock AgentCore)
|
||||
|
||||
privilege_escalation_policies_combination = {
|
||||
# IAM self-escalation and policy manipulation
|
||||
@@ -299,6 +300,7 @@ privilege_escalation_policies_combination = {
|
||||
"PassRole+AgentCoreCreateInterpreter+InvokeInterpreter": {
|
||||
"iam:PassRole",
|
||||
"bedrock-agentcore:CreateCodeInterpreter",
|
||||
"bedrock-agentcore:StartCodeInterpreterSession",
|
||||
"bedrock-agentcore:InvokeCodeInterpreter",
|
||||
},
|
||||
# Prerequisite: Existing Bedrock code interpreter with admin role
|
||||
@@ -306,6 +308,40 @@ privilege_escalation_policies_combination = {
|
||||
"bedrock-agentcore:StartCodeInterpreterSession",
|
||||
"bedrock-agentcore:InvokeCodeInterpreter",
|
||||
},
|
||||
# Prerequisite: Existing AgentCore Runtime or Harness with admin execution role.
|
||||
# InvokeAgentRuntimeCommand runs shell commands as root inside the microVM and
|
||||
# reads the execution role credentials from MMDS, bypassing the agent and guardrails.
|
||||
"AgentCoreInvokeRuntimeCommand": {
|
||||
"bedrock-agentcore:InvokeAgentRuntimeCommand",
|
||||
},
|
||||
"PassRole+AgentCoreCreateRuntime+InvokeRuntimeCommand": {
|
||||
"iam:PassRole",
|
||||
"bedrock-agentcore:CreateAgentRuntime",
|
||||
"bedrock-agentcore:CreateAgentRuntimeEndpoint",
|
||||
"bedrock-agentcore:CreateWorkloadIdentity",
|
||||
"bedrock-agentcore:InvokeAgentRuntimeCommand",
|
||||
},
|
||||
"PassRole+AgentCoreCreateHarness+InvokeRuntimeCommand": {
|
||||
"iam:PassRole",
|
||||
"bedrock-agentcore:CreateHarness",
|
||||
"bedrock-agentcore:CreateAgentRuntime",
|
||||
"bedrock-agentcore:CreateAgentRuntimeEndpoint",
|
||||
"bedrock-agentcore:CreateWorkloadIdentity",
|
||||
"bedrock-agentcore:GetAgentRuntime",
|
||||
"bedrock-agentcore:InvokeAgentRuntimeCommand",
|
||||
},
|
||||
# Prerequisite: Existing AgentCore Custom Browser with admin execution role.
|
||||
# A remote CDP driver on the browser session reads the role credentials from MMDS.
|
||||
"AgentCoreBrowserSessionConnect": {
|
||||
"bedrock-agentcore:StartBrowserSession",
|
||||
"bedrock-agentcore:ConnectBrowserAutomationStream",
|
||||
},
|
||||
"PassRole+AgentCoreCreateBrowser+ConnectBrowser": {
|
||||
"iam:PassRole",
|
||||
"bedrock-agentcore:CreateBrowser",
|
||||
"bedrock-agentcore:StartBrowserSession",
|
||||
"bedrock-agentcore:ConnectBrowserAutomationStream",
|
||||
},
|
||||
# TO-DO: We have to handle AssumeRole just if the resource is * and without conditions
|
||||
# "sts:AssumeRole": {"sts:AssumeRole"},
|
||||
}
|
||||
|
||||
+5
@@ -1239,6 +1239,7 @@ class Test_iam_inline_policy_allows_privilege_escalation:
|
||||
"Action": [
|
||||
"iam:PassRole",
|
||||
"bedrock-agentcore:CreateCodeInterpreter",
|
||||
"bedrock-agentcore:StartCodeInterpreterSession",
|
||||
"bedrock-agentcore:InvokeCodeInterpreter",
|
||||
],
|
||||
"Resource": "*",
|
||||
@@ -1286,6 +1287,10 @@ class Test_iam_inline_policy_allows_privilege_escalation:
|
||||
assert search(
|
||||
"bedrock-agentcore:CreateCodeInterpreter", result[0].status_extended
|
||||
)
|
||||
assert search(
|
||||
"bedrock-agentcore:StartCodeInterpreterSession",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert search(
|
||||
"bedrock-agentcore:InvokeCodeInterpreter", result[0].status_extended
|
||||
)
|
||||
|
||||
+382
@@ -928,6 +928,7 @@ class Test_iam_policy_allows_privilege_escalation:
|
||||
"Action": [
|
||||
"iam:PassRole",
|
||||
"bedrock-agentcore:CreateCodeInterpreter",
|
||||
"bedrock-agentcore:StartCodeInterpreterSession",
|
||||
"bedrock-agentcore:InvokeCodeInterpreter",
|
||||
],
|
||||
"Resource": "*",
|
||||
@@ -973,10 +974,391 @@ class Test_iam_policy_allows_privilege_escalation:
|
||||
assert search(
|
||||
"bedrock-agentcore:CreateCodeInterpreter", result[0].status_extended
|
||||
)
|
||||
assert search(
|
||||
"bedrock-agentcore:StartCodeInterpreterSession",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert search(
|
||||
"bedrock-agentcore:InvokeCodeInterpreter", result[0].status_extended
|
||||
)
|
||||
|
||||
@mock_aws
|
||||
def test_iam_policy_allows_privilege_escalation_agentcore_invoke_runtime_command(
|
||||
self,
|
||||
):
|
||||
"""Test detection of AgentCore Runtime/Harness privilege escalation via InvokeAgentRuntimeCommand on an existing resource."""
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])
|
||||
iam_client = client("iam", region_name=AWS_REGION_US_EAST_1)
|
||||
policy_name = "agentcore_invoke_runtime_command_policy"
|
||||
policy_document = {
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"bedrock-agentcore:InvokeAgentRuntimeCommand",
|
||||
],
|
||||
"Resource": "*",
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
policy_arn = iam_client.create_policy(
|
||||
PolicyName=policy_name, PolicyDocument=dumps(policy_document)
|
||||
)["Policy"]["Arn"]
|
||||
|
||||
from prowler.providers.aws.services.iam.iam_service import IAM
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.iam.iam_policy_allows_privilege_escalation.iam_policy_allows_privilege_escalation.iam_client",
|
||||
new=IAM(aws_provider),
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.iam.iam_policy_allows_privilege_escalation.iam_policy_allows_privilege_escalation import (
|
||||
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].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: ",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert search(
|
||||
"bedrock-agentcore:InvokeAgentRuntimeCommand",
|
||||
result[0].status_extended,
|
||||
)
|
||||
|
||||
@mock_aws
|
||||
def test_iam_policy_allows_privilege_escalation_agentcore_passrole_create_runtime(
|
||||
self,
|
||||
):
|
||||
"""Test detection of AgentCore Runtime privilege escalation by creating a new runtime with a passed role."""
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])
|
||||
iam_client = client("iam", region_name=AWS_REGION_US_EAST_1)
|
||||
policy_name = "agentcore_create_runtime_policy"
|
||||
policy_document = {
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"iam:PassRole",
|
||||
"bedrock-agentcore:CreateAgentRuntime",
|
||||
"bedrock-agentcore:CreateAgentRuntimeEndpoint",
|
||||
"bedrock-agentcore:CreateWorkloadIdentity",
|
||||
"bedrock-agentcore:InvokeAgentRuntimeCommand",
|
||||
],
|
||||
"Resource": "*",
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
policy_arn = iam_client.create_policy(
|
||||
PolicyName=policy_name, PolicyDocument=dumps(policy_document)
|
||||
)["Policy"]["Arn"]
|
||||
|
||||
from prowler.providers.aws.services.iam.iam_service import IAM
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.iam.iam_policy_allows_privilege_escalation.iam_policy_allows_privilege_escalation.iam_client",
|
||||
new=IAM(aws_provider),
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.iam.iam_policy_allows_privilege_escalation.iam_policy_allows_privilege_escalation import (
|
||||
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].resource_id == policy_name
|
||||
assert result[0].resource_arn == policy_arn
|
||||
assert search("iam:PassRole", result[0].status_extended)
|
||||
assert search(
|
||||
"bedrock-agentcore:CreateAgentRuntime",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert search(
|
||||
"bedrock-agentcore:CreateAgentRuntimeEndpoint",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert search(
|
||||
"bedrock-agentcore:CreateWorkloadIdentity",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert search(
|
||||
"bedrock-agentcore:InvokeAgentRuntimeCommand",
|
||||
result[0].status_extended,
|
||||
)
|
||||
|
||||
@mock_aws
|
||||
def test_iam_policy_allows_privilege_escalation_agentcore_passrole_create_harness(
|
||||
self,
|
||||
):
|
||||
"""Test detection of AgentCore Harness privilege escalation by creating a new harness with a passed role."""
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])
|
||||
iam_client = client("iam", region_name=AWS_REGION_US_EAST_1)
|
||||
policy_name = "agentcore_create_harness_policy"
|
||||
policy_document = {
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"iam:PassRole",
|
||||
"bedrock-agentcore:CreateHarness",
|
||||
"bedrock-agentcore:CreateAgentRuntime",
|
||||
"bedrock-agentcore:CreateAgentRuntimeEndpoint",
|
||||
"bedrock-agentcore:CreateWorkloadIdentity",
|
||||
"bedrock-agentcore:GetAgentRuntime",
|
||||
"bedrock-agentcore:InvokeAgentRuntimeCommand",
|
||||
],
|
||||
"Resource": "*",
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
policy_arn = iam_client.create_policy(
|
||||
PolicyName=policy_name, PolicyDocument=dumps(policy_document)
|
||||
)["Policy"]["Arn"]
|
||||
|
||||
from prowler.providers.aws.services.iam.iam_service import IAM
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.iam.iam_policy_allows_privilege_escalation.iam_policy_allows_privilege_escalation.iam_client",
|
||||
new=IAM(aws_provider),
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.iam.iam_policy_allows_privilege_escalation.iam_policy_allows_privilege_escalation import (
|
||||
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].resource_id == policy_name
|
||||
assert result[0].resource_arn == policy_arn
|
||||
assert search("iam:PassRole", result[0].status_extended)
|
||||
assert search("bedrock-agentcore:CreateHarness", result[0].status_extended)
|
||||
assert search(
|
||||
"bedrock-agentcore:CreateAgentRuntime",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert search(
|
||||
"bedrock-agentcore:CreateAgentRuntimeEndpoint",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert search(
|
||||
"bedrock-agentcore:CreateWorkloadIdentity",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert search(
|
||||
"bedrock-agentcore:GetAgentRuntime", result[0].status_extended
|
||||
)
|
||||
assert search(
|
||||
"bedrock-agentcore:InvokeAgentRuntimeCommand",
|
||||
result[0].status_extended,
|
||||
)
|
||||
|
||||
@mock_aws
|
||||
def test_iam_policy_allows_privilege_escalation_agentcore_browser_session_connect(
|
||||
self,
|
||||
):
|
||||
"""Test detection of AgentCore Custom Browser privilege escalation via an existing browser session."""
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])
|
||||
iam_client = client("iam", region_name=AWS_REGION_US_EAST_1)
|
||||
policy_name = "agentcore_browser_session_connect_policy"
|
||||
policy_document = {
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"bedrock-agentcore:StartBrowserSession",
|
||||
"bedrock-agentcore:ConnectBrowserAutomationStream",
|
||||
],
|
||||
"Resource": "*",
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
policy_arn = iam_client.create_policy(
|
||||
PolicyName=policy_name, PolicyDocument=dumps(policy_document)
|
||||
)["Policy"]["Arn"]
|
||||
|
||||
from prowler.providers.aws.services.iam.iam_service import IAM
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.iam.iam_policy_allows_privilege_escalation.iam_policy_allows_privilege_escalation.iam_client",
|
||||
new=IAM(aws_provider),
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.iam.iam_policy_allows_privilege_escalation.iam_policy_allows_privilege_escalation import (
|
||||
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].resource_id == policy_name
|
||||
assert result[0].resource_arn == policy_arn
|
||||
assert search(
|
||||
"bedrock-agentcore:StartBrowserSession", result[0].status_extended
|
||||
)
|
||||
assert search(
|
||||
"bedrock-agentcore:ConnectBrowserAutomationStream",
|
||||
result[0].status_extended,
|
||||
)
|
||||
|
||||
@mock_aws
|
||||
def test_iam_policy_allows_privilege_escalation_agentcore_passrole_create_browser(
|
||||
self,
|
||||
):
|
||||
"""Test detection of AgentCore Custom Browser privilege escalation by creating a new browser with a passed role."""
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])
|
||||
iam_client = client("iam", region_name=AWS_REGION_US_EAST_1)
|
||||
policy_name = "agentcore_create_browser_policy"
|
||||
policy_document = {
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"iam:PassRole",
|
||||
"bedrock-agentcore:CreateBrowser",
|
||||
"bedrock-agentcore:StartBrowserSession",
|
||||
"bedrock-agentcore:ConnectBrowserAutomationStream",
|
||||
],
|
||||
"Resource": "*",
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
policy_arn = iam_client.create_policy(
|
||||
PolicyName=policy_name, PolicyDocument=dumps(policy_document)
|
||||
)["Policy"]["Arn"]
|
||||
|
||||
from prowler.providers.aws.services.iam.iam_service import IAM
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.iam.iam_policy_allows_privilege_escalation.iam_policy_allows_privilege_escalation.iam_client",
|
||||
new=IAM(aws_provider),
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.iam.iam_policy_allows_privilege_escalation.iam_policy_allows_privilege_escalation import (
|
||||
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].resource_id == policy_name
|
||||
assert result[0].resource_arn == policy_arn
|
||||
assert search("iam:PassRole", result[0].status_extended)
|
||||
assert search("bedrock-agentcore:CreateBrowser", result[0].status_extended)
|
||||
assert search(
|
||||
"bedrock-agentcore:StartBrowserSession", result[0].status_extended
|
||||
)
|
||||
assert search(
|
||||
"bedrock-agentcore:ConnectBrowserAutomationStream",
|
||||
result[0].status_extended,
|
||||
)
|
||||
|
||||
@mock_aws
|
||||
def test_iam_policy_allows_privilege_escalation_agentcore_wildcard(
|
||||
self,
|
||||
):
|
||||
"""Test detection of AgentCore privilege escalation when the policy grants the bedrock-agentcore:* namespace wildcard."""
|
||||
aws_provider = set_mocked_aws_provider([AWS_REGION_US_EAST_1])
|
||||
iam_client = client("iam", region_name=AWS_REGION_US_EAST_1)
|
||||
policy_name = "agentcore_wildcard_policy"
|
||||
policy_document = {
|
||||
"Version": "2012-10-17",
|
||||
"Statement": [
|
||||
{
|
||||
"Effect": "Allow",
|
||||
"Action": [
|
||||
"bedrock-agentcore:*",
|
||||
],
|
||||
"Resource": "*",
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
policy_arn = iam_client.create_policy(
|
||||
PolicyName=policy_name, PolicyDocument=dumps(policy_document)
|
||||
)["Policy"]["Arn"]
|
||||
|
||||
from prowler.providers.aws.services.iam.iam_service import IAM
|
||||
|
||||
with (
|
||||
mock.patch(
|
||||
"prowler.providers.common.provider.Provider.get_global_provider",
|
||||
return_value=aws_provider,
|
||||
),
|
||||
mock.patch(
|
||||
"prowler.providers.aws.services.iam.iam_policy_allows_privilege_escalation.iam_policy_allows_privilege_escalation.iam_client",
|
||||
new=IAM(aws_provider),
|
||||
),
|
||||
):
|
||||
from prowler.providers.aws.services.iam.iam_policy_allows_privilege_escalation.iam_policy_allows_privilege_escalation import (
|
||||
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].resource_id == policy_name
|
||||
assert result[0].resource_arn == policy_arn
|
||||
assert search(
|
||||
"bedrock-agentcore:InvokeAgentRuntimeCommand",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert search(
|
||||
"bedrock-agentcore:StartCodeInterpreterSession",
|
||||
result[0].status_extended,
|
||||
)
|
||||
assert search(
|
||||
"bedrock-agentcore:StartBrowserSession", result[0].status_extended
|
||||
)
|
||||
|
||||
@mock_aws
|
||||
def test_iam_policy_allows_privilege_escalation_iam_put(
|
||||
self,
|
||||
|
||||
Reference in New Issue
Block a user