From f5e21a12c523016226dfaa19003b943e09f74c41 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Mon, 12 Oct 2026 20:29:17 +0200 Subject: [PATCH 01/17] Integrate verified AWS privesc v4 catalog fragments Co-Authored-By: Codex --- .../aws/_excluded_171e_g1.yaml | 37 +- .../aws/_excluded_171e_g7.yaml | 76 +- .../aws/_excluded_a.yaml | 309 +++--- .../aws/_excluded_audit_6fb9.yaml | 227 +++-- .../aws/_excluded_b.yaml | 244 +++-- .../aws/_excluded_refresh_g3.yaml | 46 +- .../aws/_excluded_refresh_g4.yaml | 93 +- .../aws/_excluded_refresh_g5.yaml | 61 +- .../aws/_excluded_refresh_g6.yaml | 138 +-- .../aws/_excluded_refresh_g7.yaml | 59 +- .../aws/_excluded_v4.yaml | 277 ++++++ .../aws/amplify.yaml | 299 ++++-- .../aws/apigateway.yaml | 36 +- .../aws/appconfig.yaml | 45 +- .../aws/appflow.yaml | 42 +- .../aws/apprunner.yaml | 78 +- .../aws/appstream.yaml | 187 ++-- .../aws/athena.yaml | 133 ++- .../aws/bedrock.yaml | 288 +++--- .../aws/billing.yaml | 31 + .../aws/budgets.yaml | 44 +- .../aws/challenge-v3.yaml | 853 +++++++++-------- src/privilege-escalation-paths/aws/chime.yaml | 42 +- .../aws/cloudformation.yaml | 360 ++++--- .../aws/cloudfront.yaml | 14 +- .../aws/codebuild.yaml | 324 ++++--- .../aws/codecommit.yaml | 128 +-- .../aws/codepipeline.yaml | 179 +++- .../aws/connect.yaml | 114 ++- .../aws/devicefarm.yaml | 91 +- .../aws/dynamodb.yaml | 34 + src/privilege-escalation-paths/aws/ec2.yaml | 441 +++++---- src/privilege-escalation-paths/aws/ecr.yaml | 318 ++++--- src/privilege-escalation-paths/aws/eks.yaml | 437 +++++---- .../aws/elasticbeanstalk.yaml | 122 +-- .../aws/events.yaml | 37 +- src/privilege-escalation-paths/aws/flink.yaml | 117 ++- .../aws/gameliftstreams.yaml | 72 +- .../aws/grafana.yaml | 119 ++- src/privilege-escalation-paths/aws/iam.yaml | 891 +++++++++--------- src/privilege-escalation-paths/aws/iot.yaml | 126 ++- .../aws/lambda.yaml | 763 ++++++++++----- .../aws/migrationhub.yaml | 86 +- .../aws/mldataaccess.yaml | 184 ++-- src/privilege-escalation-paths/aws/msk.yaml | 32 + .../aws/organizations.yaml | 147 +-- .../aws/pcaconnectorad.yaml | 108 ++- src/privilege-escalation-paths/aws/rds.yaml | 280 ++++-- 48 files changed, 5410 insertions(+), 3759 deletions(-) create mode 100644 src/privilege-escalation-paths/aws/_excluded_v4.yaml create mode 100644 src/privilege-escalation-paths/aws/billing.yaml create mode 100644 src/privilege-escalation-paths/aws/dynamodb.yaml create mode 100644 src/privilege-escalation-paths/aws/msk.yaml diff --git a/src/privilege-escalation-paths/aws/_excluded_171e_g1.yaml b/src/privilege-escalation-paths/aws/_excluded_171e_g1.yaml index 47f13e9b6a..fcfab4bbea 100644 --- a/src/privilege-escalation-paths/aws/_excluded_171e_g1.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_171e_g1.yaml @@ -1,27 +1,34 @@ # 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-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#no-direct-iam-role-escalation-primitive +- 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." + 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#turn-cost-view-administration-into-cross-account-disclosure +- 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." + 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: 171e422299 -- 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#abuse-invoice-receiver-delegation +- 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." + 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: 171e422299 -- 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 +- 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." + 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: 171e422299 -- 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: + 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: 171e422299 diff --git a/src/privilege-escalation-paths/aws/_excluded_171e_g7.yaml b/src/privilege-escalation-paths/aws/_excluded_171e_g7.yaml index d3747a87f6..06ece6b38f 100644 --- a/src/privilege-escalation-paths/aws/_excluded_171e_g7.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_171e_g7.yaml @@ -1,69 +1,73 @@ # G7 heading-level exclusions verified against hacktricks-cloud 171e422299. -- 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: 171e422299 -- 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: 171e422299 -- 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: 171e422299 -- 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-twinmaker-privesc/README.md#connector-invocation-without-direct-lambda-permission +- 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." + 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iot-twinmaker-privesc/README.md#updateworkspace--iampassrole--connector-control +- 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." + 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivscreatestreamkey-on-stream-key---publish-to-another-channel +- 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivsgetstreamkey-or-ivsgetingestconfiguration---convert-a-read-into-publishing-access +- 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivscreateparticipanttoken---mint-stage-publishsubscribe-access +- 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivsimportpublickey---sign-tokens-for-stages-account-wide +- 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivsimportplaybackkeypair---bypass-private-channel-playback-decisions +- 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ivs-privesc/README.md#ivsstartcomposition---send-a-stage-to-an-unauthorized-channel +- 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lex-v2-privesc/README.md#lexcreatebotlexupdatebot--iampassrole +- 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." + 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lex-v2-privesc/README.md#existing-hook-as-a-confused-business-authority-boundary +- 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." + 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-blockchain-privesc/README.md#invite-an-attacker-account-into-a-hyperledger-fabric-network +- 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)." + 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#grafanaupdateworkspace--iampassrole +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-grafana-privesc/README.md#grafanaupdateworkspace--iampassrole 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." + 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-wickr-privesc/README.md#wickrcreatedataretentionbotchallenge--take-over-the-data-retention-bot +- 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." + 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: 171e422299 diff --git a/src/privilege-escalation-paths/aws/_excluded_a.yaml b/src/privilege-escalation-paths/aws/_excluded_a.yaml index 1807bb5f23..b97d2399bc 100644 --- a/src/privilege-escalation-paths/aws/_excluded_a.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_a.yaml @@ -4,53 +4,74 @@ # --- IAM --- - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateaccesskey 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. + 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-privilege-escalation/aws-iam-privesc/README.md#iamresyncmfadevice 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-privilege-escalation/aws-iam-privesc/README.md#iamupdateopenidconnectproviderthumbprint-iamlistopenidconnectproviders-iamgetopenidconnectprovider +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamupdateopenidconnectproviderthumbprint-iamlistopenidconnectproviders-iamgetopenidconnectprovider 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 + 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. + 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 + 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. + 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. + 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 +- 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. + 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-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#ssogetrolecredentials +- 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. + 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 +- 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 + 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 +- 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 + 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 + 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 @@ -58,15 +79,18 @@ 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 +- 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 +- 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-privilege-escalation/aws-amplify-privesc/README.md#amplifygetartifacturl--download-end-to-end-test-artifacts +- 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. @@ -77,211 +101,268 @@ - 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-privilege-escalation/aws-apigateway-privesc/README.md#apigatewayupdaterestapipolicy--apigatewaypatch +- 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 +- 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 +- 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 +- 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 +- 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 +- 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 +- 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-privilege-escalation/aws-chime-privesc/README.md#legacy-chimecreateapikey - source_revision: 171e422299 - 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-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationexecutechangeset-on-a-pre-staged-change-set +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationexecutechangeset-on-a-pre-staged-change-set 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-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationsignalresource--release-a-stack-waiting-on-a-success-signal + 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-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationsignalresource--release-a-stack-waiting-on-a-success-signal 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 + 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-privilege-escalation/aws-cloudfront-privesc/README.md#cloudfrontupdatedistribution--cloudfrontgetdistributionconfig +- 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: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudfront-privesc/README.md#cloudfrontcreatefunction-cloudfrontdescribefunction-cloudfrontpublishfunction-cloudfrontgetdistributionconfig--cloudfrontupdatedistribution +- 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: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#codebuildretrybuild--re-execute-a-completed-build-under-its-stored-role +- 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 + 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-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 +- 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 +- 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 +- 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 +- 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 +- 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 +- 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-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelinepollforjobs +- 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. + 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 +- 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 +- 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 +- 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 +- 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 +- 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-privilege-escalation/aws-dynamodb-privesc/README.md#todo-read-data-abusing-data-streams +- 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-privilege-escalation/aws-ebs-privesc/README.md#ebslistsnapshotblocks-ebsgetsnapshotblock-ec2describesnapshots +- 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-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-privilege-escalation/aws-ec2-privesc/README.md#replace-security-groups-on-a-running-instance +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#replace-security-groups-on-a-running-instance 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 +- 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-privilege-escalation/aws-ec2-privesc/README.md#autoscalingsetdesiredcapacity--activate-a-stored-launch-template-and-instance-role +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#autoscalingsetdesiredcapacity--activate-a-stored-launch-template-and-instance-role 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-privilege-escalation/aws-ec2-privesc/README.md#ec2-instance-connectsendserialconsolesshpublickey +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2-instance-connectsendserialconsolesshpublickey 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-privilege-escalation/aws-ec2-privesc/README.md#ec2describelaunchtemplateversions-ec2describelaunchtemplates-optional - technique: ec2:DescribeLaunchTemplateVersions - reason: Data read (secrets in user data). -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2modifyinstancemetadataoptions-imds-downgrade-to-enable-ssrf-credential-theft + 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-privilege-escalation/aws-ec2-privesc/README.md#ec2modifyinstancemetadataoptions-imds-downgrade-to-enable-ssrf-credential-theft 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-privilege-escalation/aws-ec2-privesc/README.md#ec2modifyimageattribute-ec2modifysnapshotattribute - technique: ec2:ModifyImageAttribute / ModifySnapshotAttribute - reason: Data sharing/exfiltration; no identity gain. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2getpassworddata 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. + 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 +- 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 +- 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-privilege-escalation/aws-ecs-privesc/README.md#ecsupdateservice--reactivate-a-dormant-service-with-its-stored-task-role +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecs-privesc/README.md#ecsupdateservice--reactivate-a-dormant-service-with-its-stored-task-role 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 +- 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 +- 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 +- 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 +- 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 +- 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 +- 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 +- 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. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#apigatewayput-apigatewaypost-and-sometimes-iampassrole + technique: PutIntegration and CreateDeployment to invoke Lambda through optional integration role + reason: The documented Lambda AWS_PROXY integration invokes one function; optional PassRole does not yield the + integration role or Lambda execution role. A role-to-role edge would be false. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appconfig-privesc/README.md#appconfigcreateconfigurationprofile--iampassrole--deploymentread-permissions + technique: Passed retrieval role reads a chosen secret/object through AppConfig + reason: AppConfig returns only selected external-source bytes; it does not expose a role session or arbitrary role + actions. A credential edge requires content evidence, source ARN, retrieval-role read permission and KMS permission. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appflow-privesc/README.md#createflowupdateflow--iampassrole-to-aws-glue-catalog-authority + technique: CreateFlow or UpdateFlow uses passed role for Glue catalog mutation + reason: AppFlow can mutate Glue catalog metadata through a configured flow, but never yields the passed role or + arbitrary role execution; connector profile and S3 dependencies also need exact facts. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreatestreamingurl--enter-an-existing-fleet-under-its-machine-role + technique: CreateStreamingURL to existing stack and fleet machine role + reason: A stack/fleet association and authorization on both exact ARNs are required; the current Resource:* only rule + misses scoped grants and the inventory lacks an exact pair join. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamupdatefleet--replace-an-existing-fleet-image-while-retaining-its-role + technique: UpdateFleet swaps image retaining fleet role + reason: Image replacement requires fleet and private/shared image authorization on the paired ARNs; AWS-owned public + images are an exception. The current single fleet requirement cannot decide both paths. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-spark-role-privesc/README.md#athenagetsessionendpoint--take-over-an-active-spark-connect-session + technique: GetSessionEndpoint for live Spark Connect session + reason: GetSessionEndpoint requires the containing workgroup and live session ARN; the current workgroup-only rule can + report an expressly denied session. +- 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: budgets:CreateBudgetAction + iam:PassRole (generic role-impersonation rule) + reason: Budget APPLY_IAM_POLICY can grant a selected user/group/role only when the passed role can attach the chosen + managed policy and the action fires. APPLY_SCP_POLICY changes an organization guardrail, while RUN_SSM_DOCUMENTS + executes a chosen document on EC2. None yields the passed role; exact action type, target and trigger facts are + required. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md#chimecreatemediainsightspipelineconfiguration--iampassrole + technique: Create or update media insights pipeline configuration with passed role + reason: The media pipeline role is used only for configured source, processor and sink actions; no role credentials or + arbitrary role authority are returned. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md#legacy-chimecreateapikey + source_revision: 171e422299 + technique: chime:CreateApiKey + reason: Legacy Amazon Chime Enterprise SCIM/Okta key only. The collaboration service ended support on 2026-02-20, new + accounts cannot create legacy Team/Enterprise accounts, and the page gives no executable modern Chime SDK + privilege-escalation path. diff --git a/src/privilege-escalation-paths/aws/_excluded_audit_6fb9.yaml b/src/privilege-escalation-paths/aws/_excluded_audit_6fb9.yaml index b2679c7cf1..f74c2494db 100644 --- a/src/privilege-escalation-paths/aws/_excluded_audit_6fb9.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_audit_6fb9.yaml @@ -2,107 +2,148 @@ # 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 +- 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 + 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. + 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 +- 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 + 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 + 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-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 + 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 + 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 + 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. + 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 +- 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. + 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 +- 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 +- 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). + 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 +- 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.' + 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 +- 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). + 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 +- 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 + 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 +- 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 +- 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 +- 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. + 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 +- 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 +- 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 +- 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. + 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 +- 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: 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 +- 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 +- 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 +- 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 @@ -110,67 +151,97 @@ 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 +- 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 +- 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 +- 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 +- 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. + 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 +- 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)." + 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 +- 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)." + 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 +- 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." + 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 +- 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)." + 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 +- 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." + 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 +- 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." + 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 +- 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." + 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 +- 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." + 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 +- 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." + 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 +- 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 + 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. + 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/aws/_excluded_b.yaml b/src/privilege-escalation-paths/aws/_excluded_b.yaml index b85311a7a4..f37794bb4b 100644 --- a/src/privilege-escalation-paths/aws/_excluded_b.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_b.yaml @@ -1,31 +1,24 @@ # 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 - source_revision: a53b46392c - technique: elasticfilesystem:DeleteFileSystemPolicy / PutFileSystemPolicy - reason: Grants NFS data access to the file system; no other principal's IAM privileges are obtained (data access/exposure). -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemclientmount-and-client-action-combinations - source_revision: a53b46392c - 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-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemcreateaccesspoint--elasticfilesystemclientmount - source_revision: a53b46392c - technique: elasticfilesystem:CreateAccessPoint + ClientMount - reason: Bypasses POSIX restrictions on file data; data access only. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemcreatemounttarget +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemcreatemounttarget source_revision: a53b46392c technique: elasticfilesystem:CreateMountTarget reason: Network pivot to reach the file system; no new identity. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemmodifymounttargetsecuritygroups +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemmodifymounttargetsecuritygroups source_revision: a53b46392c technique: elasticfilesystem:ModifyMountTargetSecurityGroups reason: Network pivot to reach the file system; no new identity. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#gameliftrequestuploadcredentials +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift/README.md#gameliftrequestuploadcredentials source_revision: a53b46392c 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 + 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. @@ -33,7 +26,8 @@ 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: + 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. @@ -41,71 +35,79 @@ source_revision: a53b46392c technique: kms:Decrypt reason: Data read only. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsaildownloaddefaultkeypair +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsaildownloaddefaultkeypair source_revision: a53b46392c 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 + 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-privilege-escalation/aws-lightsail-privesc/README.md#lightsailcreatebucketaccesskey +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailcreatebucketaccesskey source_revision: a53b46392c technique: lightsail:CreateBucketAccessKey reason: Creates keys scoped to a Lightsail bucket (service-managed identity); data access only. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailgetrelationaldatabasemasteruserpassword +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailgetrelationaldatabasemasteruserpassword source_revision: a53b46392c technique: lightsail:GetRelationalDatabaseMasterUserPassword reason: Database credential read; data access. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailupdaterelationaldatabase +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailupdaterelationaldatabase source_revision: a53b46392c technique: lightsail:UpdateRelationalDatabase reason: Database password reset/exposure; data access. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailopeninstancepublicports +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailopeninstancepublicports source_revision: a53b46392c technique: lightsail:OpenInstancePublicPorts reason: Network exposure; no new identity. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailputinstancepublicports +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailputinstancepublicports source_revision: a53b46392c technique: lightsail:PutInstancePublicPorts reason: Network exposure; no new identity. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailsetresourceaccessforbucket +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailsetresourceaccessforbucket source_revision: a53b46392c technique: lightsail:SetResourceAccessForBucket reason: Bucket data access for an instance; no IAM principal. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailupdatebucket +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailupdatebucket source_revision: a53b46392c 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: + 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: + 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-privilege-escalation/aws-macie-privesc/README.md#amazon-macie---bypass-reveal-sample-integrity-check - source_revision: a53b46392c - technique: Macie reveal-sample integrity bypass - reason: Data disclosure only. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#mediapackagedescribechannel +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#mediapackagedescribechannel source_revision: a53b46392c 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-privilege-escalation/aws-mediapackage-privesc/README.md#mediapackagelistchannels +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#mediapackagelistchannels source_revision: a53b46392c technique: mediapackage:ListChannels reason: Read only. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#mediapackagerotatechannelcredentials +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#mediapackagerotatechannelcredentials source_revision: a53b46392c technique: mediapackage:RotateChannelCredentials reason: Rotates ingest credentials; media-plane access/DoS, no IAM principal. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#mediapackagerotateingestendpointcredentials +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mediapackage-privesc/README.md#mediapackagerotateingestendpointcredentials source_revision: a53b46392c technique: mediapackage:RotateIngestEndpointCredentials reason: Rotates ingest credentials; media-plane access/DoS, no IAM principal. @@ -117,51 +119,37 @@ source_revision: a53b46392c technique: mq:UpdateUser reason: Broker user change; message data access, no IAM principal. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-msk-privesc/README.md#kafkaupdatesecurity-to-expose-private-topics-without-credentials +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-msk-privesc/README.md#kafkaupdatesecurity-to-expose-private-topics-without-credentials source_revision: a53b46392c technique: kafka:UpdateSecurity reason: Enables unauthenticated access to topics; data exposure, no IAM principal. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-route53-domains-privesc/README.md#route53domainsgetdomaindetail--read-domain-registration-contacts +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-route53-domains-privesc/README.md#route53domainsgetdomaindetail--read-domain-registration-contacts source_revision: a53b46392c technique: route53domains:GetDomainDetail reason: Read only. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-route53-domains-privesc/README.md#route53domainsretrievedomainauthcode--steal-a-domain-transfer-credential +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-route53-domains-privesc/README.md#route53domainsretrievedomainauthcode--steal-a-domain-transfer-credential source_revision: a53b46392c technique: route53domains:RetrieveDomainAuthCode reason: Domain transfer credential theft; external asset takeover, no IAM principal. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-secrets-manager-privesc/README.md#secretsmanagergetsecretvalue +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-secrets-manager-privesc/README.md#secretsmanagergetsecretvalue source_revision: a53b46392c 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: a53b46392c - technique: secretsmanager:PutResourcePolicy - reason: Grants secret read access; data access only. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc/README.md#snssubscribe - source_revision: a53b46392c - 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-privilege-escalation/aws-workdocs-privesc/README.md#workdocscreateuser source_revision: a53b46392c technique: workdocs:CreateUser reason: Application-level user in WorkDocs; no IAM principal. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocs-activity-metadata-and-content-read-chain +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocs-activity-metadata-and-content-read-chain source_revision: a53b46392c technique: WorkDocs activity/metadata/content read chain reason: Data read. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocsaddresourcepermissions +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocsaddresourcepermissions source_revision: a53b46392c technique: workdocs:AddResourcePermissions reason: Document access; data only. @@ -169,39 +157,33 @@ source_revision: a53b46392c 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: + 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: + 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: + 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-privilege-escalation/aws-eventbridge-privesc/README.md#eventsupdateapidestination--redirect-stored-connection-credentials - source_revision: a53b46392c - technique: events:UpdateApiDestination - reason: Exfiltrates third-party API credentials from a connection; not an IAM principal. -- 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: + 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: a53b46392c 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-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkdescribeenvironmentresources-elasticloadbalancingmodifyloadbalancerattributes-s3putbucketpolicy-s3listbucket-s3getobject-to-enable-alb-access-logs-exfiltration - source_revision: a53b46392c - 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: + 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: + 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. @@ -209,11 +191,13 @@ source_revision: a53b46392c technique: lambda:AddPermission (alone) reason: Grants invoke on existing fixed code; no control of code or role. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#expose-a-pre-existing-authtypenone-function-url +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#expose-a-pre-existing-authtypenone-function-url source_revision: a53b46392c 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-privilege-escalation/aws-lambda-privesc/README.md#lambdaaddlayerversionpermission +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaaddlayerversionpermission source_revision: a53b46392c technique: lambda:AddLayerVersionPermission reason: Shares layer code (read); data access. @@ -221,19 +205,23 @@ source_revision: a53b46392c technique: Lambda MitM reason: Requires prior code execution in the function; persistence/interception, not a new edge. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaputprovisionedconcurrencyconfig--trigger-initialization-without-invocation +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaputprovisionedconcurrencyconfig--trigger-initialization-without-invocation source_revision: a53b46392c technique: lambda:PutProvisionedConcurrencyConfig reason: Triggers init of fixed code; no control of code or role. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunction--download-a-function-deployment-package +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunction--download-a-function-deployment-package source_revision: a53b46392c technique: lambda:GetFunction reason: Data read. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunctionconfiguration--read-environment-variables +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunctionconfiguration--read-environment-variables source_revision: a53b46392c technique: lambda:GetFunctionConfiguration reason: Data read. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetlayerversion--download-layer-code +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetlayerversion--download-layer-code source_revision: a53b46392c technique: lambda:GetLayerVersion reason: Data read. @@ -241,63 +229,48 @@ source_revision: a53b46392c 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: + 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-privilege-escalation/aws-s3-privesc/README.md#s3putbucketpolicy - source_revision: a53b46392c - 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-privilege-escalation/aws-s3-privesc/README.md#s3getbucketacl-s3putbucketacl - source_revision: a53b46392c - 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-privilege-escalation/aws-s3-privesc/README.md#s3getobjectacl-s3putobjectacl - source_revision: a53b46392c - technique: s3:GetObjectAcl + s3:PutObjectAcl - reason: Object data access only. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3getobjectversionacl-s3putobjectversionacl - source_revision: a53b46392c - technique: s3:GetObjectVersionAcl + s3:PutObjectVersionAcl - reason: Object data access only. + 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-privilege-escalation/aws-s3-privesc/README.md#s3putbucketcors source_revision: a53b46392c technique: s3:PutBucketCORS reason: Browser cross-origin data access; no IAM principal. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreatepresignedmlflowtrackingserverurl-sagemaker-mlflowaccessui-sagemaker-mlflowsearchexperiments +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakercreatepresignedmlflowtrackingserverurl-sagemaker-mlflowaccessui-sagemaker-mlflowsearchexperiments source_revision: a53b46392c 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: + 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-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerstartpipelineexecution--inject-parameters-into-privileged-steps - source_revision: a53b46392c - technique: sagemaker:StartPipelineExecution - reason: Runs fixed pipeline steps with attacker parameters; no control of code or role. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerretrypipelineexecution--replay-failed-steps-and-stored-parameters +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerretrypipelineexecution--replay-failed-steps-and-stored-parameters source_revision: a53b46392c technique: sagemaker:RetryPipelineExecution reason: Replays fixed steps; no control of code or role. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#datazonecreateuserprofile-and-iamgetuser-for-project-assignment-without-an-existing-profile +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#datazonecreateuserprofile-and-iamgetuser-for-project-assignment-without-an-existing-profile source_revision: a53b46392c 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-privilege-escalation/aws-service-catalog-privesc/README.md#sensitive-cloudformation-outputs-with-servicecataloggetprovisionedproductoutputs - source_revision: a53b46392c - technique: servicecatalog:GetProvisionedProductOutputs - reason: Data read. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmstartassociationsonce--run-a-stored-association-on-its-fixed-targets +- 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: a53b46392c technique: ssm:StartAssociationsOnce reason: Runs fixed associations on fixed targets; no control of code or role. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmdescribeparameters-ssmgetparameter--ssmgetparameters--ssmgetparametersbypath +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmdescribeparameters-ssmgetparameter--ssmgetparameters--ssmgetparametersbypath source_revision: a53b46392c technique: ssm:GetParameter(s) reason: Data read. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmgetparameterhistory--recover-current-and-previous-parameter-values +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmgetparameterhistory--recover-current-and-previous-parameter-values source_revision: a53b46392c technique: ssm:GetParameterHistory reason: Data read. @@ -305,7 +278,8 @@ source_revision: a53b46392c technique: ssm:ListCommands reason: Data read. -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmgetcommandinvocation-ssmlistcommandinvocations--ssmlistcommands +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmgetcommandinvocation-ssmlistcommandinvocations--ssmlistcommands source_revision: a53b46392c technique: ssm:GetCommandInvocation reason: Data read. @@ -313,15 +287,25 @@ 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: + 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: + 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-privilege-escalation/aws-transfer-family-privesc/README.md#transferstartfiletransfer--send-role-readable-s3-data-through-a-stored-connector +- 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: a53b46392c technique: transfer:StartFileTransfer - reason: Data exfiltration through a fixed connector role (the role only reads/sends files the caller selects); data access. + reason: Data exfiltration through a fixed connector role (the role only reads/sends files the caller selects); data + access. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreatevirtualmfadevice-iamenablemfadevice-and-the-target-users-access-keys + technique: Enable attacker MFA device using already-held target access keys + reason: This variant needs possession of the target user’s live access keys before MFA enrolment. Secret possession is + runtime state outside the configuration snapshot; aws-iam-enable-attacker-mfa-device-other-user covers the distinct + configuration-decidable path where credential-minting permission exists. diff --git a/src/privilege-escalation-paths/aws/_excluded_refresh_g3.yaml b/src/privilege-escalation-paths/aws/_excluded_refresh_g3.yaml index 82baf4c662..cf7eeb9b33 100644 --- a/src/privilege-escalation-paths/aws/_excluded_refresh_g3.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_refresh_g3.yaml @@ -9,11 +9,15 @@ 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 +- 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 @@ -25,18 +29,11 @@ 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 +- 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-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: 171e422299 -- 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: 171e422299 - 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. @@ -45,23 +42,30 @@ 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 +- 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 +- 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-privilege-escalation/aws-cloud-control-handler-role-privesc/README.md#getresource--listresources--iampassrole--read-through-a-resource-handler-role +- 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.' + 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-proton-privesc/README.md#protoncreateenvironment-iampassrole--template-control +- 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. + 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 +- 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/aws/_excluded_refresh_g4.yaml b/src/privilege-escalation-paths/aws/_excluded_refresh_g4.yaml index ac61ca29ad..1a87484aec 100644 --- a/src/privilege-escalation-paths/aws/_excluded_refresh_g4.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_refresh_g4.yaml @@ -11,14 +11,18 @@ 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#athenaupdatepreparedstatement--poison-a-query-executed-by-another-principal +- 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." + 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-stored-query-privesc/README.md#athenaupdatenamedquery--poison-saved-sql-consumed-by-another-principal +- 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." + 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: 171e422299 - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-aurora-dsql-privesc/README.md#aurora-dsql @@ -26,12 +30,14 @@ reason: "Introductory section (links to enumeration); no technique." source_revision: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-aurora-dsql-privesc/README.md#dsqldbconnectadmin--database-administrator-access +- 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-aurora-dsql-privesc/README.md#dsqlputclusterpolicy--self-grant-database-administrator-access +- 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 @@ -41,19 +47,23 @@ 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 +- 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 +- 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-privilege-escalation/aws-bedrock-agentcore-privesc/README.md#credential-vend--getworkloadaccesstoken--getresourceapikey--getresourceoauth2token--steal-the-third-party-secrets-agents-use +- 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 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." + reason: "Vends third-party (SaaS/OAuth) secrets used by agents, not AWS principals; also needs secretsmanager:GetSecretValue + on the provider secret." source_revision: 171e422299 - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datazone-privesc/README.md#amazon-datazone @@ -61,9 +71,12 @@ 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 +- 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." + 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 @@ -71,17 +84,13 @@ 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 +- 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 @@ -96,49 +105,61 @@ 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 +- 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 +- 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 +- 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." + 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 +- 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 +- 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." + 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 +- 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-privilege-escalation/aws-managed-flink-privesc/README.md#add-private-network-reach-without-ec2-permission +- 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#iam-identity-center--sso +- 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 +- 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 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 @@ -148,15 +169,19 @@ - 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." + 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." + 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 +- 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." + 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/aws/_excluded_refresh_g5.yaml b/src/privilege-escalation-paths/aws/_excluded_refresh_g5.yaml index 3dcfa00fdd..1642902921 100644 --- a/src/privilege-escalation-paths/aws/_excluded_refresh_g5.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_refresh_g5.yaml @@ -7,22 +7,23 @@ technique: AppFlow 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-appflow-privesc/README.md#redshift-and-custom-connector-boundaries +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appflow-privesc/README.md#redshift-and-custom-connector-boundaries 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.' + 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#appsyncupdategraphqlapi--appsynccreateapikey +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#appsyncupdategraphqlapi--appsynccreateapikey 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.' + reason: 'Switches the API''s primary auth to API_KEY: application-level data access through existing resolvers, not an AWS + principal escalation.' source_revision: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudwatch-omni-privesc/README.md#cloudwatch-omni +- 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-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: 171e422299 - 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. @@ -31,15 +32,18 @@ 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 +- 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 +- 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 +- 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 @@ -47,31 +51,27 @@ 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 +- 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-privilege-escalation/aws-kinesis-data-streams-privesc/README.md#createchannel--associatestreamswithchannel--iampassrole +- 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.' + 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-mq-privesc/README.md#mqupdateconfiguration-mqupdatebroker-mqcreateusermqupdateuser +- 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 +- 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. @@ -80,11 +80,14 @@ 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 +- 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 +- 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: 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/aws/_excluded_refresh_g6.yaml b/src/privilege-escalation-paths/aws/_excluded_refresh_g6.yaml index 3160131d54..e8e1337784 100644 --- a/src/privilege-escalation-paths/aws/_excluded_refresh_g6.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_refresh_g6.yaml @@ -1,31 +1,38 @@ # 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 +- 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. + 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 +- 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 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 +- 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: 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-privilege-escalation/aws-cognito-user-pools-privesc/README.md#emailusername-modification-privesc +- 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. + reason: Application-level impersonation when the app trusts unverified claims; no IAM permission and no AWS principal + reached. source_revision: 171e422299 - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-datasync-privesc/README.md#aws-datasync 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-directory-services-privesc/README.md#directory-services--workdocs +- 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 @@ -33,15 +40,12 @@ 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#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: 171e422299 - 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-privilege-escalation/aws-memorydb-user-reset-privesc/README.md#post-exploitation-replace-an-acl-users-password-with-memorydbupdateuser +- 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: 171e422299 @@ -49,59 +53,78 @@ 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-odb-privesc/README.md#odbupdateautonomousdatabase--reset-the-oracle-admin-credential-and-weaken-connection-controls +- 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-opensearch-serverless-privesc/README.md#opensearch-service +- 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 +- 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: 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 +- 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 +- 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. + 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 +- 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. + 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 +- 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 +- 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). + 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 +- 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 +- 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. + 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 +- 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. + 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 +- 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 +- 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 @@ -109,7 +132,8 @@ 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-route53-domains-privesc/README.md#route53domainstransferdomaintoanotherawsaccount--transfer-domain-registration-to-an-attacker-account +- 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: 171e422299 @@ -117,9 +141,12 @@ 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-credential-brokers-privesc/README.md#s3-express-and-s3-access-grants-credential-brokers +- 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. + 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: 171e422299 - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-files-privesc/README.md#s3-files technique: Section introduction @@ -129,43 +156,44 @@ 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-privilege-escalation/aws-snowball-privesc/README.md#snowball-edge-job-management +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-snowball-privesc/README.md#snowball-edge-job-management 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#aws-transfer-family +- 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 +- 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). + 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 +- 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 +- 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). + 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-privilege-escalation/aws-verified-permissions-privesc/README.md#redirect-token-trust-with-updateidentitysource +- 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-verified-permissions-privesc/README.md#rebind-a-policy-store-alias-to-a-permissive-store +- 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: 171e422299 diff --git a/src/privilege-escalation-paths/aws/_excluded_refresh_g7.yaml b/src/privilege-escalation-paths/aws/_excluded_refresh_g7.yaml index 69f124a90d..5bf8bc89ce 100644 --- a/src/privilege-escalation-paths/aws/_excluded_refresh_g7.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_refresh_g7.yaml @@ -7,14 +7,17 @@ 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 +- 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.' + 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 +- 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. + 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 @@ -32,11 +35,13 @@ technique: Chime SDK reason: Service introduction pointing to the enumeration page; no technique. source_revision: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md#chimecreatemediacapturepipeline--optional-iampassrole +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md#chimecreatemediacapturepipeline--optional-iampassrole 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-cases-privesc/README.md#casestagresource--casesuntagresource-plus-tag-conditioned-cases-permissions +- 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: Changes tag-conditioned access to Connect Cases data; data access only, no other principal obtained. source_revision: 171e422299 @@ -44,31 +49,32 @@ 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 +- 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-privilege-escalation/aws-entity-resolution-privesc/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.' + 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: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift-streams-privesc/README.md#gamelift-streams +- 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-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. + 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: 171e422299 -- 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 +- 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 @@ -76,19 +82,24 @@ 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 +- 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). + 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 +- 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 +- 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 +- 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 @@ -98,9 +109,11 @@ source_revision: 171e422299 - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-timestream-privesc/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. + reason: Scheduled-query roles only run Timestream SQL and write to Timestream/SNS/S3 error reports; bounded data + delegation. source_revision: 171e422299 -- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#directory-services--workdocs +- 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 diff --git a/src/privilege-escalation-paths/aws/_excluded_v4.yaml b/src/privilege-escalation-paths/aws/_excluded_v4.yaml new file mode 100644 index 0000000000..43237c64e9 --- /dev/null +++ b/src/privilege-escalation-paths/aws/_excluded_v4.yaml @@ -0,0 +1,277 @@ +- 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: CDK source poisoning needs a later deployment and a repository-to-deployment join. AWS CodeCommit GitPush to a + pipeline source is covered by aws-codecommit-gitpush-pipeline-source and + aws-codecommit-gitpush-pipeline-source-cloudformation-role; external SCM writes require external repository access + absent from the AWS snapshot. +- 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: The view can expose raw telemetry, including credentials if a particular log or trace record contains them. + Configuration of the view and Dataset grants alone cannot establish a usable secret; actual record content and + credential validity are runtime/content facts. No AWS principal credential edge can be emitted from configuration + alone. + source_revision: 171e422299 +- 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: StartChatContact on the exact flow/contact resources can invoke associated Lambda or Lex operations. + Escalation depends on the flow and backend code trusting attacker-controlled attributes or messages and performing a + privileged action; flow configuration alone does not prove that behavior or arbitrary use of the Lambda role. + Backend semantics and response content are required for a principal edge. + source_revision: 171e422299 +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-customer-profiles-privesc/README.md#associatestreamforsegments--iampassrole + technique: profile:AssociateStreamForSegments + iam:PassRole + reason: Bounded Kinesis delivery via a passed role; association alone does not deliver and no full role session is + gained. A bounded delegated-operation target is needed; do not infer a full role session. + source_revision: 171e422299 +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-customer-profiles-privesc/README.md#createintegrationworkflow--iampassrole + technique: profile:CreateIntegrationWorkflow + iam:PassRole + reason: Bounded AppFlow/S3/KMS integration setup via a passed role; no full role session is gained. A bounded + delegated-operation target is needed; do not infer a full role session. + source_revision: 171e422299 +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-customer-profiles-privesc/README.md#createsegmentsnapshot--iampassrole + technique: profile:CreateSegmentSnapshot + iam:PassRole + reason: Bounded segment export to S3/KMS via a passed role; no full role session is gained. A bounded + delegated-operation target is needed; do not infer a full role session. + 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: Read-scoped fleet-role credentials are returned, but a full-role graph edge would overstate effective + permissions. + 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: UpdateCluster resets a PLAIN_TEXT Elastic cluster admin password; cluster-admin target and cluster facts are + unsupported. A service-plane identity target is needed. + source_revision: 171e422299 +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md#dynamodbputresourcepolicy-and-optionally-dynamodbgetresourcepolicy + technique: dynamodb:PutResourcePolicy + reason: PutResourcePolicy grants actions on one DynamoDB table, not all permissions of the named principal. A + resource-scoped privilege target is needed. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ebs-privesc/README.md#ec2createsnapshot + technique: ec2:CreateSnapshot + reason: CreateSnapshot alone does not yield AD credentials; DC disk content, mount/read, and hash extraction are + required. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2describelaunchtemplateversions-ec2describelaunchtemplates-optional + technique: ec2:DescribeLaunchTemplateVersions + reason: Launch-template UserData may contain a live IAM key, but permission alone cannot establish its contents or + validity. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2modifyimageattribute-ec2modifysnapshotattribute + technique: ec2:ModifyImageAttribute / ModifySnapshotAttribute + reason: AMI/snapshot sharing exposes contents; a live embedded credential and recipient extraction are needed for + identity gain. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrgetauthorizationtoken-ecrbatchgetimage-ecrgetdownloadurlforlayer + technique: ECR image pull + reason: ECR pull yields another identity only when a retrievable layer contains a live credential. +- 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: The section demonstrates attacker-created EXTERNAL tasks, covered by + aws-ecs-passrole-registertaskdefinition-runtask; it does not show forced placement of existing victim tasks on the + attacker host. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemclientmount-and-client-action-combinations + source_revision: a53b46392c + technique: elasticfilesystem:ClientMount / ClientWrite / ClientRootAccess combinations + reason: ClientWrite/ClientRootAccess add bounded EFS filesystem privileges beyond ClientMount, not a full AWS role. A + resource-scoped privilege target is needed. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemcreateaccesspoint--elasticfilesystemclientmount + source_revision: a53b46392c + technique: elasticfilesystem:CreateAccessPoint + ClientMount + reason: An access point can choose UID/GID and cross POSIX modes on one filesystem/path. A resource-scoped privilege + target is needed. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-efs-privesc/README.md#elasticfilesystemdeletefilesystempolicyelasticfilesystemputfilesystempolicy + source_revision: a53b46392c + technique: elasticfilesystem:DeleteFileSystemPolicy / PutFileSystemPolicy + reason: EFS policy mutation can grant client actions on one filesystem, not global AWS permissions. A resource-scoped + privilege target is needed. +- 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: a53b46392c + technique: ALB access-log exfiltration + reason: ALB log redirection may capture tokens, but future URL contents and token validity are not in configuration. +- 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: ModifyUser resets and widens an attached cache RBAC identity; the evidence-gated challenge-v3 record does not + evaluate this configuration path. A service-plane identity target is needed. + source_revision: 171e422299 +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsputpermission--self-grant-publishing-through-a-bus-policy + technique: events:PutPermission + reason: PutPermission can add a durable event-bus resource-policy Allow for events:PutEvents to the caller or another + principal. This grants bus publishing authority, but no AWS principal or target-role execution follows without a + matching rule, authorized target, and event. A service-resource permission target and exact + bus-policy/effective-permission join are needed before this is a catalog edge. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eventbridge-privesc/README.md#eventsupdateapidestination--redirect-stored-connection-credentials + technique: events:UpdateApiDestination + reason: Changing a destination endpoint can expose its retained Connection API-key, Basic or OAuth credential to the + new HTTPS endpoint on a later matching event. This is a reusable external credential, but the catalog lacks an + external-service identity target and the destination-to-Connection plus event-delivery facts; do not infer exposure + from UpdateApiDestination permission alone. +- 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 + technique: Create an enhanced-bus subscriber with a universal target and a passed role + reason: The current entry checks events:CreateSubscriber on * and can match a different bus. A valid role edge needs + authorization on the same enhanced-bus ARN and the future name-scoped subscriber ARN, exact-role iam:PassRole, a + supported universal target, and a retained/live matching event. Until a joint bus/subscriber resource evaluator + exists, this path cannot produce a false-positive-free catalog edge. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-gamelift-streams-privesc/README.md#gameliftstreamscreatestreamsessionadminshell-on-a-session-with-a-role + technique: Open an admin shell in a live stream session that has a role + reason: CreateStreamSessionAdminShell is authorized on the parent stream-group ARN. The current wildcard grant can + match an unrelated group; a valid edge needs a live role-bearing session joined to its exact parent stream group and + authorization on that group. Session inventory is not currently collected, so the role target must remain UNKNOWN. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamsetdefaultpolicyversion + technique: Switch the default version of a customer-managed policy attached to the source + reason: SetDefaultPolicyVersion escalates only if a non-default version of the same attached customer-managed policy + grants permissions the source lacks. The current account-admin target assumes such a version without reading and + comparing its document. Collect ListPolicyVersions and GetPolicyVersion for the exact attached policy and evaluate + the candidate version before restoring a role/permission edge. +- 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 + technique: Move another user into an IAM path where the source's credential permissions already apply + reason: The current rule matches CreateAccessKey/CreateLoginProfile/UpdateLoginProfile on any user ARN, even when it + cannot cover the same user after its path changes. A valid edge must choose one new path and verify UpdateUser on + both old and resulting ARN plus the follow-up permission on that resulting ARN; credential state or group membership + must also permit the final step. +- 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 + technique: Move a group into an IAM path where the source can add members + reason: The current rule matches AddUserToGroup on any group ARN, even when it cannot cover the same group after its + path changes. A valid edge must choose one new path and verify UpdateGroup on both old and resulting ARN plus the + follow-up permission on that resulting ARN; credential state or group membership must also permit the final step. +- 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: This can activate previously masked Billing console permissions for IAM identities with existing Billing + policy grants. A definite finding requires the preference to be disabled before the change and an exact + affected-principal/effective-policy join; the preference does not itself create IAM grants or affect Billing SDK + APIs. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lightsail-privesc/README.md#lightsailupdatecontainerservice + source_revision: a53b46392c + technique: lightsail:UpdateContainerService + reason: UpdateContainerService only activates the ECR image-puller role. Private repository authorization and a + separate ability to control or observe the workload are required; no identity or code control follows from this + action alone. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-macie-privesc/README.md#amazon-macie---bypass-reveal-sample-integrity-check + source_revision: a53b46392c + technique: Macie reveal-sample integrity bypass + reason: 'Historical sample integrity bypass is not a current escalation: the ETag/content-match check rejects a deleted + or replaced S3 object. A current bypass and credential-bearing sample would need independent verification.' +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + technique: finspace:CreateKxCluster + iam:PassRole (historical) + reason: AWS FinSpace ended support on 2026-10-07; no current environment or role execution exists. Historical only. + https://docs.aws.amazon.com/finspace/latest/management-api/amazon-finspace-end-of-support.html +- 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: Setting iamRole on a FinSpace Kx user does not vend the role credentials; the connecting identity must already + assume that role. FinSpace ended support on 2026-10-07. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3putbucketpolicy + source_revision: a53b46392c + technique: s3:PutBucketPolicy + reason: Same-account PutBucketPolicy may self-grant bucket/object actions, but this is resource-scoped access. Object + contents or a privileged consumer must be known to infer another principal; Block Public Access and explicit denies + can block the grant. Do not infer unconditional PutObject. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3getbucketacl-s3putbucketacl + source_revision: a53b46392c + technique: s3:GetBucketAcl + s3:PutBucketAcl + reason: PutBucketAcl can grant bucket ACL rights when ACLs are enabled, but this is resource-scoped access. Object + Ownership and Block Public Access may reject it; no other principal or code consumer follows from the ACL alone. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3getobjectacl-s3putobjectacl + source_revision: a53b46392c + technique: s3:GetObjectAcl + s3:PutObjectAcl + reason: PutObjectAcl can grant access to one object when ACLs are enabled. Whether that object contains credentials or + executable code consumed by a stronger principal requires contents and consumer facts absent from the snapshot. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-s3-privesc/README.md#s3getobjectversionacl-s3putobjectversionacl + source_revision: a53b46392c + technique: s3:GetObjectVersionAcl + s3:PutObjectVersionAcl + reason: PutObjectVersionAcl can grant access to one historical version when ACLs are enabled. Whether the version has + a still-valid credential requires version contents and credential validity facts absent from the snapshot. +- 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: PutTablePolicy or PutTableBucketPolicy can self-grant table read/write and management actions within the + table-bucket boundary. This resource-scoped grant does not yield another principal or unrelated IAM privileges. + 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: PutVectorBucketPolicy can self-grant vector read/write and index management within the vector-bucket boundary. + This resource-scoped grant does not yield another principal; explicit denies and KMS access still apply. + source_revision: 171e422299 +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sagemaker-privesc/README.md#sagemakerstartpipelineexecution--inject-parameters-into-privileged-steps + source_revision: a53b46392c + technique: sagemaker:StartPipelineExecution + reason: StartPipelineExecution overrides parameter values. Privileged effects require a pipeline definition and step + code that pass those values into a sensitive command, resource or destination without safe validation; IAM + permission alone does not establish that data flow. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-secrets-manager-privesc/README.md#secretsmanagergetresourcepolicy-secretsmanagerputresourcepolicy-secretsmanagerlistsecrets + source_revision: a53b46392c + technique: secretsmanager:PutResourcePolicy + reason: PutResourcePolicy can self-grant secret read to a same-account IAM user. Another identity follows only if the + secret contains a live usable credential and KMS allows decrypt; policy metadata alone does not reveal those facts. +- source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-service-catalog-privesc/README.md#sensitive-cloudformation-outputs-with-servicecataloggetprovisionedproductoutputs + source_revision: a53b46392c + technique: servicecatalog:GetProvisionedProductOutputs + reason: GetProvisionedProductOutputs returns data. Another identity follows only if an output is a live credential + accepted by a target system; output contents and validity are absent from the configuration snapshot. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc/README.md#snssubscribe + source_revision: a53b46392c + technique: sns:Subscribe + reason: Subscribe can attach a Lambda endpoint as a later trigger, but the function must admit the topic, a later + publish must occur, and unchanged code must perform a sensitive effect; those runtime and code facts are not + established by Subscribe. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc/README.md#snsaddpermission + source_revision: a53b46392c + technique: sns:AddPermission + reason: AddPermission grants selected SNS actions to an account on this topic. The page documents topic + access/manipulation, not another principal or credential beyond topic-scoped permissions. +- 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: SetTopicAttributes can grant a same-account user Subscribe on this topic and future message delivery. This + resource-scoped grant does not itself identify a credential or another principal. + source_revision: 171e422299 +- 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: A wildcard SNS source permission can permit Lambda invocation, but attacker messages run unchanged code. A + privileged effect requires function code and runtime data-flow evidence not established by the policy alone. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sqs-privesc/README.md#sqsaddpermission + source_revision: a53b46392c + technique: sqs:AddPermission + reason: AddPermission grants selected SQS actions to an account on this queue. The page documents queue + access/manipulation only; no second identity follows without credential-bearing message contents. +- 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: SetQueueAttributes can grant a same-account user ReceiveMessage on this queue. This resource-scoped grant does + not identify a live credential in its messages. + source_revision: 171e422299 diff --git a/src/privilege-escalation-paths/aws/amplify.yaml b/src/privilege-escalation-paths/aws/amplify.yaml index b2f1efa6b1..2188410058 100644 --- a/src/privilege-escalation-paths/aws/amplify.yaml +++ b/src/privilege-escalation-paths/aws/amplify.yaml @@ -1,20 +1,111 @@ # AWS Amplify privilege escalation techniques. # Source: hacktricks-cloud aws-amplify-privesc/README.md. +- 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: amplify:GetApp + resource: "{target.resource_arn}" + - 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)] + conditions: + - id: gen1_backend_with_studio + description: The app must have an existing Amplify Gen 1 backend with Studio (Admin UI) enabled; the backend + environment name must be known to open the session. + 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 the collected amplify_app entries with Gen 1 backend environments + (amplify:ListBackendEnvironments); accounts whose apps or backend environments were not collected keep one + unresolved placeholder. amplify:GetApp is authorized on the app ARN + (arn:aws:amplify:::apps/, {target.resource_arn}); amplifybackend:CreateToken is authorized + on the Amplify Admin token resource arn:aws:amplifybackend:::/backend//challenge/* + ({target.amplifybackend_token_arn}). Source - the Service Authorization Reference JSON + (servicereference.us-east-1.amazonaws.com/v1/amplifybackend), verified 2026-10-11; CreateToken/GetToken list both + the backend resource arn::amplifybackend:::/backend//* + ({target.amplifybackend_backend_arn}) and the token resource + arn::amplifybackend:::/backend//challenge/* ({target.amplifybackend_token_arn}), + so both are required. + +- id: aws-amplifybackend-gettoken-studio-admin + provider: aws + service: amplifybackend + title: Recover a live Amplify Studio administrator login + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetapp-amplifybackendgettoken--recover-a-live-studio-login + source_revision: 171e422299 + summary: The source can hijack an existing Amplify Studio application-administration session of a Gen 1 backend when + it knows a live session id. + requires: + all_of: + - action: amplify:GetApp + resource: "{target.resource_arn}" + - action: amplifybackend:GetToken + resource: "{target.amplifybackend_token_arn}" + - action: amplifybackend:GetToken + 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)] + conditions: + - id: live_session + description: A live, unexpired Studio login session id must be known (CloudTrail redacts it; it leaks only through + URLs, browser history or logs). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict amplifybackend:GetToken, keep Studio login URLs out of logs and shared artifacts, and delete + unused tokens. + notes: Application-plane administration only; not IAM credentials. Targets are the collected amplify_app entries with + Gen 1 backend environments; accounts without them collected keep an unresolved placeholder. amplify:GetApp is on the + app ARN and amplifybackend:GetToken on the token resource + arn:aws:amplifybackend:::/backend//challenge/* ({target.amplifybackend_token_arn}). Source - + the Service Authorization Reference JSON (servicereference.us-east-1.amazonaws.com/v1/amplifybackend), verified + 2026-10-11; CreateToken/GetToken list both the backend resource + arn::amplifybackend:::/backend//* ({target.amplifybackend_backend_arn}) and the + token resource arn::amplifybackend:::/backend//challenge/* + ({target.amplifybackend_token_arn}), so both are required. - id: aws-amplify-updateapp-startjob provider: aws service: amplify title: Change an Amplify app build specification and start a build - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifyupdateapp-amplifystartjob + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifyupdateapp-amplifystartjob source_revision: 6fb9ac51fd - summary: The source can obtain the privileges of the IAM service role attached to an Amplify app whose build it - can reconfigure and run. + summary: The source can obtain the privileges of the IAM service role attached to an Amplify app whose build it can + reconfigure and run. requires: all_of: - action: amplify:UpdateApp resource: '{target.attached_resource_arn}' - action: amplify:StartJob - resource: '{target.attached_resource_arn}' + resource: '*' target: kind: aws_role selector: @@ -25,25 +116,24 @@ outcome: workload_execution conditions: - id: app_has_service_role - description: The app must have an IAM service role configured (trusting amplify.amazonaws.com); otherwise builds - run without AWS permissions. + description: The app must have an IAM service role configured (trusting amplify.amazonaws.com); otherwise builds run + without AWS permissions. blockers: - scp_or_boundary_deny - confidence: derived + confidence: conditional severity: critical mitigation: Restrict amplify:UpdateApp/UpdateBranch and StartJob; keep Amplify service roles least-privileged. references: - https://docs.aws.amazon.com/amplify/latest/userguide/how-to-service-role-amplify-console.html - notes: StartJob Resource is the branch ARN (app ARN prefix); the evaluator should treat app-ARN wildcards as covering - branches. amplify:UpdateBranch can be an equivalent build-spec change path. Severity critical when the attached - role is admin-equivalent. - - + notes: StartJob is authorized on branch jobs/*, distinct from the app/branch ARN. Resource:* is a conservative gate + until the evaluator can join exact app, branch and job ARNs; automatic builds or webhooks require a separate + observed trigger fact. - id: aws-amplify-updatebranch-startjob provider: aws service: amplify title: Change an Amplify branch's build environment variables and start a build - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifyupdatebranch-amplifystartjob--branch-scoped-build-code-execution + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifyupdatebranch-amplifystartjob--branch-scoped-build-code-execution source_revision: 6fb9ac51fd summary: The source can obtain the privileges of the IAM service role of an Amplify app whose branch build environment it can change and build. @@ -52,7 +142,7 @@ - action: amplify:UpdateBranch resource: '{target.attached_resource_arn}' - action: amplify:StartJob - resource: '{target.attached_resource_arn}' + resource: '*' target: kind: aws_role selector: @@ -63,123 +153,156 @@ outcome: workload_execution conditions: - id: app_has_service_role - description: The app must have an IAM service role configured (trusting amplify.amazonaws.com); otherwise builds - run without AWS permissions. + description: The app must have an IAM service role configured (trusting amplify.amazonaws.com); otherwise builds run + without AWS permissions. - id: runtime_honours_startup_variable - description: The existing build must start an interpreter that loads a startup environment variable pointing - at content reachable in the build workspace; a branch buildSpec override was observed not to be executed. + description: The existing build must start an interpreter that loads a startup environment variable pointing at + content reachable in the build workspace; a branch buildSpec override was observed not to be executed. - id: trigger description: Automatic builds or an incoming webhook can replace amplify:StartJob as the trigger. blockers: - scp_or_boundary_deny confidence: conditional severity: critical - mitigation: Restrict amplify:UpdateBranch, amplify:UpdateApp and amplify:StartJob to deployment administrators - and keep Amplify service roles least-privileged. + mitigation: Restrict amplify:UpdateBranch, amplify:UpdateApp and amplify:StartJob to deployment administrators and + keep Amplify service roles least-privileged. references: - https://docs.aws.amazon.com/amplify/latest/userguide/how-to-service-role-amplify-console.html - notes: Branch ARNs are under the app ARN; the evaluator should treat app-ARN wildcards as covering branches and - jobs. No iam:PassRole is needed when the existing service role is reused. Severity critical when the attached - role is admin-equivalent. - - + notes: StartJob is authorized on branch jobs/*, distinct from the app/branch ARN. Resource:* is a conservative gate + until the evaluator can join exact app, branch and job ARNs; automatic builds or webhooks require a separate + observed trigger fact. - 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 + title: Repoint an Amplify app service role and start a 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 can execute a controlled build under a passable role assigned as the app service role. requires: all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: amplify:UpdateApp - resource: "*" - - action: amplify:StartJob - resource: "*" + - action: iam:PassRole + resource: '{target.arn}' + - 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}" + 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. + - id: controlled_build + description: An existing app must be updatable and run attacker-controlled build code under the passed service role. blockers: - - scp_or_boundary_deny + - 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. + 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 + - 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: StartJob Resource:* is conservative until app/branch/jobs ARN joins are supported; automatic triggers need an + observed trigger fact. SSR compute role is a separate path and does not require StartJob. +- id: aws-amplify-updateapp-passrole-ssr 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 + 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 obtain an Amplify Studio application-administration session over the data model, auth and configuration of Gen 1 backends it can mint Studio logins for. + summary: The source can execute controlled SSR code as a passable compute role of an updatable app. requires: all_of: - - action: amplify:GetApp - resource: "{target.resource_arn}" - - action: amplifybackend:CreateToken - resource: "{target.amplifybackend_token_arn}" - - action: amplifybackend:CreateToken - resource: "{target.amplifybackend_backend_arn}" + - action: iam:PassRole + resource: '{target.arn}' + - action: amplify:UpdateApp + resource: '*' target: - kind: aws_service_plane_admin + kind: aws_role selector: - service_plane: amplifybackend + trust_allows_service: amplify.amazonaws.com + resource_permission_covers_target: iam:PassRole scope: same_account - aggregate_as: "Amplify Studio administrators in {account}" - grants: [Amplify Studio administrator (aws-amplify-admin)] + aggregate_as: Roles trusting amplify.amazonaws.com passable in {account} + outcome: workload_execution conditions: - - id: gen1_backend_with_studio - description: The app must have an existing Amplify Gen 1 backend with Studio (Admin UI) enabled; the backend environment name must be known to open the session. + - 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 + - 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. +- id: aws-amplify-config-credential + provider: aws + service: amplify + title: Read plaintext variables and build-log URLs that may contain credentials + 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 + source_revision: 0b36331 + summary: A verified exposed AWS credential for another principal can be read by the source. + requires: + all_of: + - action: amplify:GetApp + resource: '*' + - action: amplify:GetBranch + resource: '*' + - action: amplify:GetJob + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-amplify-config-credential + scope: same_account + conditions: + - id: verified_evidence + description: The exact usable credential and its newly reachable owner, or service-plane administrator grant, must + be verified; absent evidence yields UNKNOWN. + - 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 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 the collected amplify_app entries with Gen 1 backend environments (amplify:ListBackendEnvironments); accounts whose apps or backend environments were not collected keep one unresolved placeholder. amplify:GetApp is authorized on the app ARN (arn:aws:amplify:::apps/, {target.resource_arn}); amplifybackend:CreateToken is authorized on the Amplify Admin token resource arn:aws:amplifybackend:::/backend//challenge/* ({target.amplifybackend_token_arn}). Source - the Service Authorization Reference JSON (servicereference.us-east-1.amazonaws.com/v1/amplifybackend), verified 2026-10-11; CreateToken/GetToken list both the backend resource arn::amplifybackend:::/backend//* ({target.amplifybackend_backend_arn}) and the token resource arn::amplifybackend:::/backend//challenge/* ({target.amplifybackend_token_arn}), so both are required. - -- id: aws-amplifybackend-gettoken-studio-admin + mitigation: Restrict the listed action to approved operators and protect exposed credentials. + notes: Required collector evidence is absent from current snapshots; missing evidence remains UNKNOWN/unresolved. +- id: aws-amplify-artifact-credential provider: aws - service: amplifybackend - title: Recover a live Amplify Studio administrator login - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetapp-amplifybackendgettoken--recover-a-live-studio-login - source_revision: 171e422299 - summary: The source can hijack an existing Amplify Studio application-administration session of a Gen 1 backend when it knows a live session id. + service: amplify + title: Download E2E artifacts that may contain tokens + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-amplify-privesc/README.md#amplifygetartifacturl--download-end-to-end-test-artifacts + source_revision: 0b36331 + summary: A verified exposed AWS credential for another principal can be read by the source. requires: all_of: - - action: amplify:GetApp - resource: "{target.resource_arn}" - - action: amplifybackend:GetToken - resource: "{target.amplifybackend_token_arn}" - - action: amplifybackend:GetToken - resource: "{target.amplifybackend_backend_arn}" + - action: amplify:GetArtifactUrl + resource: '*' target: - kind: aws_service_plane_admin + kind: aws_verified_authority selector: - service_plane: amplifybackend + aws_challenge_fact: aws-amplify-artifact-credential scope: same_account - aggregate_as: "Amplify Studio administrators in {account}" - grants: [Amplify Studio administrator (aws-amplify-admin)] conditions: - - id: live_session - description: A live, unexpired Studio login session id must be known (CloudTrail redacts it; it leaks only through URLs, browser history or logs). - blockers: - - scp_or_boundary_deny + - id: verified_evidence + description: The exact usable credential and its newly reachable owner, or service-plane administrator grant, must + be verified; absent evidence yields UNKNOWN. + - 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 amplifybackend:GetToken, keep Studio login URLs out of logs and shared artifacts, and delete unused tokens. - notes: Application-plane administration only; not IAM credentials. Targets are the collected amplify_app entries with Gen 1 backend environments; accounts without them collected keep an unresolved placeholder. amplify:GetApp is on the app ARN and amplifybackend:GetToken on the token resource arn:aws:amplifybackend:::/backend//challenge/* ({target.amplifybackend_token_arn}). Source - the Service Authorization Reference JSON (servicereference.us-east-1.amazonaws.com/v1/amplifybackend), verified 2026-10-11; CreateToken/GetToken list both the backend resource arn::amplifybackend:::/backend//* ({target.amplifybackend_backend_arn}) and the token resource arn::amplifybackend:::/backend//challenge/* ({target.amplifybackend_token_arn}), so both are required. + mitigation: Restrict the listed action to approved operators and protect exposed credentials. + notes: Required collector evidence is absent from current snapshots; missing evidence remains UNKNOWN/unresolved. diff --git a/src/privilege-escalation-paths/aws/apigateway.yaml b/src/privilege-escalation-paths/aws/apigateway.yaml index 795184acb2..d00fb2fb9d 100644 --- a/src/privilege-escalation-paths/aws/apigateway.yaml +++ b/src/privilege-escalation-paths/aws/apigateway.yaml @@ -1,38 +1,4 @@ # AWS API Gateway privilege escalation techniques. # Source: hacktricks-cloud aws-apigateway-privesc/README.md. -- id: aws-apigateway-integration-credentials-passrole - provider: aws - service: apigateway - title: Create a REST API AWS-service integration that runs with a passed credentials role - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apigateway-privesc/README.md#apigatewayput-apigatewaypost-and-sometimes-iampassrole - source_revision: 171e422299 - summary: The source can obtain the privileges of passable roles trusting apigateway.amazonaws.com by using them as the execution credentials of an AWS-service integration it can invoke. - requires: - all_of: - - action: apigateway:PUT - resource: "*" - - action: apigateway:POST - resource: "*" - - action: iam:PassRole - resource: "{target.arn}" - target: - kind: aws_role - selector: - trust_allows_service: apigateway.amazonaws.com - resource_permission_covers_target: iam:PassRole - scope: same_account - aggregate_as: "Roles trusting apigateway.amazonaws.com in {account}" - conditions: - - id: integration_action_limited - description: An AWS-service integration calls one configured service action per integration; the source can create several, but reachable actions are those exposed by AWS integrations, so effective privilege is close to but not always fully the role's. - - id: deployment_or_testinvoke - description: The integration must be invoked, which needs a deployment (POST) or apigateway test invocation; resource policies or authorizers on existing APIs do not apply to new APIs the source creates. - blockers: - - scp_or_boundary_deny - confidence: conditional - severity: medium - mitigation: Restrict iam:PassRole for apigateway.amazonaws.com roles and apigateway write actions to API administrators. - references: - - https://docs.aws.amazon.com/apigateway/latest/developerguide/integrating-api-with-aws-services-s3.html - notes: HackTricks demonstrates the Lambda AWS_PROXY integration, where the credentials role is only used to invoke the chosen function and does not hand the caller the function's execution role; reach beyond that relies on an AWS-service integration URI calling other service actions with the same credentials role, hence conditional and medium severity. Existing integrations already holding a role are reachable with PATCH+POST without PassRole (role attached to an integration); the evaluator may model that as attached_resource_covered_by apigateway:PATCH. +[] diff --git a/src/privilege-escalation-paths/aws/appconfig.yaml b/src/privilege-escalation-paths/aws/appconfig.yaml index 787b9b81cc..043d748f5d 100644 --- a/src/privilege-escalation-paths/aws/appconfig.yaml +++ b/src/privilege-escalation-paths/aws/appconfig.yaml @@ -1,47 +1,4 @@ # AWS appconfig privilege escalation techniques. # Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). -- id: aws-appconfig-passrole-createconfigurationprofile - provider: aws - service: appconfig - title: Read another service's data through a passed AppConfig retrieval role - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appconfig-privesc/README.md#appconfigcreateconfigurationprofile--iampassrole--deploymentread-permissions - source_revision: 6fb9ac51fd - summary: The source can exercise the read privileges of a passable role trusting appconfig.amazonaws.com over Secrets Manager secrets, Parameter Store parameters, SSM documents or S3 objects by making it the retrieval role of an external-source configuration profile it deploys and reads. - requires: - all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: appconfig:CreateConfigurationProfile - resource: "*" - - action: appconfig:StartDeployment - resource: "*" - - action: appconfig:StartConfigurationSession - resource: "*" - - action: appconfig:GetLatestConfiguration - resource: "*" - target: - kind: aws_role - selector: - trust_allows_service: appconfig.amazonaws.com - resource_permission_covers_target: iam:PassRole - scope: same_account - aggregate_as: "Roles trusting appconfig.amazonaws.com passable in {account}" - outcome: impersonation - conditions: - - id: bounded_read - description: AppConfig uses the retrieval role only to fetch the configured source; the source obtains that source's content, not a role session or arbitrary API calls. - - id: known_source_and_version - description: The secret, parameter, document or object ARN and a deployable version must be known, and an existing application, environment and deployment strategy must be in scope of the AppConfig actions. - - id: kms_decrypt - description: The retrieval role also needs kms:Decrypt on the source's customer-managed key when one is used. - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict which roles can be passed. - blockers: - - scp_or_boundary_deny - confidence: conditional - severity: medium - mitigation: Restrict iam:PassRole on AppConfig retrieval roles with iam:PassedToService and exact role ARNs, scope each retrieval role to its own configuration sources, and limit external-source configuration profile creation to AppConfig administrators. - references: - - https://docs.aws.amazon.com/appconfig/latest/userguide/appconfig-creating-configuration-and-profile.html - notes: Bounded impact - delegated data read of what the retrieval role can read, not a role session (same modelling as the DataSync bounded PassRole entries). Replaces the exclusion of this heading. +[] diff --git a/src/privilege-escalation-paths/aws/appflow.yaml b/src/privilege-escalation-paths/aws/appflow.yaml index 12d75234a9..f043475c6a 100644 --- a/src/privilege-escalation-paths/aws/appflow.yaml +++ b/src/privilege-escalation-paths/aws/appflow.yaml @@ -1,44 +1,4 @@ # AWS appflow privilege escalation techniques. # Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). -- id: aws-appflow-passrole-glue-catalog - provider: aws - service: appflow - title: Use a passed AppFlow role to create or update Glue Data Catalog tables - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appflow-privesc/README.md#createflowupdateflow--iampassrole-to-aws-glue-catalog-authority - source_revision: 6fb9ac51fd - summary: The source can exercise the Glue Data Catalog table and partition create/update privileges of a passable role trusting appflow.amazonaws.com by setting it as the metadata-catalog role of a flow it creates or updates and runs. - requires: - all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: appflow:StartFlow - resource: "*" - any_of: - - - action: appflow:CreateFlow - resource: "*" - - - action: appflow:UpdateFlow - resource: "*" - target: - kind: aws_role - selector: - trust_allows_service: appflow.amazonaws.com - resource_permission_covers_target: iam:PassRole - scope: same_account - aggregate_as: "Roles trusting appflow.amazonaws.com passable in {account}" - outcome: impersonation - conditions: - - id: bounded_catalog_authority - description: AppFlow uses the role only for the Glue table, database and partition operations of the flow's catalog registration; no credentials and no arbitrary actions under the role. - - id: connector_profiles - description: Referenced connector profiles also need appflow:UseConnectorProfile, and an S3-destination flow needs the caller-side S3 bucket permissions. - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict which roles can be passed. - blockers: - - scp_or_boundary_deny - confidence: conditional - severity: low - mitigation: Restrict iam:PassRole on AppFlow catalog roles with iam:PassedToService and exact role ARNs, scope those roles to dedicated Glue databases, and limit flow creation and update. - references: - - https://docs.aws.amazon.com/appflow/latest/userguide/security_iam_service-with-iam.html - notes: Bounded impact - catalog-integrity proxy through the passed role (page states it is privilege escalation but not role credential theft). Modelled like the DataSync bounded PassRole entries. +[] diff --git a/src/privilege-escalation-paths/aws/apprunner.yaml b/src/privilege-escalation-paths/aws/apprunner.yaml index e6a946671b..8d267bd8f8 100644 --- a/src/privilege-escalation-paths/aws/apprunner.yaml +++ b/src/privilege-escalation-paths/aws/apprunner.yaml @@ -5,10 +5,11 @@ 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: + 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. + 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 @@ -43,10 +44,11 @@ provider: aws service: apprunner title: Update an existing App Runner service that has an instance role - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-apprunner-privesc/README.md#apprunnerupdateservice + 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 the instance role of an existing App Runner service by changing - its image or start command. + summary: The source can obtain the privileges of the instance role of an existing App Runner service by changing its + image or start command. requires: all_of: - action: apprunner:UpdateService @@ -61,8 +63,8 @@ outcome: workload_execution conditions: - id: passrole_on_change - description: If the update changes the instance role, iam:PassRole is required; keeping the current role does - not need it. + description: If the update changes the instance role, iam:PassRole is required; keeping the current role does not + need it. blockers: - scp_or_boundary_deny confidence: derived @@ -76,15 +78,17 @@ 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: + 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. + 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}" - - action: apprunner:UpdateService - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: apprunner:UpdateService + resource: "*" target: kind: aws_role selector: @@ -94,15 +98,45 @@ aggregate_as: "Roles trusting tasks.apprunner.amazonaws.com passable in {account}" outcome: workload_execution conditions: - - id: existing_service - description: At least one existing App Runner service must be covered by apprunner:UpdateService. - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict which roles can be passed. + - id: existing_service + description: At least one existing App Runner service must be covered by apprunner:UpdateService. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. blockers: - - scp_or_boundary_deny + - 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. + 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); the page notes that changing role-bearing configuration triggers iam:PassRole. + - https://docs.aws.amazon.com/apprunner/latest/api/API_UpdateService.html + notes: Companion of aws-apprunner-updateservice (keeps the existing role, no PassRole); the page notes that changing + role-bearing configuration triggers iam:PassRole. +- 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: 0b36331 + 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_verified_authority + selector: + aws_challenge_fact: aws-apprunner-plaintext-credential + scope: same_account + conditions: + - id: verified_evidence + description: The exact usable credential and its newly reachable owner, or service-plane administrator grant, must + be verified; absent evidence yields UNKNOWN. + - 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 listed action to approved operators and protect exposed credentials. + notes: Required collector evidence is absent from current snapshots; missing evidence remains UNKNOWN/unresolved. diff --git a/src/privilege-escalation-paths/aws/appstream.yaml b/src/privilege-escalation-paths/aws/appstream.yaml index 7d3bc279d8..3410f4720e 100644 --- a/src/privilege-escalation-paths/aws/appstream.yaml +++ b/src/privilege-escalation-paths/aws/appstream.yaml @@ -3,57 +3,15 @@ # Existing-resource techniques use via_resource_type appstream_* (roles trusting appstream.amazonaws.com; the # fleet / image-builder / app-block-builder inventory is not collected, so attachment resolves as unknown). -- id: aws-appstream-createstreamingurl-existing-fleet - provider: aws - service: appstream - title: Open a streaming session on an existing fleet that has an 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: The source can obtain the privileges of the IAM role of existing AppStream fleets associated with a stack - it can create streaming URLs for. - requires: - all_of: - - action: appstream:CreateStreamingURL - resource: '*' - target: - kind: aws_role - selector: - trust_allows_service: appstream.amazonaws.com - via_resource_type: appstream_fleet - scope: same_account - aggregate_as: IAM roles of AppStream fleets in {account} - outcome: workload_execution - conditions: - - id: stack_fleet_association - description: The fleet must be running and associated with a stack; CreateStreamingURL authorizes the stack - ARN (the edge is computed only for grants covering "*"). - - id: session_can_reach_credentials - description: The streamed application or desktop must let the user run code or reach the instance's role credential - profile; locked-down application-only stacks with restricted file system and clipboard settings may prevent - it. - - id: application_allowed - description: Fleets using Elastic or application-mode streaming need an application the user is allowed to launch. - blockers: - - scp_or_boundary_deny - confidence: conditional - severity: critical - mitigation: Restrict appstream:CreateStreamingURL to the identity broker, attach least-privilege roles to fleets - and prefer SAML or user-pool access with entitlements over API-minted streaming URLs. - references: - - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateStreamingURL.html - - https://docs.aws.amazon.com/appstream2/latest/developerguide/using-iam-roles-to-grant-permissions-to-applications-scripts-streaming-instances.html - notes: Fleet instances expose the fleet IamRoleArn through the appstream_machine_role credential profile. Fleet-to-stack - association is not collected, so every role trusting appstream.amazonaws.com is reported with unknown attachment. - - - id: aws-appstream-createimagebuilderstreamingurl provider: aws service: appstream title: Connect to an existing image builder that has an IAM role - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilderstreamingurl--administratorroot-access-to-an-existing-builder + 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: The source can obtain the privileges of the IAM role of existing AppStream image builders in Resource - scope (image-builder sessions run with administrator access). + summary: The source can obtain the privileges of the IAM role of existing AppStream image builders in Resource scope + (image-builder sessions run with administrator access). requires: all_of: - action: appstream:CreateImageBuilderStreamingURL @@ -68,8 +26,8 @@ outcome: workload_execution conditions: - id: builder_running - description: The image builder must be running (or startable by the source with appstream:StartImageBuilder) - and have an IAM role. + description: The image builder must be running (or startable by the source with appstream:StartImageBuilder) and + have an IAM role. blockers: - scp_or_boundary_deny confidence: conditional @@ -85,7 +43,8 @@ provider: aws service: appstream title: Connect to an existing app block builder that has an 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: + 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: The source can obtain the privileges of the IAM role of existing AppStream app block builders in Resource scope. @@ -115,89 +74,12 @@ notes: App block builder inventory is not collected; attachment resolves as unknown. -- id: aws-appstream-updateapplication-elastic-fleet - provider: aws - service: appstream - title: Change the launch definition of an application used by an Elastic fleet - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamupdateapplication--poison-an-elastic-fleet-application-launch - source_revision: 6fb9ac51fd - summary: The source can obtain (when a user next launches the application) the privileges of the IAM role of fleets - that run an application it can update. - requires: - all_of: - - action: appstream:UpdateApplication - resource: '{target.consumer_input_arn}' - target: - kind: aws_role - selector: - trust_allows_service: appstream.amazonaws.com - consumer_input_writable_via: appstream:UpdateApplication - scope: same_account - aggregate_as: IAM roles of AppStream fleets running updatable applications in {account} - outcome: workload_execution - conditions: - - id: application_launched - description: A user (or the source, through a streaming URL) must launch the application on a fleet that has - an IAM role. - - id: launch_target_controlled - description: The new launch path or parameters must run content the source controls (for example from an app - block it can write). - blockers: - - scp_or_boundary_deny - confidence: conditional - severity: critical - mitigation: Restrict appstream:UpdateApplication and app block sources to packaging administrators and attach - least-privilege roles to Elastic fleets. - references: - - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_UpdateApplication.html - notes: '{target.consumer_input_arn} is the AppStream application ARN; the application-to-fleet mapping is not - collected.' - - -- id: aws-appstream-updatefleet-image-swap - provider: aws - service: appstream - title: Replace an existing AppStream fleet image or session-script archive while retaining its role - 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 - summary: The source can obtain the IAM role privileges of an existing fleet by supplying a controlled image or - session-script archive that runs on later fleet instances. - requires: - all_of: - - action: appstream:UpdateFleet - resource: '{target.resource_arn}' - target: - kind: aws_role - selector: - trust_allows_service: appstream.amazonaws.com - via_resource_type: appstream_fleet - scope: same_account - aggregate_as: IAM roles of AppStream fleets in {account} - outcome: workload_execution - conditions: - - id: controlled_image_or_script - description: The source must provide an image it controls, or an S3 session-script ZIP readable by AppStream - in the fleet account and Region. - - id: session_trigger - description: The fleet must launch an instance or user session so the controlled image or session script runs. - blockers: - - scp_or_boundary_deny - confidence: conditional - severity: critical - mitigation: Restrict appstream:UpdateFleet on fleets with IAM roles, validate images and session-script S3 objects, - and monitor changes to fleet image and session-script settings. - references: - - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_UpdateFleet.html - notes: The same UpdateFleet permission and fleet-role target cover both image substitution and an Elastic fleet - session-script location change. The session-script variant is documented at aws-persistence/aws-appstream-persistence/README.md#appstreamupdatefleet--s3--recurring-system-session-scripts-on-an-existing-elastic-fleet. - A role swap instead requires iam:PassRole. - - - id: aws-appstream-passrole-createimagebuilder-createfleet provider: aws service: appstream title: Create an image builder or fleet with a passed role and stream into it - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamcreateimagebuilder--createfleet--iampassrole--session-with-the-passed-roles-credentials + 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: @@ -241,11 +123,11 @@ - id: passrole_condition_key description: iam:PassedToService conditions may restrict which roles can be passed. - id: image_and_network - description: An available image and VPC subnet/security group the source may use are required; the fleet path - can reuse an existing stack instead of CreateStack/AssociateFleet. + description: An available image and VPC subnet/security group the source may use are required; the fleet path can + reuse an existing stack instead of CreateStack/AssociateFleet. - id: update_existing - description: The UpdateFleet and UpdateAppBlockBuilder alternatives need an existing fleet (associated with - a stack the source can stream from) or app block builder in scope, and set its role to the passed one. + description: The UpdateFleet and UpdateAppBlockBuilder alternatives need an existing fleet (associated with a stack + the source can stream from) or app block builder in scope, and set its role to the passed one. blockers: - scp_or_boundary_deny confidence: conditional @@ -255,5 +137,42 @@ references: - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateImageBuilder.html - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_CreateFleet.html - notes: 'Reach is roles trusting appstream.amazonaws.com in PassRole scope. Alternatives: new image builder, new - fleet with stack, new app block builder, or an existing fleet / app block builder repointed to the passed role.' + notes: 'Reach is roles trusting appstream.amazonaws.com in PassRole scope. Alternatives: new image builder, new fleet with + stack, new app block builder, or an existing fleet / app block builder repointed to the passed role.' +- id: aws-appstream-updateapplication-elastic-fleet + provider: aws + service: appstream + title: Change the launch definition of an application used by an Elastic fleet + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appstream-privesc/README.md#appstreamupdateapplication--poison-an-elastic-fleet-application-launch + source_revision: 6fb9ac51fd + summary: The source can obtain (when a user next launches the application) the privileges of the IAM role of fleets + that run an application it can update. + requires: + all_of: + - action: appstream:UpdateApplication + resource: '{target.consumer_input_arn}' + target: + kind: aws_role + selector: + trust_allows_service: appstream.amazonaws.com + consumer_input_writable_via: appstream:UpdateApplication + scope: same_account + aggregate_as: IAM roles of AppStream fleets running updatable applications in {account} + outcome: workload_execution + conditions: + - id: application_launched + description: A user (or the source, through a streaming URL) must launch the application on a fleet that has an IAM + role. + - id: executable_launch + description: The launch path/parameters must execute attacker code, either an inline interpreter command such as + PowerShell or a controlled file/app block. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: critical + mitigation: Restrict appstream:UpdateApplication and app block sources to packaging administrators and attach + least-privilege roles to Elastic fleets. + references: + - https://docs.aws.amazon.com/appstream2/latest/APIReference/API_UpdateApplication.html + notes: '{target.consumer_input_arn} is the AppStream application ARN; the application-to-fleet mapping is not collected.' diff --git a/src/privilege-escalation-paths/aws/athena.yaml b/src/privilege-escalation-paths/aws/athena.yaml index 6cfbded74d..7d7f1e91aa 100644 --- a/src/privilege-escalation-paths/aws/athena.yaml +++ b/src/privilege-escalation-paths/aws/athena.yaml @@ -7,19 +7,21 @@ 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: + 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. + 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}" - - action: athena:CreateWorkGroup - resource: "*" - - action: athena:StartSession - resource: "*" - - action: athena:StartCalculationExecution - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: athena:CreateWorkGroup + resource: "*" + - action: athena:StartSession + resource: "*" + - action: athena:StartCalculationExecution + resource: "*" target: kind: aws_role selector: @@ -28,31 +30,34 @@ scope: same_account aggregate_as: "Roles trusting athena.amazonaws.com passable in {account}" 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: 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. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: derived severity: critical - mitigation: Restrict iam:PassRole on Athena Spark execution roles with iam:PassedToService=athena.amazonaws.com and restrict athena:CreateWorkGroup to administrators. + 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 + - 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. - id: aws-athena-startcalculationexecution-existing-session provider: aws service: athena title: Submit a calculation to 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: + 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: The source can obtain the privileges of the execution role of Spark workgroups in which it can submit calculations to a live session. + summary: The source can obtain the privileges of the execution role of Spark workgroups in which it can submit + calculations to a live session. requires: all_of: - - action: athena:StartCalculationExecution - resource: "{target.resource_arn}" + - action: athena:StartCalculationExecution + resource: "{target.resource_arn}" target: kind: aws_role selector: @@ -61,58 +66,31 @@ scope: same_account aggregate_as: "Execution roles of Athena Spark workgroups in {account}" conditions: - - id: live_session - description: A session must be active in the workgroup and its ID known to the source; sessions are ephemeral. + - id: live_session + description: A session must be active in the workgroup and its ID known to the source; sessions are ephemeral. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: critical - mitigation: Scope athena:StartCalculationExecution to the caller's own workgroups and keep Spark execution roles least-privileged. + mitigation: Scope athena:StartCalculationExecution to the caller's own workgroups and keep Spark 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_StartCalculationExecution.html notes: The action is authorized on the workgroup ARN; no PassRole is needed. -- id: aws-athena-getsessionendpoint-spark-connect - provider: aws - service: athena - title: Obtain the Spark Connect endpoint and token of an active Athena Spark 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: The source can obtain the privileges of the execution role of Spark workgroups whose active Spark Connect sessions it can attach to. - requires: - all_of: - - action: athena:GetSessionEndpoint - resource: "{target.resource_arn}" - target: - kind: aws_role - selector: - trust_allows_service: athena.amazonaws.com - via_resource_type: athena_workgroup - scope: same_account - aggregate_as: "Execution roles of Athena Spark workgroups in {account}" - conditions: - - id: live_spark35_session - description: A live Spark 3.5 session must exist in the workgroup and its ID be known to the source. - blockers: - - scp_or_boundary_deny - confidence: conditional - severity: critical - mitigation: Restrict athena:GetSessionEndpoint to session owners and keep Spark execution roles least-privileged. - references: - - https://docs.aws.amazon.com/athena/latest/APIReference/API_GetSessionEndpoint.html - notes: The returned bearer token controls the existing session; no PassRole is needed. - - id: aws-athena-createpresignednotebookurl provider: aws service: athena title: Mint a presigned URL for a running 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: + 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: The source can obtain the privileges of the execution role of Spark workgroups whose running notebook sessions it can open. + summary: The source can obtain the privileges of the execution role of Spark workgroups whose running notebook + sessions it can open. requires: all_of: - - action: athena:CreatePresignedNotebookUrl - resource: "{target.resource_arn}" + - action: athena:CreatePresignedNotebookUrl + resource: "{target.resource_arn}" target: kind: aws_role selector: @@ -121,28 +99,31 @@ scope: same_account aggregate_as: "Execution roles of Athena Spark workgroups in {account}" conditions: - - id: live_notebook_session - description: A live notebook session must exist in the workgroup and its ID be known to the source. + - id: live_notebook_session + description: A live notebook session must exist in the workgroup and its ID be known to the source. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: critical - mitigation: Restrict athena:CreatePresignedNotebookUrl to notebook owners and keep Spark execution roles least-privileged. + mitigation: Restrict athena:CreatePresignedNotebookUrl to notebook owners and keep Spark 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_CreatePresignedNotebookUrl.html notes: The URL is a bearer credential for the notebook; no PassRole or StartCalculationExecution is needed. - id: aws-athena-updatenotebook-poison provider: aws service: athena title: Replace the cells of an Athena Spark notebook that is executed later - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-athena-stored-query-privesc/README.md#athenaupdatenotebook--poison-a-spark-notebook-executed-later + 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 - summary: The source can obtain the privileges of the execution role of Spark workgroups whose notebooks it can rewrite, once those cells are run. + summary: The source can obtain the privileges of the execution role of Spark workgroups whose notebooks it can + rewrite, once those cells are run. requires: all_of: - - action: athena:UpdateNotebook - resource: "{target.resource_arn}" + - action: athena:UpdateNotebook + resource: "{target.resource_arn}" target: kind: aws_role selector: @@ -151,15 +132,15 @@ scope: same_account aggregate_as: "Execution roles of Athena Spark workgroups in {account}" conditions: - - id: notebook_runs_later - description: An operator or automation must later run the rewritten cells; the update itself executes nothing. - - id: known_notebook - description: The notebook ID (and session ID for an active notebook) must be known to the source. + - id: notebook_runs_later + description: An operator or automation must later run the rewritten cells; the update itself executes nothing. + - id: known_notebook + description: The notebook ID (and session ID for an active notebook) must be known to the source. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict athena:UpdateNotebook to notebook owners and keep Spark execution roles least-privileged. references: - - https://docs.aws.amazon.com/athena/latest/APIReference/API_UpdateNotebook.html + - https://docs.aws.amazon.com/athena/latest/APIReference/API_UpdateNotebook.html notes: Authorized on the workgroup ARN, so any known notebook in the workgroup is reachable. diff --git a/src/privilege-escalation-paths/aws/bedrock.yaml b/src/privilege-escalation-paths/aws/bedrock.yaml index d28ea6c1aa..d11ff6fd52 100644 --- a/src/privilege-escalation-paths/aws/bedrock.yaml +++ b/src/privilege-escalation-paths/aws/bedrock.yaml @@ -5,10 +5,11 @@ provider: aws service: bedrock title: Run code in an existing AgentCore Code Interpreter with an execution 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: + 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 - summary: The source can obtain the privileges of the execution role of a custom AgentCore Code Interpreter it - can start sessions in and invoke. + summary: The source can obtain the privileges of the execution role of a custom AgentCore Code Interpreter it can + start sessions in and invoke. requires: all_of: - action: bedrock-agentcore:StartCodeInterpreterSession @@ -21,8 +22,8 @@ attached_to_service: bedrock-agentcore attached_resource_covered_by: bedrock-agentcore:InvokeCodeInterpreter scope: same_account - aggregate_as: Execution roles of AgentCore Code Interpreters covered by bedrock-agentcore:InvokeCodeInterpreter - in {account} + aggregate_as: Execution roles of AgentCore Code Interpreters covered by bedrock-agentcore:InvokeCodeInterpreter in + {account} outcome: workload_execution conditions: - id: network_mode @@ -42,10 +43,11 @@ 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--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. + 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 @@ -81,15 +83,17 @@ 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: + 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. + 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: "*" + - action: lambda:UpdateFunctionCode + resource: "{target.attached_resource_arn}" + - action: bedrock:InvokeAgent + resource: "*" target: kind: aws_role selector: @@ -98,38 +102,39 @@ 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). + - 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 + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Restrict lambda:UpdateFunctionCode on agent tool functions and keep their execution roles least-privileged. + 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). + - 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 +- id: aws-bedrock-agentcore-createagentruntime-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 + 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 creating a harness with that execution role and running commands in its runtime. + 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:CreateHarness - resource: "*" - - action: bedrock-agentcore:CreateAgentRuntime - resource: "*" - - action: bedrock-agentcore:CreateAgentRuntimeEndpoint - resource: "*" - - action: bedrock-agentcore:InvokeAgentRuntimeCommand - resource: "*" - - action: bedrock-agentcore:InvokeAgentRuntime - resource: "*" + - 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: @@ -138,38 +143,37 @@ scope: same_account aggregate_as: "Roles trusting bedrock-agentcore.amazonaws.com passable in {account}" 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: 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 + - 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. + 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/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/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-createagentruntime-passrole +- id: aws-bedrock-agentcore-updateagentruntime-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 + 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 running a runtime artifact it controls under that role. + 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:CreateAgentRuntime - resource: "*" - - action: bedrock-agentcore:CreateAgentRuntimeEndpoint - resource: "*" - - action: bedrock-agentcore:InvokeAgentRuntime - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: bedrock-agentcore:UpdateAgentRuntime + resource: "*" + - action: bedrock-agentcore:InvokeAgentRuntime + resource: "*" target: kind: aws_role selector: @@ -178,115 +182,149 @@ scope: same_account aggregate_as: "Roles trusting bedrock-agentcore.amazonaws.com passable in {account}" 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. + - 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 + - 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. + 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_CreateAgentRuntime.html - notes: The aws-bedrock-privesc page describes the same technique; it is sourced here at the AgentCore page. + - 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. -- id: aws-bedrock-agentcore-updateagentruntime-passrole +- id: aws-bedrock-agentcore-invokeharness-shell-existing 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. + title: Invoke an existing AgentCore harness with its shell tool to run commands as its execution role + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-post-exploitation/README.md#aws---agentcore-harness-rce-via-indirect-prompt-injection + source_revision: 6fb9ac51fd + summary: The source can obtain the privileges of the execution role of an existing AgentCore harness it can invoke, + because the built-in shell tool (enabled unless allowedTools restricts it, and overridable per invocation) runs + commands as root in the harness runtime. requires: all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: bedrock-agentcore:UpdateAgentRuntime - resource: "*" - - action: bedrock-agentcore:InvokeAgentRuntime - resource: "*" + - action: bedrock-agentcore:InvokeHarness + resource: "{target.resource_arn}" target: kind: aws_role selector: - trust_allows_service: bedrock-agentcore.amazonaws.com - resource_permission_covers_target: iam:PassRole + attached_to_service: bedrock-agentcore + via_resource_type: bedrock-agentcore_harness scope: same_account - aggregate_as: "Roles trusting bedrock-agentcore.amazonaws.com passable in {account}" + aggregate_as: "Execution roles of AgentCore harnesses invokable 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. + - id: shell_tool_available + description: The shell tool must be selectable for the invocation (no restrictive allowedTools on the harness that + the invocation cannot override) and the model must follow the instruction. + - id: indirect_variant + description: Without InvokeHarness, the same result needs attacker-controlled content that a harness with shell + enabled processes (indirect prompt injection); that variant is not permission-based. blockers: - - scp_or_boundary_deny + - 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. + severity: high + mitigation: Restrict bedrock-agentcore:InvokeHarness to the application principal, restrict allowedTools so harnesses + processing untrusted content cannot select shell, and keep harness execution roles least-privileged. 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. - -- id: aws-bedrock-agentcore-invokeagentruntimecommand-existing-runtime + - https://docs.aws.amazon.com/bedrock-agentcore/latest/APIReference/API_InvokeHarness.html + notes: Existing-harness counterpart of aws-bedrock-agentcore-createharness-passrole. Harnesses are not collected, so + roles trusting bedrock-agentcore.amazonaws.com are the fallback target set (unknown). +- id: aws-bedrock-agentcore-createharness-passrole provider: aws service: bedrock - title: Run shell commands in an existing AgentCore agent runtime - 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 - summary: The source can obtain the privileges of the execution role of an existing AgentCore agent runtime (including harness runtimes) by running commands in it. + 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: bedrock-agentcore:InvokeAgentRuntimeCommand - resource: "{target.attached_resource_arn}" + - 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: '*' + - action: bedrock-agentcore:CreateMemory + resource: '*' + - action: bedrock-agentcore:CreateWorkloadIdentity + resource: '*' + - action: bedrock-agentcore:GetAgentRuntime + resource: '*' target: kind: aws_role selector: - attached_to_service: bedrock-agentcore - attached_resource_covered_by: bedrock-agentcore:InvokeAgentRuntimeCommand + trust_allows_service: bedrock-agentcore.amazonaws.com + resource_permission_covers_target: iam:PassRole scope: same_account - aggregate_as: "Execution roles of AgentCore runtimes covered by bedrock-agentcore:InvokeAgentRuntimeCommand in {account}" - outcome: workload_execution + aggregate_as: Roles trusting bedrock-agentcore.amazonaws.com passable in {account} conditions: - - id: runtime_endpoint - description: The runtime must have a ready endpoint the source can address; runtimes are not collected, so any role trusting bedrock-agentcore.amazonaws.com is a candidate. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. + - 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 + - scp_or_boundary_deny confidence: conditional severity: critical - mitigation: Deny bedrock-agentcore:InvokeAgentRuntimeCommand except where direct shell access is required, and keep runtime execution roles least-privileged. + 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: The harness heading shows InvokeAgentRuntimeCommand giving a shell as the runtime's execution role; on an existing runtime neither iam:PassRole nor any create action is needed. - -- id: aws-bedrock-agentcore-invokeharness-shell-existing + - https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-permissions.html + notes: The documented composite creation requires CreateMemory, CreateWorkloadIdentity and GetAgentRuntime. Endpoint, + identity and memory reads may also be required by the selected configuration; a missing service-linked runtime + identity role leaves the result UNKNOWN. +- id: aws-bedrock-agentcore-invokeagentruntimecommand-existing-runtime provider: aws service: bedrock - title: Invoke an existing AgentCore harness with its shell tool to run commands as its execution role - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-post-exploitation/README.md#aws---agentcore-harness-rce-via-indirect-prompt-injection + title: Run shell commands in an existing AgentCore agent runtime + 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 - summary: The source can obtain the privileges of the execution role of an existing AgentCore harness it can invoke, because the built-in shell tool (enabled unless allowedTools restricts it, and overridable per invocation) runs commands as root in the harness runtime. + summary: The source can obtain the privileges of the execution role of an existing AgentCore agent runtime (including + harness runtimes) by running commands in it. requires: all_of: - - action: bedrock-agentcore:InvokeHarness - resource: "{target.resource_arn}" + - action: bedrock-agentcore:InvokeAgentRuntimeCommand + resource: '{target.attached_resource_arn}' + - action: bedrock-agentcore:InvokeAgentRuntime + resource: '{target.attached_resource_arn}' target: kind: aws_role selector: attached_to_service: bedrock-agentcore - via_resource_type: bedrock-agentcore_harness + attached_resource_covered_by: bedrock-agentcore:InvokeAgentRuntimeCommand scope: same_account - aggregate_as: "Execution roles of AgentCore harnesses invokable in {account}" + aggregate_as: Execution roles of AgentCore runtimes covered by bedrock-agentcore:InvokeAgentRuntimeCommand in + {account} outcome: workload_execution conditions: - - id: shell_tool_available - description: The shell tool must be selectable for the invocation (no restrictive allowedTools on the harness that the invocation cannot override) and the model must follow the instruction. - - id: indirect_variant - description: Without InvokeHarness, the same result needs attacker-controlled content that a harness with shell enabled processes (indirect prompt injection); that variant is not permission-based. + - id: runtime_endpoint + description: The runtime must have a ready endpoint the source can address; runtimes are not collected, so any role + trusting bedrock-agentcore.amazonaws.com is a candidate. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional - severity: high - mitigation: Restrict bedrock-agentcore:InvokeHarness to the application principal, restrict allowedTools so harnesses processing untrusted content cannot select shell, and keep harness execution roles least-privileged. + severity: critical + mitigation: Deny bedrock-agentcore:InvokeAgentRuntimeCommand except where direct shell access is required, and keep + runtime execution roles least-privileged. references: - - https://docs.aws.amazon.com/bedrock-agentcore/latest/APIReference/API_InvokeHarness.html - notes: Existing-harness counterpart of aws-bedrock-agentcore-createharness-passrole. Harnesses are not collected, so roles trusting bedrock-agentcore.amazonaws.com are the fallback target set (unknown). + - https://docs.aws.amazon.com/bedrock-agentcore/latest/devguide/runtime-permissions.html + notes: The harness heading shows InvokeAgentRuntimeCommand giving a shell as the runtime's execution role; on an + existing runtime neither iam:PassRole nor any create action is needed. diff --git a/src/privilege-escalation-paths/aws/billing.yaml b/src/privilege-escalation-paths/aws/billing.yaml new file mode 100644 index 0000000000..e6bb2ca0e6 --- /dev/null +++ b/src/privilege-escalation-paths/aws/billing.yaml @@ -0,0 +1,31 @@ +- id: aws-billing-enable-dormant-iam-console-access + provider: aws + service: billing + title: Enable dormant Billing console grants + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-invoicing-and-billing-privesc/README.md#enable-previously-granted-legacy-billing-permissions + summary: The source can enable account Billing console IAM access, activating previously masked permissions for itself + or another identity. + requires: + all_of: + - action: billing:UpdateIAMAccessPreference + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-billing-enable-dormant-iam-console-access + scope: same_account + severity: high + mitigation: Restrict billing:UpdateIAMAccessPreference and review masked Billing console grants. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_billing.html + - https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/control-access-billing.html + confidence: conditional + conditions: + - id: dormant_grant + description: Allow IAM Access is disabled and the exact source has an applicable Billing console policy grant that + becomes effective when enabled. + - 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: Required collector evidence is absent from current snapshots; missing evidence remains UNKNOWN/unresolved. diff --git a/src/privilege-escalation-paths/aws/budgets.yaml b/src/privilege-escalation-paths/aws/budgets.yaml index 8302483591..ecda04555c 100644 --- a/src/privilege-escalation-paths/aws/budgets.yaml +++ b/src/privilege-escalation-paths/aws/budgets.yaml @@ -1,46 +1,4 @@ # AWS Budgets privilege escalation techniques. # Source: hacktricks-cloud aws-budgets-privesc/README.md (rev 171e422299). -- id: aws-budgets-passrole-createbudgetaction - provider: aws - service: budgets - title: Create a budget action that runs as a passed execution 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_revision: 6fb9ac51fd - summary: The source can make a passable role trusting budgets.amazonaws.com attach IAM policies or SCPs, or run - SSM documents, on its behalf (bounded by the three budget action types). - requires: - all_of: - - action: iam:PassRole - resource: '{target.arn}' - - action: budgets:CreateBudgetAction - resource: '*' - target: - kind: aws_role - selector: - trust_allows_service: budgets.amazonaws.com - resource_permission_covers_target: iam:PassRole - scope: same_account - aggregate_as: Roles trusting budgets.amazonaws.com passable in {account} - outcome: impersonation - conditions: - - id: action_type_bound - description: Only APPLY_IAM_POLICY (managed policy to users/groups/roles), APPLY_SCP_POLICY (management account) - and RUN_SSM_DOCUMENTS (stop EC2/RDS documents) are possible; the gain is what the role can do through these, - not a full role session. - - id: action_fires - description: The action runs only when the budget threshold is crossed (automatic approval) or after budgets:ExecuteBudgetAction - approval; an existing budget the source can attach the action to is required. - - 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 budget execution roles and budgets:CreateBudgetAction to finance administrators; - scope execution roles to the policies and targets intended. - references: - - https://docs.aws.amazon.com/cost-management/latest/userguide/budgets-controls.html - - https://docs.aws.amazon.com/aws-cost-management/latest/APIReference/API_budgets_CreateBudgetAction.html - notes: With APPLY_IAM_POLICY and a role allowed to attach any managed policy, the source can attach AdministratorAccess - to itself. +[] diff --git a/src/privilege-escalation-paths/aws/challenge-v3.yaml b/src/privilege-escalation-paths/aws/challenge-v3.yaml index 9464d8dbd1..aa62f518dc 100644 --- a/src/privilege-escalation-paths/aws/challenge-v3.yaml +++ b/src/privilege-escalation-paths/aws/challenge-v3.yaml @@ -3,9 +3,10 @@ provider: aws service: transfer title: Substitute an AS2 partner signing certificate - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#as2-partner-certificate-substitution--impersonate-a-trading-partner - summary: Partner-profile certificate replacement -> that exact AS2 partner protocol identity. Exact source, target - and prerequisite proof are required. + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#as2-partner-certificate-substitution--impersonate-a-trading-partner + summary: Partner-profile certificate replacement -> that exact AS2 partner protocol identity. Exact source, target and + prerequisite proof are required. requires: all_of: - action: transfer:ImportCertificate @@ -22,20 +23,21 @@ - that exact AS2 partner protocol identity. conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - No partner edge from ImportCertificate alone; exact updated profile and agreement are mandatory. + description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; No + partner edge from ImportCertificate alone; exact updated profile and agreement are mandatory. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-02-register-an-acme-account-with-a-binding-to-issue-certif provider: aws service: acm title: Register an ACME account with a binding to issue certificates through its IAM role - source: src/pentesting-cloud/aws-security/aws-persistence/aws-acm-persistence/README.md#register-an-attacker-controlled-acme-certificate-account + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-acm-persistence/README.md#register-an-attacker-controlled-acme-certificate-account summary: EAB secret or creation -> exact ACM ACME endpoint certificate-issuance plane. Exact source, target and prerequisite proof are required. requires: @@ -47,21 +49,21 @@ selector: aws_challenge_fact: aws-v3-02-register-an-acme-account-with-a-binding-to-issue-certif scope: same_account - aggregate_as: Verified Register an ACME account with a binding to issue certificates through its IAM role targets - in {account} + aggregate_as: Verified Register an ACME account with a binding to issue certificates through its IAM role targets in + {account} grants: - exact ACM ACME endpoint certificate-issuance plane. conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - EAB possession never equals general use of its IAM role; domain validation and actor key are separate. + description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; EAB + possession never equals general use of its IAM role; domain validation and actor key are separate. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-03-replace-a-trusted-connect-workspace-application-with-at provider: aws service: app-integrations @@ -78,8 +80,8 @@ selector: aws_challenge_fact: aws-v3-03-replace-a-trusted-connect-workspace-application-with-at scope: same_account - aggregate_as: Verified Replace a trusted Connect workspace application with attacker-controlled content targets - in {account} + aggregate_as: Verified Replace a trusted Connect workspace application with attacker-controlled content targets in + {account} grants: - exact associated agent workspace session. conditions: @@ -92,13 +94,14 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-04-force-install-a-hostile-extension-in-workspaces-web-ses provider: aws service: workspaces-web title: Force-install a hostile extension in WorkSpaces Web sessions - source: src/pentesting-cloud/aws-security/aws-persistence/aws-workspaces-web-persistence/README.md#persist-a-hostile-extension-in-every-secure-browser-session + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-workspaces-web-persistence/README.md#persist-a-hostile-extension-in-every-secure-browser-session summary: Attached browser-settings write -> portal browser session with that forced extension. Exact source, target and prerequisite proof are required. requires: @@ -115,21 +118,22 @@ - portal browser session with that forced extension. conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - A session/extension is the bounded target; no claim about arbitrary sites or users without manifest and session + description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; A + session/extension is the bounded target; no claim about arbitrary sites or users without manifest and session evidence. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-05-add-or-replace-a-workspaces-web-portal-saml-oidc-identi provider: aws service: workspaces-web title: Add or replace a WorkSpaces Web portal SAML/OIDC identity provider - source: src/pentesting-cloud/aws-security/aws-persistence/aws-workspaces-web-persistence/README.md#persist-an-attacker-controlled-portal-identity-provider + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-workspaces-web-persistence/README.md#persist-an-attacker-controlled-portal-identity-provider summary: Controlled IdP trusted by an exact standard-federation portal -> portal access plane. Exact source, target and prerequisite proof are required. requires: @@ -146,20 +150,21 @@ - portal access plane. conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - IdP write alone is insufficient; only that portal and its federated session are targets. + description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; IdP + write alone is insufficient; only that portal and its federated session are targets. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-06-use-independent-cognito-replica-lockout-counters-to-gue provider: aws service: challenge-evidence title: Use independent Cognito replica lockout counters to guess a user password - 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 + 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 summary: Public Cognito client and active replica -> named user-pool user token, conditional on password/challenges. Exact external source and target proof are required. requires: {} @@ -177,20 +182,21 @@ - named user-pool user token, conditional on password/challenges. conditions: - id: exact_external_foothold - description: Replica lockout divergence does not prove a correct guess or MFA completion. Source evidence must - prove anonymous control for the exact target. + description: Replica lockout divergence does not prove a correct guess or MFA completion. Source evidence must prove + anonymous control for the exact target. confidence: conditional severity: high mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal - is inferred from configuration. + notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is + inferred from configuration. - id: aws-v3-07-agentcore-runtime-ssrf-to-its-execution-role-credential provider: aws service: challenge-evidence title: AgentCore Runtime SSRF to its execution-role credentials - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-post-exploitation/README.md#1-runtime-ssrf---mmds-credentials - summary: Compromised AgentCore Runtime -> its exact execution role through MMDS credentials. Exact external source - and target proof are required. + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-post-exploitation/README.md#1-runtime-ssrf---mmds-credentials + summary: Compromised AgentCore Runtime -> its exact execution role through MMDS credentials. Exact external source and + target proof are required. requires: {} source_kind: aws_challenge_foothold source_selector: @@ -205,20 +211,21 @@ - its exact execution role through MMDS credentials. conditions: - id: exact_external_foothold - description: Runtime role attachment is only a target anchor; SSRF behavior needs proof. Source evidence must - prove runtime control for the exact target. + description: Runtime role attachment is only a target anchor; SSRF behavior needs proof. Source evidence must prove + runtime control for the exact target. confidence: conditional severity: high mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal - is inferred from configuration. + notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is + inferred from configuration. - id: aws-v3-08-read-ec2-instance-profile-credentials-from-imds-inside provider: aws service: challenge-evidence title: Read EC2 instance-profile credentials from IMDS inside an ECS task - 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 - summary: Compromised ECS-on-EC2 task -> its host instance-profile role. Exact external source and target proof - are required. + 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 + summary: Compromised ECS-on-EC2 task -> its host instance-profile role. Exact external source and target proof are + required. requires: {} source_kind: aws_challenge_foothold source_selector: @@ -238,15 +245,16 @@ confidence: conditional severity: high mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal - is inferred from configuration. + notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is + inferred from configuration. - id: aws-v3-09-use-host-or-container-runtime-control-to-steal-credenti provider: aws service: challenge-evidence title: Use host or container-runtime control to steal credentials of neighboring ECS tasks - 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 - summary: Root/socket control on one ECS container instance -> co-located running task roles. Exact external source - and target proof are required. + 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 + summary: Root/socket control on one ECS container instance -> co-located running task roles. Exact external source and + target proof are required. requires: {} source_kind: aws_challenge_foothold source_selector: @@ -267,15 +275,16 @@ confidence: conditional severity: high mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal - is inferred from configuration. + notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is + inferred from configuration. - id: aws-v3-10-read-lambda-execution-role-credentials-from-runtime-env provider: aws service: challenge-evidence title: Read Lambda execution-role credentials from runtime environment variables - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#exfiltrate-lambda-credentials - summary: Lambda process-environment access -> that function execution role. Exact external source and target proof - are required. + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#exfiltrate-lambda-credentials + summary: Lambda process-environment access -> that function execution role. Exact external source and target proof are + required. requires: {} source_kind: aws_challenge_foothold source_selector: @@ -296,13 +305,14 @@ confidence: conditional severity: high mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal - is inferred from configuration. + notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is + inferred from configuration. - id: aws-v3-11-harvest-the-strategy-recommendations-collector-aws-keys provider: aws service: challenge-evidence title: Harvest the Strategy Recommendations collector AWS keys from local configuration - 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 + 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 summary: Collector-host file access -> IAM principal whose active key is in the collector config. Exact external source and target proof are required. requires: {} @@ -314,8 +324,8 @@ selector: aws_challenge_fact: aws-v3-11-harvest-the-strategy-recommendations-collector-aws-keys scope: same_account - aggregate_as: Verified Harvest the Strategy Recommendations collector AWS keys from local configuration targets - in {account} + aggregate_as: Verified Harvest the Strategy Recommendations collector AWS keys from local configuration targets in + {account} grants: - IAM principal whose active key is in the collector config. conditions: @@ -325,15 +335,16 @@ confidence: conditional severity: high mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal - is inferred from configuration. + notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is + inferred from configuration. - id: aws-v3-12-drive-a-privileged-lambda-consumer-through-a-writable-e provider: aws service: sns title: Drive a privileged Lambda consumer through a writable event source - 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 - summary: Writable event source -> configured Lambda consumer role, conditional on a verified dangerous handler - sink. Exact source, target and prerequisite proof are required. + 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 + summary: Writable event source -> configured Lambda consumer role, conditional on a verified dangerous handler sink. + Exact source, target and prerequisite proof are required. requires: all_of: - action: sns:Publish @@ -355,13 +366,14 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-13-publish-to-an-iot-rule-whose-lambda-action-misuses-atta provider: aws service: iot title: Publish to an IoT rule whose Lambda action misuses attacker-controlled fields - 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 + 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 summary: iot:Publish to matching enabled rule -> Lambda rule-action role, conditional on verified unsafe handler behavior. Exact source, target and prerequisite proof are required. requires: @@ -373,26 +385,27 @@ selector: aws_challenge_fact: aws-v3-13-publish-to-an-iot-rule-whose-lambda-action-misuses-atta scope: same_account - aggregate_as: Verified Publish to an IoT rule whose Lambda action misuses attacker-controlled fields targets - in {account} + aggregate_as: Verified Publish to an IoT rule whose Lambda action misuses attacker-controlled fields targets in + {account} grants: - Lambda rule-action role, conditional on verified unsafe handler behavior. conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - IoT rule invocation alone is not role control. + description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; IoT + rule invocation alone is not role control. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-14-trigger-privileged-business-actions-through-a-lex-fulfi provider: aws service: lex title: Trigger privileged business actions through a Lex fulfillment hook - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lex-v2-post-exploitation/README.md#abuse-an-existing-code-hook-through-runtime-access + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lex-v2-post-exploitation/README.md#abuse-an-existing-code-hook-through-runtime-access summary: Lex runtime call -> exact configured hook role, conditional on a verified privileged intent/slot behavior. Exact source, target and prerequisite proof are required. requires: @@ -409,20 +422,21 @@ - exact configured hook role, conditional on a verified privileged intent/slot behavior. conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - A hook invocation without application authorization analysis is no principal edge. + description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; A + hook invocation without application authorization analysis is no principal edge. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-15-replay-a-victim-application-session-recovered-from-waf provider: aws service: logs title: Replay a victim application session recovered from WAF records - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#aws-waf-log-credential-harvesting-and-request-replay + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#aws-waf-log-credential-harvesting-and-request-replay summary: Readable WAF log destination -> exact application session identified by a captured replayable header, conditional only. Exact source, target and prerequisite proof are required. requires: @@ -447,13 +461,14 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-16-redeem-a-device-farm-session-endpoint-and-control-a-log provider: aws service: devicefarm title: Redeem a Device Farm session endpoint and control a logged-in test account - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-device-farm-post-exploitation/README.md#take-over-a-running-remote-access-device + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-device-farm-post-exploitation/README.md#take-over-a-running-remote-access-device summary: GetRemoteAccessSession on an active exact session -> Device Farm interactive session control. Exact source, target and prerequisite proof are required. requires: @@ -478,13 +493,14 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-17-reconnect-to-another-user-s-live-gamelift-streams-appli provider: aws service: gameliftstreams title: Reconnect to another user’s live GameLift Streams application session - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-gamelift-streams-post-exploitation/README.md#reconnect-to-an-active-or-disconnected-session + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-gamelift-streams-post-exploitation/README.md#reconnect-to-an-active-or-disconnected-session summary: CreateStreamSessionConnection on exact active session -> GameLift Streams session control. Exact source, target and prerequisite proof are required. requires: @@ -501,20 +517,21 @@ - GameLift Streams session control. conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - A stream session is not automatically a logged-in application account. + description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; A + stream session is not automatically a logged-in application account. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-18-attach-an-attacker-idp-to-a-workspaces-secure-browser-p provider: aws service: workspaces-web title: Attach an attacker IdP to a WorkSpaces Secure Browser portal - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-web-post-exploitation/README.md#add-or-replace-an-attacker-controlled-identity-provider + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-web-post-exploitation/README.md#add-or-replace-an-attacker-controlled-identity-provider summary: WorkSpaces Web IdP replacement -> exact portal federation access plane. Exact source, target and prerequisite proof are required. requires: @@ -531,22 +548,23 @@ - exact portal federation access plane. conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - Do not imply IAM access or Identity Center access from portal login. + description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; Do + not imply IAM access or Identity Center access from portal login. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-19-grant-a-controlled-identity-sitewise-monitor-administra provider: aws service: iotsitewise title: Grant a controlled identity SiteWise Monitor administrator access - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-sitewise-post-exploitation/README.md#grant-yourself-access-to-a-legacy-sitewise-monitor-portal - summary: Create/UpdateAccessPolicy -> exact SiteWise Monitor portal/project ADMINISTRATOR plane. Exact source, - target and prerequisite proof are required. + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-sitewise-post-exploitation/README.md#grant-yourself-access-to-a-legacy-sitewise-monitor-portal + summary: Create/UpdateAccessPolicy -> exact SiteWise Monitor portal/project ADMINISTRATOR plane. Exact source, target + and prerequisite proof are required. requires: all_of: - action: iotsitewise:CreateAccessPolicy @@ -568,15 +586,16 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-20-mint-an-ivs-chat-token-using-another-application-user-i provider: aws service: ivschat title: Mint an IVS Chat token using another application user ID - 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 - summary: CreateChatToken -> IVS Chat room identity/capabilities specified in token request. Exact source, target - and prerequisite proof are required. + 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 + summary: CreateChatToken -> IVS Chat room identity/capabilities specified in token request. Exact source, target and + prerequisite proof are required. requires: all_of: - action: ivschat:CreateChatToken @@ -591,20 +610,21 @@ - IVS Chat room identity/capabilities specified in token request. conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - No AWS IAM principal edge or access outside the room. + description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; No + AWS IAM principal edge or access outside the room. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-21-delegate-audit-manager-control-set-authority-to-an-atta provider: aws service: auditmanager title: Delegate Audit Manager control-set authority to an attacker-controlled role - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-audit-manager-post-exploitation/README.md#delegate-a-control-set-to-another-role + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-audit-manager-post-exploitation/README.md#delegate-a-control-set-to-another-role summary: BatchCreateDelegationByAssessment -> exact Audit Manager control-set RESOURCE_OWNER plane for controlled role. Exact source, target and prerequisite proof are required. requires: @@ -622,20 +642,21 @@ - exact Audit Manager control-set RESOURCE_OWNER plane for controlled role. conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - Do not equate delegation with sts:AssumeRole or AWS account admin. + description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; Do + not equate delegation with sts:AssumeRole or AWS account admin. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-22-clone-a-wireless-device-with-recovered-lorawan-or-sidew provider: aws service: iotwireless title: Clone a wireless device with recovered LoRaWAN or Sidewalk keys - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-wireless-post-exploitation/README.md#recover-wireless-device-onboarding-and-session-secrets + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-wireless-post-exploitation/README.md#recover-wireless-device-onboarding-and-session-secrets summary: GetWirelessDevice secret -> exact wireless-device protocol identity, conditional on secret availability. Exact source, target and prerequisite proof are required. requires: @@ -659,13 +680,14 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-23-redirect-a-supply-chain-erp-connector-to-capture-a-dele provider: aws service: challenge-evidence title: Redirect a Supply Chain ERP connector to capture a delegated ERP credential - 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 + 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 summary: Writable ERP connector endpoint with linked secret -> exact connector ERP account, conditional on credential transmission. Exact external source and target proof are required. requires: {} @@ -683,18 +705,19 @@ - exact connector ERP account, conditional on credential transmission. conditions: - id: exact_external_foothold - description: A secret ARN does not prove its value, handshake, or external acceptance. Source evidence must - prove application control for the exact target. + description: A secret ARN does not prove its value, handshake, or external acceptance. Source evidence must prove + application control for the exact target. confidence: conditional severity: high mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal - is inferred from configuration. + notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is + inferred from configuration. - id: aws-v3-24-recover-or-redirect-procurement-portal-authentication-m provider: aws service: invoicing title: Recover or redirect procurement-portal authentication material - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#steal-or-sabotage-a-procurement-portal-connection + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-invoicing-and-billing-post-exploitation/README.md#steal-or-sabotage-a-procurement-portal-connection summary: Procurement preference read/redirect -> exact external procurement connection account, conditional on credential use. Exact source, target and prerequisite proof are required. requires: @@ -718,15 +741,16 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-25-use-a-cognito-idp-client-secret-as-the-oauth-applicatio provider: aws service: cognito-idp title: Use a Cognito IdP client secret as the OAuth application client - 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 - summary: Cognito client-secret disclosure -> exact OAuth application client/service-plane scopes. Exact source, - target and prerequisite proof are required. + 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 + summary: Cognito client-secret disclosure -> exact OAuth application client/service-plane scopes. Exact source, target + and prerequisite proof are required. requires: all_of: - action: cognito-idp:DescribeUserPoolClient @@ -741,20 +765,21 @@ - exact OAuth application client/service-plane scopes. conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - A client secret is not a Cognito user, IAM role or arbitrary OAuth resource scope. + description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; A + client secret is not a Cognito user, IAM role or arbitrary OAuth resource scope. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-26-reuse-an-amazon-managed-blockchain-accessor-billing-tok provider: aws service: managedblockchain title: Reuse an Amazon Managed Blockchain accessor billing token - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-managed-blockchain-post-exploitation/README.md#recover-an-accessor-bearer-token + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-managed-blockchain-post-exploitation/README.md#recover-an-accessor-bearer-token summary: GetAccessor on AVAILABLE accessor -> exact Managed Blockchain billing-token service plane. Exact source, target and prerequisite proof are required. requires: @@ -778,15 +803,16 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-27-join-kinesis-video-signaling-as-a-master-or-viewer-peer provider: aws service: kinesisvideo title: Join Kinesis Video signaling as a master or viewer peer - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kinesis-video-streams-post-exploitation/README.md#recover-turn-credentials-and-impersonate-webrtc-peers - summary: Kinesis Video ConnectAsMaster/Viewer -> exact signaling-channel peer role. Exact source, target and prerequisite - proof are required. + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kinesis-video-streams-post-exploitation/README.md#recover-turn-credentials-and-impersonate-webrtc-peers + summary: Kinesis Video ConnectAsMaster/Viewer -> exact signaling-channel peer role. Exact source, target and + prerequisite proof are required. requires: all_of: - action: kinesisvideo:ConnectAsViewer @@ -808,15 +834,16 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-28-reach-a-lambda-execution-role-through-unsafe-workflow-i provider: aws service: states title: Reach a Lambda execution role through unsafe workflow input deserialization - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesstartexecution---input-injection-into-dangerous-sinks - summary: StartExecution -> exact state-machine Lambda role only when reviewed input reaches a dangerous sink. - Exact source, target and prerequisite proof are required. + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesstartexecution---input-injection-into-dangerous-sinks + summary: StartExecution -> exact state-machine Lambda role only when reviewed input reaches a dangerous sink. Exact + source, target and prerequisite proof are required. requires: all_of: - action: states:StartExecution @@ -839,13 +866,14 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-29-redirect-a-credentialed-step-functions-http-task-to-cap provider: aws service: states title: Redirect a credentialed Step Functions HTTP Task to capture its connection credential - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesstartexecution---input-injection-into-dangerous-sinks + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-stepfunctions-post-exploitation/README.md#statesstartexecution---input-injection-into-dangerous-sinks summary: StartExecution -> HTTP Task connection credential exposure, conditional on exact input mapping and usable secret. Exact source, target and prerequisite proof are required. requires: @@ -857,28 +885,29 @@ selector: aws_challenge_fact: aws-v3-29-redirect-a-credentialed-step-functions-http-task-to-cap scope: same_account - aggregate_as: Verified Redirect a credentialed Step Functions HTTP Task to capture its connection credential - targets in {account} + aggregate_as: Verified Redirect a credentialed Step Functions HTTP Task to capture its connection credential targets + in {account} grants: - HTTP Task connection credential exposure, conditional on exact input mapping and usable se conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - If URL is fixed or credential destination cannot be controlled, no edge. + description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; If + URL is fixed or credential destination cannot be controlled, no edge. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-30-inject-a-lambda-durable-callback-result-that-triggers-a provider: aws service: lambda title: Inject a Lambda durable callback result that triggers a privileged workflow branch - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambda-durable-callback-result-injection - summary: SendDurableExecutionCallback* -> exact durable function role, conditional on live callback and unsafe - branch. Exact source, target and prerequisite proof are required. + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambda-durable-callback-result-injection + summary: SendDurableExecutionCallback* -> exact durable function role, conditional on live callback and unsafe branch. + Exact source, target and prerequisite proof are required. requires: all_of: - action: lambda:SendDurableExecutionCallbackSuccess @@ -888,21 +917,21 @@ selector: aws_challenge_fact: aws-v3-30-inject-a-lambda-durable-callback-result-that-triggers-a scope: same_account - aggregate_as: Verified Inject a Lambda durable callback result that triggers a privileged workflow branch targets - in {account} + aggregate_as: Verified Inject a Lambda durable callback result that triggers a privileged workflow branch targets in + {account} grants: - exact durable function role, conditional on live callback and unsafe branch. conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - A callback permission cannot manufacture a live callback or privileged branch. + description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; A + callback permission cannot manufacture a live callback or privileged branch. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-31-steal-a-different-user-s-cached-iam-identity-center-acc provider: aws service: challenge-evidence @@ -919,8 +948,8 @@ selector: aws_challenge_fact: aws-v3-31-steal-a-different-user-s-cached-iam-identity-center-acc scope: same_account - aggregate_as: Verified Steal a different user's cached IAM Identity Center access token and exchange it for - assigned role credentials targets in {account} + aggregate_as: Verified Steal a different user's cached IAM Identity Center access token and exchange it for assigned + role credentials targets in {account} grants: - exact victim-assigned permission-set role. conditions: @@ -930,15 +959,15 @@ confidence: conditional severity: high mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal - is inferred from configuration. + notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is + inferred from configuration. - id: aws-v3-32-reuse-another-user-s-cached-sts-role-credentials-or-sta provider: aws service: challenge-evidence title: Reuse another user's cached STS role credentials or static IAM user keys from local AWS CLI files source: src/pentesting-cloud/aws-security/aws-services/aws-iam-enum.md#local-enumeration - summary: Host file read of cached STS/static key -> exact owner principal. Exact external source and target proof - are required. + summary: Host file read of cached STS/static key -> exact owner principal. Exact external source and target proof are + required. requires: {} source_kind: aws_challenge_foothold source_selector: @@ -948,26 +977,27 @@ selector: aws_challenge_fact: aws-v3-32-reuse-another-user-s-cached-sts-role-credentials-or-sta scope: same_account - aggregate_as: Verified Reuse another user's cached STS role credentials or static IAM user keys from local AWS - CLI files targets in {account} + aggregate_as: Verified Reuse another user's cached STS role credentials or static IAM user keys from local AWS CLI + files targets in {account} grants: - exact owner principal. conditions: - id: exact_external_foothold - description: No edge from mere existence of a shared host or AWS CLI installation. Source evidence must prove - local control for the exact target. + description: No edge from mere existence of a shared host or AWS CLI installation. Source evidence must prove local + control for the exact target. confidence: conditional severity: high mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal - is inferred from configuration. + notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is + inferred from configuration. - id: aws-v3-33-read-aws-vpn-client-temporary-credentials-from-another provider: aws service: challenge-evidence title: Read AWS VPN Client temporary credentials from another user's local profile - source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md#local-enumeration - summary: Host file read of AWS VPN temporary credentials -> exact issuing role, conditional on current token. - Exact external source and target proof are required. + source: + src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md#local-enumeration + summary: Host file read of AWS VPN temporary credentials -> exact issuing role, conditional on current token. Exact + external source and target proof are required. requires: {} source_kind: aws_challenge_foothold source_selector: @@ -988,13 +1018,14 @@ confidence: conditional severity: high mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal - is inferred from configuration. + notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is + inferred from configuration. - id: aws-v3-34-change-an-authorization-tag-to-satisfy-a-tag-conditione provider: aws service: tag title: Change an authorization tag to satisfy a tag-conditioned policy and gain higher permissions - source: src/pentesting-cloud/aws-security/aws-services/aws-resource-groups-tagging-api-enum.md#bulk-tagging-and-tag-sync-boundaries + source: + src/pentesting-cloud/aws-security/aws-services/aws-resource-groups-tagging-api-enum.md#bulk-tagging-and-tag-sync-boundaries summary: Authorized tag mutation -> precise newly allowed IAM action, then any existing technique enabled by that action. The evidence record must name the native tag action, exact policy condition and newly granted action. requires: @@ -1011,8 +1042,8 @@ - exact newly allowed action conditions: - id: native_tag_and_condition_proof - description: tag:TagResources alone does not imply native tag authorization; recompute all Deny, boundary and - SCP controls. + description: tag:TagResources alone does not imply native tag authorization; recompute all Deny, boundary and SCP + controls. confidence: conditional severity: high mitigation: Restrict both tag:TagResources and native service tagging actions on policy-conditioned resources. @@ -1045,16 +1076,17 @@ confidence: conditional severity: high mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal - is inferred from configuration. + notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is + inferred from configuration. - id: aws-v3-36-chime-createappinstanceuser-admin provider: aws service: chime title: Chime CreateAppInstanceUser/Admin - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md#chimecreateappinstanceuser--chimecreateappinstanceadmin - summary: 'Add `service_plane: chime` on `aws_service_plane_admin` with `target.selector.chime_app_instance_arn: - ...`; require `chime:CreateAppInstanceUser` and `chime:CreateAppInstanceAdmin` or the exact existing-user admin - grant on that AppInstance. Exact source, target and prerequisite proof are required.' + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md#chimecreateappinstanceuser--chimecreateappinstanceadmin + summary: 'Add `service_plane: chime` on `aws_service_plane_admin` with `target.selector.chime_app_instance_arn: ...`; require + `chime:CreateAppInstanceUser` and `chime:CreateAppInstanceAdmin` or the exact existing-user admin grant on that AppInstance. + Exact source, target and prerequisite proof are required.' requires: all_of: - action: chime:CreateAppInstanceUser @@ -1078,74 +1110,14 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. -- id: aws-v3-37-scp-guardrail-removal - provider: aws - service: organizations - title: SCP guardrail removal - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#dismantling-scp-guardrails--organizationsdetachpolicy-updatepolicy-disablepolicytype-moveaccount - summary: '`target.selector.aws_exact_scp_deny_lifted: true`, `target.outcome: blocker_removal`; require the exact - `organizations:DetachPolicy/UpdatePolicy/DisablePolicyType/MoveAccount/LeaveOrganization` path. Exact source, - target and prerequisite proof are required.' - requires: - all_of: - - action: organizations:DetachPolicy - resource: '*' - target: - kind: aws_verified_authority - selector: - aws_challenge_fact: aws-v3-37-scp-guardrail-removal - scope: same_account - aggregate_as: Verified SCP guardrail removal targets in {account} - grants: - - '`target.selector.aws_exact_scp_deny_lifted: true`, `target.outcome: blocker_removal`; requ' - conditions: - - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - Exact attached SCP Deny and blocked permission recomputation for a named account/principal. - blockers: - - scp_or_boundary_deny - confidence: conditional - severity: high - mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. -- id: aws-v3-38-organizations-resource-policy - provider: aws - service: organizations - title: Organizations resource policy - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationsputresourcepolicy--delegate-organizations-itself-to-a-member-account - summary: '`target.selector.aws_org_resource_policy_delegates_to_controlled_account: true`; require `organizations:PutResourcePolicy`. - Exact source, target and prerequisite proof are required.' - requires: - all_of: - - action: organizations:PutResourcePolicy - resource: '*' - target: - kind: aws_verified_authority - selector: - aws_challenge_fact: aws-v3-38-organizations-resource-policy - scope: same_account - aggregate_as: Verified Organizations resource policy targets in {account} - grants: - - '`target.selector.aws_org_resource_policy_delegates_to_controlled_account: true`; require `' - conditions: - - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - Controlled member account plus precise resulting Organizations policy permission. - blockers: - - scp_or_boundary_deny - confidence: conditional - severity: high - mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-39-appstream-user-pool-stack-login provider: aws service: appstream title: AppStream user-pool stack login - source: src/pentesting-cloud/aws-security/aws-persistence/aws-appstream-persistence/README.md#appstreamcreateuser--batchassociateuserstack--regional-user-pool-foothold + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-appstream-persistence/README.md#appstreamcreateuser--batchassociateuserstack--regional-user-pool-foothold summary: '`target.selector.appstream_user_pool_stack_fleet_role: true`; target exact `aws_role`; require `appstream:CreateUser`, `BatchAssociateUserStack`, and user-session eligibility. Exact source, target and prerequisite proof are required.' requires: @@ -1171,13 +1143,14 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-40-cloudwatch-omni-space-admin provider: aws service: cloudwatch title: CloudWatch Omni Space Admin - source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-omni-persistence/README.md#cloudwatchcreateaccessgrant--install-a-space-admin-principal + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-cloudwatch-omni-persistence/README.md#cloudwatchcreateaccessgrant--install-a-space-admin-principal summary: 'Add `service_plane: cloudwatch-omni`; `target.selector.omni_space_arn: ...`; require exact `cloudwatch:CreateAccessGrant`. Exact source, target and prerequisite proof are required.' requires: @@ -1201,13 +1174,14 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-41-elasticache-attached-rbac-user-takeover provider: aws service: elasticache title: ElastiCache attached RBAC user takeover - source: src/pentesting-cloud/aws-security/aws-persistence/aws-elasticache-persistence/README.md#elasticachemodifyuser--hijack-or-widen-an-existing-rbac-user + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-elasticache-persistence/README.md#elasticachemodifyuser--hijack-or-widen-an-existing-rbac-user summary: 'Add `service_plane: elasticache` and exact replication-group selector; require row-specific ModifyUser/CreateUser/ModifyUserGroup or ModifyReplicationGroup. Exact source, target and prerequisite proof are required.' requires: @@ -1231,13 +1205,14 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-42-elasticache-full-access-user-group provider: aws service: elasticache title: ElastiCache full-access user group - source: src/pentesting-cloud/aws-security/aws-persistence/aws-elasticache-persistence/README.md#elasticachecreateuser-elasticachecreateusergroup--elasticachemodifyusergroup--plant-a-full-access-rbac-user + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-elasticache-persistence/README.md#elasticachecreateuser-elasticachecreateusergroup--elasticachemodifyusergroup--plant-a-full-access-rbac-user summary: 'Add `service_plane: elasticache` and exact replication-group selector; require row-specific ModifyUser/CreateUser/ModifyUserGroup or ModifyReplicationGroup. Exact source, target and prerequisite proof are required.' requires: @@ -1263,13 +1238,14 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-43-memorydb-full-access-acl-user provider: aws service: memorydb title: MemoryDB full-access ACL user - source: src/pentesting-cloud/aws-security/aws-persistence/aws-memorydb-persistence/README.md#memorydbcreateuser-memorydbcreateacl--memorydbupdateacl--plant-a-full-access-acl-user + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-memorydb-persistence/README.md#memorydbcreateuser-memorydbcreateacl--memorydbupdateacl--plant-a-full-access-acl-user summary: 'Add `service_plane: memorydb` and exact cluster selector; require row-specific `memorydb:CreateUser/UpdateUser/UpdateACL`. Exact source, target and prerequisite proof are required.' requires: @@ -1295,13 +1271,14 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-44-memorydb-attached-user-takeover provider: aws service: memorydb title: MemoryDB attached user takeover - source: src/pentesting-cloud/aws-security/aws-persistence/aws-memorydb-persistence/README.md#memorydbupdateuser--hijack-or-widen-an-existing-acl-user + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-memorydb-persistence/README.md#memorydbupdateuser--hijack-or-widen-an-existing-acl-user summary: 'Add `service_plane: memorydb` and exact cluster selector; require row-specific `memorydb:CreateUser/UpdateUser/UpdateACL`. Exact source, target and prerequisite proof are required.' requires: @@ -1325,16 +1302,17 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-45-chime-sdk-admin-persistence provider: aws service: chime title: Chime SDK admin persistence - source: src/pentesting-cloud/aws-security/aws-persistence/aws-chime-sdk-persistence/README.md#add-an-attacker-controlled-messaging-identity - summary: 'Add `service_plane: chime` on `aws_service_plane_admin` with `target.selector.chime_app_instance_arn: - ...`; require `chime:CreateAppInstanceUser` and `chime:CreateAppInstanceAdmin` or the exact existing-user admin - grant on that AppInstance. Exact source, target and prerequisite proof are required.' + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-chime-sdk-persistence/README.md#add-an-attacker-controlled-messaging-identity + summary: 'Add `service_plane: chime` on `aws_service_plane_admin` with `target.selector.chime_app_instance_arn: ...`; require + `chime:CreateAppInstanceUser` and `chime:CreateAppInstanceAdmin` or the exact existing-user admin grant on that AppInstance. + Exact source, target and prerequisite proof are required.' requires: all_of: - action: chime:CreateAppInstanceAdmin @@ -1349,20 +1327,21 @@ - 'Add `service_plane: chime` on `aws_service_plane_admin` with `target.selector.chime_app_in' conditions: - id: exact_verified_prerequisites - description: The AppInstanceAdmin mutation must cover the exact AppInstance and an existing attacker-controlled - user or bot ARN; continued messaging access needs separate grants. + description: The AppInstanceAdmin mutation must cover the exact AppInstance and an existing attacker-controlled user + or bot ARN; continued messaging access needs separate grants. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-46-sagemaker-domain-lifecycle provider: aws service: sagemaker title: SageMaker domain lifecycle - source: src/pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence/README.md#set-lifecycle-configuration-on-sagemaker-studio + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-sagemaker-persistence/README.md#set-lifecycle-configuration-on-sagemaker-studio summary: Domain lifecycle-config write -> exact inheriting SageMaker Studio app role on later start. Exact source, target and prerequisite proof are required. requires: @@ -1386,16 +1365,17 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-47-connect-createuser provider: aws service: connect title: Connect CreateUser - source: src/pentesting-cloud/aws-security/aws-persistence/aws-connect-persistence/README.md#create-a-durable-connect-administrator - summary: 'Existing `service_plane: connect`; add `target.selector.connect_create_admin_user_request: true`; require - `connect:CreateUser` on generated user, selected security profile and routing profile resource ARNs. Exact source, - target and prerequisite proof are required.' + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-connect-persistence/README.md#create-a-durable-connect-administrator + summary: 'Existing `service_plane: connect`; add `target.selector.connect_create_admin_user_request: true`; require `connect:CreateUser` + on generated user, selected security profile and routing profile resource ARNs. Exact source, target and prerequisite + proof are required.' requires: all_of: - action: connect:CreateUser @@ -1417,13 +1397,14 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-48-redshift-serverless-admin-reset provider: aws service: redshift-serverless title: Redshift Serverless ADMIN reset - source: src/pentesting-cloud/aws-security/aws-persistence/aws-redshift-persistence/README.md#redshift-serverlessupdatenamespace---reset-the-serverless-database-administrator + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-redshift-persistence/README.md#redshift-serverlessupdatenamespace---reset-the-serverless-database-administrator summary: 'Add `service_plane: redshift-serverless` and namespace selector; require `redshift-serverless:UpdateNamespace` on that namespace with admin password reset. Exact source, target and prerequisite proof are required.' requires: @@ -1447,15 +1428,16 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-49-healthlake-smart-authorizer provider: aws service: healthlake title: HealthLake SMART authorizer - source: src/pentesting-cloud/aws-security/aws-persistence/aws-healthlake-persistence/README.md#take-over-smart-on-fhir-authorization - summary: Authorizer replacement -> exact HealthLake datastore FHIR service plane through a trusted service role. - Exact source, target and prerequisite proof are required. + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-healthlake-persistence/README.md#take-over-smart-on-fhir-authorization + summary: Authorizer replacement -> exact HealthLake datastore FHIR service plane through a trusted service role. Exact + source, target and prerequisite proof are required. requires: all_of: - action: healthlake:UpdateFHIRDatastore @@ -1471,21 +1453,23 @@ conditions: - id: exact_verified_prerequisites description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - Dynamic Lambda return role is not inferred from config; role candidate must be exact and token behavior conditional. + Dynamic Lambda return role is not inferred from config; role candidate must be exact and token behavior + conditional. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-50-oracle-autonomous-database-admin provider: aws service: odb title: Oracle Autonomous Database ADMIN - source: src/pentesting-cloud/aws-security/aws-persistence/aws-odb-persistence/README.md#retain-oracle-admin-access-with-a-known-password - summary: 'Add `service_plane: odb` and autonomous DB selector; require exact Oracle Database@AWS password update - action. Exact source, target and prerequisite proof are required.' + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-odb-persistence/README.md#retain-oracle-admin-access-with-a-known-password + summary: 'Add `service_plane: odb` and autonomous DB selector; require exact Oracle Database@AWS password update action. + Exact source, target and prerequisite proof are required.' requires: all_of: - action: odb:UpdateAutonomousDatabase @@ -1508,15 +1492,16 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-51-firewall-manager-delegate provider: aws service: fms title: Firewall Manager delegate - source: src/pentesting-cloud/aws-security/aws-persistence/aws-firewall-manager-persistence/README.md#retaining-the-fms-administrator-role - summary: Add exact organization-delegate service-plane target (`fms`, `network-security-manager`, `inspector2`) - scoped to a **controlled member account**; require row-specific delegate action. Exact source, target and prerequisite + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-firewall-manager-persistence/README.md#retaining-the-fms-administrator-role + summary: Add exact organization-delegate service-plane target (`fms`, `network-security-manager`, `inspector2`) scoped + to a **controlled member account**; require row-specific delegate action. Exact source, target and prerequisite proof are required. requires: all_of: @@ -1539,15 +1524,16 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-52-network-security-manager-delegate provider: aws service: network-security-manager title: Network Security Manager delegate - source: src/pentesting-cloud/aws-security/aws-persistence/aws-network-security-manager-persistence/README.md#network-security-managerputadminaccount--retain-delegated-network-security-administration - summary: Add exact organization-delegate service-plane target (`fms`, `network-security-manager`, `inspector2`) - scoped to a **controlled member account**; require row-specific delegate action. Exact source, target and prerequisite + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-network-security-manager-persistence/README.md#network-security-managerputadminaccount--retain-delegated-network-security-administration + summary: Add exact organization-delegate service-plane target (`fms`, `network-security-manager`, `inspector2`) scoped + to a **controlled member account**; require row-specific delegate action. Exact source, target and prerequisite proof are required. requires: all_of: @@ -1570,15 +1556,16 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-53-influxdb-admin-credentials provider: aws service: secretsmanager title: InfluxDB admin credentials - source: src/pentesting-cloud/aws-security/aws-persistence/aws-timestream-persistence/README.md#timestream-for-influxdb-plant-a-native-api-token - summary: 'Add `service_plane: timestream-influxdb` and DB selector; require `secretsmanager:GetSecretValue` on - exact admin secret ARN. Exact source, target and prerequisite proof are required.' + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-timestream-persistence/README.md#timestream-for-influxdb-plant-a-native-api-token + summary: 'Add `service_plane: timestream-influxdb` and DB selector; require `secretsmanager:GetSecretValue` on exact admin + secret ARN. Exact source, target and prerequisite proof are required.' requires: all_of: - action: secretsmanager:GetSecretValue @@ -1600,13 +1587,14 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-54-lightsail-db-master-password provider: aws service: lightsail title: Lightsail DB master password - source: src/pentesting-cloud/aws-security/aws-persistence/aws-lightsail-persistence/README.md#download-instance-ssh-keys--db-passwords + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-lightsail-persistence/README.md#download-instance-ssh-keys--db-passwords summary: 'Add `service_plane: lightsail-relational-db` and exact DB selector; require `lightsail:GetRelationalDatabaseMasterUserPassword`. Exact source, target and prerequisite proof are required.' requires: @@ -1630,15 +1618,16 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-55-opensearch-domain-policy provider: aws service: es title: OpenSearch domain policy - source: src/pentesting-cloud/aws-security/aws-persistence/aws-opensearch-access-policy-persistence/README.md#esupdatedomainconfig--domain-access-policy-takeover - summary: 'Add `service_plane: opensearch` and domain selector; require `es:UpdateDomainConfig` for exact domain - policy. Exact source, target and prerequisite proof are required.' + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-opensearch-access-policy-persistence/README.md#esupdatedomainconfig--domain-access-policy-takeover + summary: 'Add `service_plane: opensearch` and domain selector; require `es:UpdateDomainConfig` for exact domain policy. + Exact source, target and prerequisite proof are required.' requires: all_of: - action: es:UpdateDomainConfig @@ -1660,13 +1649,14 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-56-marketplace-seller-entity-policy provider: aws service: aws-marketplace title: Marketplace seller entity policy - source: src/pentesting-cloud/aws-security/aws-persistence/aws-marketplace-persistence/README.md#aws-marketplaceputresourcepolicy--cross-account-seller-entity-control + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-marketplace-persistence/README.md#aws-marketplaceputresourcepolicy--cross-account-seller-entity-control summary: 'Add `service_plane: aws-marketplace-seller`; exact entity selector; require `aws-marketplace:PutResourcePolicy` and prove resulting `aws-marketplace:StartChangeSet`. Exact source, target and prerequisite proof are required.' requires: @@ -1690,16 +1680,15 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-57-workmail-impersonation-role provider: aws service: workmail title: WorkMail impersonation role source: src/pentesting-cloud/aws-security/aws-services/aws-workmail-enum.md#exact-impersonation-to-mailbox-chain - summary: 'Add `service_plane: workmail-mailbox` with per-mailbox selector; require `workmail:AssumeImpersonationRole` - or `workmail:ResetPassword` on the specific organization/user. Exact source, target and prerequisite proof are - required.' + summary: 'Add `service_plane: workmail-mailbox` with per-mailbox selector; require `workmail:AssumeImpersonationRole` or + `workmail:ResetPassword` on the specific organization/user. Exact source, target and prerequisite proof are required.' requires: all_of: - action: workmail:AssumeImpersonationRole @@ -1721,16 +1710,16 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-58-leaveorganization-scp-escape provider: aws service: organizations title: LeaveOrganization SCP escape - source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/organizations-and-central-account-pivots.md#scp-and-rcp-gaps - summary: '`target.selector.aws_exact_scp_deny_lifted: true`, `target.outcome: blocker_removal`; require the exact - `organizations:DetachPolicy/UpdatePolicy/DisablePolicyType/MoveAccount/LeaveOrganization` path. Exact source, - target and prerequisite proof are required.' + source: + src/pentesting-cloud/aws-security/aws-cross-account-attacks/organizations-and-central-account-pivots.md#scp-and-rcp-gaps + summary: '`target.selector.aws_exact_scp_deny_lifted: true`, `target.outcome: blocker_removal`; require the exact `organizations:DetachPolicy/UpdatePolicy/DisablePolicyType/MoveAccount/LeaveOrganization` + path. Exact source, target and prerequisite proof are required.' requires: all_of: - action: organizations:LeaveOrganization @@ -1746,20 +1735,21 @@ conditions: - id: exact_verified_prerequisites description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - Only if leaving is actually allowed and exact removed SCP Deny unblocks a named action; account trust changes - must be recalculated. + Only if leaving is actually allowed and exact removed SCP Deny unblocks a named action; account trust changes must + be recalculated. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-59-anonymous-cognito-guest-role provider: aws service: challenge-evidence title: Anonymous Cognito guest role - source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum/README.md#guest-identity-credentials + source: + src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum/README.md#guest-identity-credentials summary: Add a **source entry point** `aws_cognito_anonymous_pool_role` rather than making every IAM source anonymous; row 83/84 then use a normal role-to-resource permission edge. Exact external source and target proof are required. requires: {} @@ -1781,13 +1771,14 @@ confidence: conditional severity: high mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal - is inferred from configuration. + notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is + inferred from configuration. - id: aws-v3-60-cognito-classic-flow provider: aws service: challenge-evidence title: Cognito classic flow - source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum/README.md#enhanced-and-basic-authentication-flows + source: + src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum/README.md#enhanced-and-basic-authentication-flows summary: Add a **source entry point** `aws_cognito_anonymous_pool_role` rather than making every IAM source anonymous; row 83/84 then use a normal role-to-resource permission edge. Exact external source and target proof are required. requires: {} @@ -1804,18 +1795,19 @@ - Add a **source entry point** `aws_cognito_anonymous_pool_role` rather than making every IA conditions: - id: exact_external_foothold - description: Basic flow enabled, exact role mapping, OIDC trust, and STS authorization. Source evidence must - prove anonymous control for the exact target. + description: Basic flow enabled, exact role mapping, OIDC trust, and STS authorization. Source evidence must prove + anonymous control for the exact target. confidence: conditional severity: high mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal - is inferred from configuration. + notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is + inferred from configuration. - id: aws-v3-61-public-signup-cognito-role provider: aws service: challenge-evidence title: Public SignUp Cognito role - source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-user-pool-unauthenticated-access/README.md#registration + source: + src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-user-pool-unauthenticated-access/README.md#registration summary: Public SignUp -> authenticated identity-pool role for exact user-pool client, conditional on completing confirmation/challenges. Exact external source and target proof are required. requires: {} @@ -1837,13 +1829,14 @@ confidence: conditional severity: high mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal - is inferred from configuration. + notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is + inferred from configuration. - id: aws-v3-62-cognito-guest-to-dynamodb provider: aws service: challenge-evidence title: Cognito guest to DynamoDB - source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-dynamodb-unauthenticated-access/README.md#cognito-guest-identities-for-dynamodb + source: + src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-dynamodb-unauthenticated-access/README.md#cognito-guest-identities-for-dynamodb summary: Add a **source entry point** `aws_cognito_anonymous_pool_role` rather than making every IAM source anonymous; row 83/84 then use a normal role-to-resource permission edge. Exact external source and target proof are required. requires: {} @@ -1865,13 +1858,14 @@ confidence: conditional severity: high mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal - is inferred from configuration. + notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is + inferred from configuration. - id: aws-v3-63-cognito-guest-to-lex provider: aws service: challenge-evidence title: Cognito guest to Lex - 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 + 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 summary: Add a **source entry point** `aws_cognito_anonymous_pool_role` rather than making every IAM source anonymous; row 83/84 then use a normal role-to-resource permission edge. Exact external source and target proof are required. requires: {} @@ -1893,15 +1887,16 @@ confidence: conditional severity: high mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal - is inferred from configuration. + notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is + inferred from configuration. - id: aws-v3-64-devops-agent-operator-app-idp-swap provider: aws service: aidevops title: DevOps Agent operator app IdP swap - 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 - summary: Controlled external IdP accepted by exact DevOps Agent operator app -> operator service-plane session. - Exact source, target and prerequisite proof are required. + 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 + summary: Controlled external IdP accepted by exact DevOps Agent operator app -> operator service-plane session. Exact + source, target and prerequisite proof are required. requires: all_of: - action: aidevops:DisableOperatorApp @@ -1927,15 +1922,16 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-65-remove-own-explicit-deny provider: aws service: iam title: Remove own explicit Deny - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#policy-and-permission-boundary-deletion - summary: '`target.selector.aws_exact_self_deny_removed: true`, `target.outcome: blocker_removal`; require the - matching IAM Delete*Policy/Detach*Policy action. Exact source, target and prerequisite proof are required.' + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iam-post-exploitation/README.md#policy-and-permission-boundary-deletion + summary: '`target.selector.aws_exact_self_deny_removed: true`, `target.outcome: blocker_removal`; require the matching IAM + Delete*Policy/Detach*Policy action. Exact source, target and prerequisite proof are required.' requires: all_of: - action: iam:DeleteUserPolicy @@ -1957,16 +1953,17 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-66-evs-vmware-admin-secret provider: aws service: evs title: EVS VMware admin secret - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-evs-post-exploitation/README.md#recover-evs-managed-vcf-and-esx-credentials - summary: 'Add `service_plane: evs-vmware-appliance` and exact environment/appliance account selector; require - `evs:GetEnvironment` or service credential-read action plus `secretsmanager:GetSecretValue` on exact linked - secret. Exact source, target and prerequisite proof are required.' + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-evs-post-exploitation/README.md#recover-evs-managed-vcf-and-esx-credentials + summary: 'Add `service_plane: evs-vmware-appliance` and exact environment/appliance account selector; require `evs:GetEnvironment` + or service credential-read action plus `secretsmanager:GetSecretValue` on exact linked secret. Exact source, target and + prerequisite proof are required.' requires: all_of: - action: evs:GetEnvironment @@ -1990,16 +1987,17 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-67-evs-connector-secret provider: aws service: evs title: EVS connector secret - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-evs-post-exploitation/README.md#recover-connector-credentials-for-an-existing-vcf-appliance - summary: 'Add `service_plane: evs-vmware-appliance` and exact environment/appliance account selector; require - `evs:GetEnvironment` or service credential-read action plus `secretsmanager:GetSecretValue` on exact linked - secret. Exact source, target and prerequisite proof are required.' + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-evs-post-exploitation/README.md#recover-connector-credentials-for-an-existing-vcf-appliance + summary: 'Add `service_plane: evs-vmware-appliance` and exact environment/appliance account selector; require `evs:GetEnvironment` + or service credential-read action plus `secretsmanager:GetSecretValue` on exact linked secret. Exact source, target and + prerequisite proof are required.' requires: all_of: - action: evs:GetEnvironment @@ -2023,15 +2021,16 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-68-firewall-manager-admin-action provider: aws service: fms title: Firewall Manager admin action - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#organizationsdescribeorganization--fmsassociateadminaccount-fmsdisassociateadminaccount-fmsputadminaccount - summary: Add exact organization-delegate service-plane target (`fms`, `network-security-manager`, `inspector2`) - scoped to a **controlled member account**; require row-specific delegate action. Exact source, target and prerequisite + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-firewall-manager-post-exploitation/README.md#organizationsdescribeorganization--fmsassociateadminaccount-fmsdisassociateadminaccount-fmsputadminaccount + summary: Add exact organization-delegate service-plane target (`fms`, `network-security-manager`, `inspector2`) scoped + to a **controlled member account**; require row-specific delegate action. Exact source, target and prerequisite proof are required. requires: all_of: @@ -2054,13 +2053,14 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-69-elasticache-legacy-auth-rotation provider: aws service: elasticache title: ElastiCache legacy AUTH rotation - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elasticache-post-exploitation/README.md#elasticachemodifyreplicationgroup--add-an-attacker-known-legacy-auth-token + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-elasticache-post-exploitation/README.md#elasticachemodifyreplicationgroup--add-an-attacker-known-legacy-auth-token summary: 'Add `service_plane: elasticache` and exact replication-group selector; require row-specific ModifyUser/CreateUser/ModifyUserGroup or ModifyReplicationGroup. Exact source, target and prerequisite proof are required.' requires: @@ -2084,15 +2084,16 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-70-inspector-delegated-administrator provider: aws service: inspector2 title: Inspector delegated administrator - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2disabledelegatedadminaccount-inspector2enabledelegatedadminaccount--organizationslistdelegatedadministrators--organizationsenableawsserviceaccess--iamcreateservicelinkedrole - summary: Add exact organization-delegate service-plane target (`fms`, `network-security-manager`, `inspector2`) - scoped to a **controlled member account**; require row-specific delegate action. Exact source, target and prerequisite + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2disabledelegatedadminaccount-inspector2enabledelegatedadminaccount--organizationslistdelegatedadministrators--organizationsenableawsserviceaccess--iamcreateservicelinkedrole + summary: Add exact organization-delegate service-plane target (`fms`, `network-security-manager`, `inspector2`) scoped + to a **controlled member account**; require row-specific delegate action. Exact source, target and prerequisite proof are required. requires: all_of: @@ -2115,16 +2116,16 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-71-workmail-resetpassword provider: aws service: workmail title: WorkMail ResetPassword - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workmail-post-exploitation/README.md#sending-paths--telemetry-gaps - summary: 'Add `service_plane: workmail-mailbox` with per-mailbox selector; require `workmail:AssumeImpersonationRole` - or `workmail:ResetPassword` on the specific organization/user. Exact source, target and prerequisite proof are - required.' + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workmail-post-exploitation/README.md#sending-paths--telemetry-gaps + summary: 'Add `service_plane: workmail-mailbox` with per-mailbox selector; require `workmail:AssumeImpersonationRole` or + `workmail:ResetPassword` on the specific organization/user. Exact source, target and prerequisite proof are required.' requires: all_of: - action: workmail:ResetPassword @@ -2146,5 +2147,73 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. +- id: aws-v3-37-scp-guardrail-removal + provider: aws + service: organizations + title: SCP guardrail removal + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#dismantling-scp-guardrails--organizationsdetachpolicy-updatepolicy-disablepolicytype-moveaccount + summary: Lifts an exact SCP denial from a member principal only when the changed policy/attachment and previously + clipped IAM Allow are verified. + requires: + any_of: + - - action: organizations:DetachPolicy + resource: '*' + - - action: organizations:UpdatePolicy + resource: '*' + - - action: organizations:DisablePolicyType + resource: '*' + - - action: organizations:MoveAccount + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-v3-37-scp-guardrail-removal + scope: same_account + aggregate_as: Verified SCP guardrail removal targets in {account} + grants: + - exact SCP blocker removal + conditions: + - id: exact_verified_prerequisites + description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; + Exact attached SCP Deny and blocked permission recomputation for a named account/principal. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed mutation or read permission and review its exact resource scope. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. +- id: aws-v3-38-organizations-resource-policy + provider: aws + service: organizations + title: Organizations resource policy + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#organizationsputresourcepolicy--delegate-organizations-itself-to-a-member-account + summary: Delegates exact Organizations actions to a controlled member principal only when the resulting policy and + identity allow are verified. + requires: + all_of: + - action: organizations:PutResourcePolicy + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-v3-38-organizations-resource-policy + scope: same_account + aggregate_as: Verified Organizations resource policy targets in {account} + grants: + - verified Organizations API delegation + conditions: + - id: exact_verified_prerequisites + description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; + Controlled member account plus precise resulting Organizations policy permission. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed mutation or read permission and review its exact resource scope. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is + UNKNOWN/unresolved; verified evidence never creates a definite path. diff --git a/src/privilege-escalation-paths/aws/chime.yaml b/src/privilege-escalation-paths/aws/chime.yaml index 339a617265..5dbbf8d060 100644 --- a/src/privilege-escalation-paths/aws/chime.yaml +++ b/src/privilege-escalation-paths/aws/chime.yaml @@ -1,44 +1,4 @@ # AWS chime privilege escalation techniques. # Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). -- id: aws-chime-passrole-mediainsightspipelineconfiguration - provider: aws - service: chime - title: Use a passed media-pipelines role through a media insights pipeline configuration - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-chime-privesc/README.md#chimecreatemediainsightspipelineconfiguration--iampassrole - source_revision: 6fb9ac51fd - summary: The source can exercise the media read and sink privileges (Kinesis Video, Lambda, Kinesis Data Streams, S3, SQS, SNS) of a passable role trusting mediapipelines.chime.amazonaws.com by storing it in a media insights pipeline configuration and starting a pipeline. - requires: - all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: chime:CreateMediaInsightsPipeline - resource: "*" - any_of: - - - action: chime:CreateMediaInsightsPipelineConfiguration - resource: "*" - - - action: chime:UpdateMediaInsightsPipelineConfiguration - resource: "*" - target: - kind: aws_role - selector: - trust_allows_service: mediapipelines.chime.amazonaws.com - resource_permission_covers_target: iam:PassRole - scope: same_account - aggregate_as: "Roles trusting mediapipelines.chime.amazonaws.com passable in {account}" - outcome: impersonation - conditions: - - id: bounded_pipeline_elements - description: The role is used only for the configured source, processors and sinks; no credentials are returned and impact is bounded by the pipeline elements and runtime source/sink validation. - - id: supported_source - description: Starting a pipeline needs a supported Kinesis Video source and valid sink resources. - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict which roles can be passed. - blockers: - - scp_or_boundary_deny - confidence: conditional - severity: medium - mitigation: Restrict iam:PassRole on media-pipelines roles with iam:PassedToService=mediapipelines.chime.amazonaws.com and exact role ARNs, and scope those roles to their own streams and sinks. - references: - - https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_media-pipelines-chime_CreateMediaInsightsPipelineConfiguration.html - notes: Bounded impact - privilege proxy over media and sink resources the role can access, not a role session (DataSync bounded PassRole precedent). +[] diff --git a/src/privilege-escalation-paths/aws/cloudformation.yaml b/src/privilege-escalation-paths/aws/cloudformation.yaml index 69213fe051..9f4ad52e30 100644 --- a/src/privilege-escalation-paths/aws/cloudformation.yaml +++ b/src/privilege-escalation-paths/aws/cloudformation.yaml @@ -5,15 +5,17 @@ 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: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#iampassrole-cloudformationcreatestack source_revision: 171e422299 - summary: The source can obtain the privileges of passable roles trusting cloudformation.amazonaws.com by deploying a template it controls with that service role. + summary: The source can obtain the privileges of passable roles trusting cloudformation.amazonaws.com by deploying a + template it controls with that service role. requires: all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: cloudformation:CreateStack - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: cloudformation:CreateStack + resource: "*" target: kind: aws_role selector: @@ -21,32 +23,37 @@ scope: same_account aggregate_as: "Roles trusting cloudformation.amazonaws.com in {account}" conditions: - - id: passrole_condition_key - description: iam:PassedToService / cloudformation:RoleArn conditions may restrict this. - - id: template_location - description: The template must be supplied from S3 (HTTPS URL) or inline; an S3 location readable by CloudFormation is needed. + - id: passrole_condition_key + description: iam:PassedToService / cloudformation:RoleArn conditions may restrict this. + - id: template_location + description: The template must be supplied from S3 (HTTPS URL) or inline; an S3 location readable by CloudFormation + is needed. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: derived 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. + - 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: + 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 obtain the privileges of passable roles trusting cloudformation.amazonaws.com by updating an existing stack with a template it controls and that role. + summary: The source can obtain the privileges of passable roles trusting cloudformation.amazonaws.com by updating an + existing stack with a template it controls and that role. requires: all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: cloudformation:UpdateStack - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: cloudformation:UpdateStack + resource: "*" target: kind: aws_role selector: @@ -54,12 +61,13 @@ scope: same_account aggregate_as: "Roles trusting cloudformation.amazonaws.com in {account}" 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. + - 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. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: derived severity: critical mitigation: Restrict iam:PassRole on CloudFormation service roles and use the cloudformation:RoleArn condition key. @@ -70,13 +78,15 @@ provider: aws service: cloudformation title: Update a stack that already has a service role - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationupdatestack-and-where-needed-cloudformationsetstackpolicy + 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 obtain the privileges of the service role stored on an existing stack by updating that stack with a template it controls. + summary: The source can obtain the privileges of the service role stored on an existing stack by updating that stack + with a template it controls. requires: all_of: - - action: cloudformation:UpdateStack - resource: "{target.attached_resource_arn}" + - action: cloudformation:UpdateStack + resource: "{target.attached_resource_arn}" target: kind: aws_role selector: @@ -85,13 +95,14 @@ scope: same_account aggregate_as: "Service roles of stacks covered by cloudformation:UpdateStack in {account}" conditions: - - id: stack_policy - description: A stack policy denying updates may require cloudformation:SetStackPolicy. + - id: stack_policy + description: A stack policy denying updates may require cloudformation:SetStackPolicy. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: derived severity: critical - mitigation: Restrict cloudformation:UpdateStack to deployment pipelines; use stack policies and cloudformation:RoleArn conditions. + mitigation: Restrict cloudformation:UpdateStack to deployment pipelines; use stack policies and cloudformation:RoleArn + conditions. references: [] notes: Stacks without a stored service role run with the caller's own permissions and are not targets. @@ -99,17 +110,19 @@ 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: + 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 obtain the privileges of passable roles trusting cloudformation.amazonaws.com by creating and executing a change set with that role. + summary: The source can obtain the privileges of passable roles trusting cloudformation.amazonaws.com by creating and + executing a change set with that role. requires: all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: cloudformation:CreateChangeSet - resource: "*" - - action: cloudformation:ExecuteChangeSet - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: cloudformation:CreateChangeSet + resource: "*" + - action: cloudformation:ExecuteChangeSet + resource: "*" target: kind: aws_role selector: @@ -117,10 +130,10 @@ scope: same_account aggregate_as: "Roles trusting cloudformation.amazonaws.com in {account}" conditions: - - id: stack_policy - description: Updating an existing stack with a deny stack policy may require cloudformation:SetStackPolicy. + - id: stack_policy + description: Updating an existing stack with a deny stack policy may require cloudformation:SetStackPolicy. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: derived severity: critical mitigation: Restrict iam:PassRole on CloudFormation service roles and use the cloudformation:RoleArn condition key. @@ -131,15 +144,17 @@ provider: aws service: cloudformation title: Create and execute a change set on a stack that already has a service role - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationcreatechangeset-cloudformationexecutechangeset-and-where-needed-cloudformationsetstackpolicy + 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 obtain the privileges of the service role stored on an existing stack by creating and executing a change set with a template it controls. + summary: The source can obtain the privileges of the service role stored on an existing stack by creating and + executing a change set with a template it controls. requires: all_of: - - action: cloudformation:CreateChangeSet - resource: "{target.attached_resource_arn}" - - action: cloudformation:ExecuteChangeSet - resource: "{target.attached_resource_arn}" + - action: cloudformation:CreateChangeSet + resource: "{target.attached_resource_arn}" + - action: cloudformation:ExecuteChangeSet + resource: "{target.attached_resource_arn}" target: kind: aws_role selector: @@ -148,10 +163,10 @@ scope: same_account aggregate_as: "Service roles of stacks covered by cloudformation:CreateChangeSet in {account}" conditions: - - id: stack_policy - description: A deny stack policy may require cloudformation:SetStackPolicy. + - id: stack_policy + description: A deny stack policy may require cloudformation:SetStackPolicy. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: derived severity: critical mitigation: Restrict change-set creation and execution to deployment pipelines. @@ -162,10 +177,11 @@ 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: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#iampassrole-cloudformationcreatestackset--cloudformationupdatestackset source_revision: 6fb9ac51fd - summary: The source can obtain the privileges of the StackSet execution roles in the accounts the passed administration - role can assume, by deploying a template it controls through a self-managed StackSet. + summary: The source can obtain the privileges of the StackSet execution roles in the accounts the passed + administration role can assume, by deploying a template it controls through a self-managed StackSet. pivot_resource_type: aws_stackset_administration_role requires: all_of: @@ -186,40 +202,40 @@ aggregate_as: StackSet execution roles assumable by passable administration roles (from {account}) 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. + 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: CloudFormation must be able to deploy stack instances in the execution role's account and region (account and region enabled, no failure-tolerance abort). - 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. + 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. + 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 each execution role that the pivot can assume: the execution role''s trust allows the - pivot role or its account, and the pivot role''s identity policy allows sts:AssumeRole on it. The Service Authorization - Reference lists iam:PassRole as a dependent action of CreateStackSet and UpdateStackSet and none for CreateStackInstances.' + notes: '{pivot} is the StackSet administration role (a role trusting cloudformation.amazonaws.com that the source can pass). + The target is each execution role that the pivot can assume: the execution role''s trust allows the pivot role or its + account, and the pivot role''s identity policy allows sts:AssumeRole on it. The Service Authorization Reference lists + iam:PassRole as a dependent action of CreateStackSet and UpdateStackSet and none for CreateStackInstances.' - id: aws-cloudformation-updatestackset-attached provider: aws service: cloudformation title: Update an existing self-managed StackSet - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationupdatestackset + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#cloudformationupdatestackset source_revision: 6fb9ac51fd summary: The source can obtain the privileges of the execution roles of an existing self-managed StackSet's stack - instances by updating its template, which CloudFormation deploys through the StackSet's stored administration - role. + instances by updating its template, which CloudFormation deploys through the StackSet's stored administration role. pivot_resource_type: aws_stackset_administration_role requires: all_of: @@ -236,8 +252,8 @@ description: An existing StackSet the source can update must store this administration role; StackSets are not collected, so any administration role trusting cloudformation.amazonaws.com is a candidate pivot. - id: stored_execution_role - description: Without iam:PassRole the update keeps the StackSet's stored ExecutionRoleName, so only execution - roles with that name are reached in practice. + description: Without iam:PassRole the update keeps the StackSet's stored ExecutionRoleName, so only execution roles + with that name are reached in practice. - id: stackset_permission_model description: Service-managed StackSets use service-created execution roles in OU accounts (updated from the management or delegated-admin account) and are not modelled by the pivot. The service-managed variant is covered @@ -246,8 +262,8 @@ - scp_or_boundary_deny confidence: conditional severity: critical - mitigation: Restrict cloudformation:UpdateStackSet to the StackSet administrators and scope execution-role trust - to the administration role ARN. + mitigation: Restrict cloudformation:UpdateStackSet to the StackSet administrators and scope execution-role trust to + the administration role ARN. references: - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-prereqs-self-managed.html notes: The previous selector value attached_to_service cloudformation-stackset resolved to the nonexistent principal @@ -259,13 +275,15 @@ provider: aws service: cloudformation title: Replace a mutable nested-stack template object in S3 - 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: + 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 - summary: The source can obtain (on a later legitimate update) the privileges of the service role of a stack whose nested-stack TemplateURL points to an S3 object the source can overwrite. + summary: The source can obtain (on a later legitimate update) the privileges of the service role of a stack whose + nested-stack TemplateURL points to an S3 object the source can overwrite. requires: all_of: - - action: s3:PutObject - resource: "{target.consumer_input_arn}" + - action: s3:PutObject + resource: "{target.consumer_input_arn}" target: kind: aws_role selector: @@ -274,116 +292,143 @@ scope: same_account aggregate_as: "Service roles of stacks with writable nested templates in {account}" conditions: - - id: delayed_trigger - description: A later parent-stack operation must actually update the nested stack; the source does not control the trigger. - - id: bucket_controls - description: Bucket policy, Object Lock, versioned URLs and KMS key policy must not prevent replacement. + - id: delayed_trigger + description: A later parent-stack operation must actually update the nested stack; the source does not control the + trigger. + - id: bucket_controls + description: Bucket policy, Object Lock, versioned URLs and KMS key policy must not prevent replacement. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high mitigation: Use immutable/versioned template URLs and separate template-publishing permissions from deployment. references: [] - notes: "Requires placeholder {target.consumer_input_arn}: the S3 object ARN referenced as the nested TemplateURL. Gaining the role's privileges for the source's own principal needs a follow-on step (e.g. the poisoned template granting the source access)." + notes: "Requires placeholder {target.consumer_input_arn}: the S3 object ARN referenced as the nested TemplateURL. Gaining + the role's privileges for the source's own principal needs a follow-on step (e.g. the poisoned template granting the source + access)." - 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: + 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. + 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}" - - action: cloudformation:RegisterType - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: cloudformation:RegisterType + resource: "*" any_of: - - - action: cloudformation:CreateResource - resource: "*" - - - action: cloudformation:CreateStack - resource: "*" - - - action: cloudformation:UpdateStack - resource: "*" - - - action: cloudformation:SetTypeConfiguration - resource: "*" + - - action: cloudformation:CreateResource + resource: "*" + - - action: cloudformation:CreateStack + resource: "*" + - - action: cloudformation:UpdateStack + resource: "*" + - - action: cloudformation:SetTypeConfiguration + 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}" + aggregate_as: "CloudFormation extension execution roles (trusting resources.cloudformation.amazonaws.com) passable in + {account}" 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 type must be invoked (Cloud Control CreateResource, a stack operation using the type, or an enabled Hook targeting a later operation); a Hook needs SetTypeConfiguration and a subsequent matching operation. - - id: passrole_condition_key - description: iam:PassedToService conditions on the PassRole grant may restrict passing the execution role. + - 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 type must be invoked (Cloud Control CreateResource, a stack operation using the type, or + an enabled Hook targeting a later operation); a Hook needs SetTypeConfiguration and a subsequent matching + operation. + - id: passrole_condition_key + description: iam:PassedToService conditions on the PassRole grant may restrict passing the execution role. blockers: - - scp_or_boundary_deny + - 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. + 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: Extension execution roles trust resources.cloudformation.amazonaws.com, not cloudformation.amazonaws.com, so the target set is disjoint from stack service roles. cloudformation:ActivateType of a third-party public extension with an execution role is a related path but runs code the source does not author unless it published that extension. + - 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: Extension execution roles trust resources.cloudformation.amazonaws.com, not cloudformation.amazonaws.com, so + the target set is disjoint from stack service roles. cloudformation:ActivateType of a third-party public extension + with an execution role is a related path but runs code the source does not author unless it published that + extension. - id: aws-cloudformation-ssm-parameter-poisoning provider: aws service: cloudformation title: Overwrite a Parameter Store value that a stack resolves as a template parameter - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudformation-privesc/README.md#ssmputparameter-on-a-cloudformation-supplied-parameter--delayed-policy-injection + 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 - summary: The source can obtain (on a later legitimate stack update) the privileges of a stack's stored service role when a security-sensitive property of that stack is taken from an SSM parameter-typed template parameter whose Parameter Store value the source can overwrite. + summary: A later stack update attaches an attacker-selected policy to a role the source can assume, increasing the + authority of that role. requires: all_of: - - action: ssm:PutParameter - resource: "{target.consumer_input_arn}" + - action: ssm:PutParameter + resource: '*' + - action: sts:AssumeRole + resource: '*' target: - kind: aws_role + kind: aws_verified_authority selector: - attached_to_service: cloudformation - consumer_input_writable_via: ssm:PutParameter + aws_challenge_fact: aws-cloudformation-ssm-parameter-poisoning scope: same_account - aggregate_as: "Service roles of stacks resolving writable Parameter Store values in {account}" - outcome: workload_execution conditions: - - id: delayed_trigger - description: A later stack update must resolve the parameter again (supplied parameter kept with its previous key); the source does not control the trigger. - - id: consumer_semantics - description: Impact depends on the property consuming the value (policy ARNs, trust principals, AMI IDs, code locations, endpoints); a value used only for non-sensitive settings yields no privilege. - - id: kms_and_tier - description: SecureString parameters with a customer-managed key need kms:Encrypt on that key for the overwrite. + - id: delayed_trigger + description: A later stack update must resolve the parameter again (supplied parameter kept with its previous key); + the source does not control the trigger. + - id: consumer_semantics + description: Impact depends on the property consuming the value (policy ARNs, trust principals, AMI IDs, code + locations, endpoints); a value used only for non-sensitive settings yields no privilege. + - id: kms_and_tier + description: SecureString parameters with a customer-managed key need kms:Encrypt on that key for the overwrite. + - 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 + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Restrict ssm:PutParameter on deployment-consumed parameter namespaces, pin security-sensitive values to reviewed versions or ordinary template parameters, and alert when a parameter write precedes a stack operation that resolves it. + mitigation: Restrict ssm:PutParameter on deployment-consumed parameter namespaces, pin security-sensitive values to + reviewed versions or ordinary template parameters, and alert when a parameter write precedes a stack operation that + resolves it. references: - - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-supplied-parameter-types.html - notes: "{target.consumer_input_arn} is the Parameter Store parameter ARN named by the stack's SSM parameter-typed template parameter; that mapping is not collected, so the edge is unknown until it is. Same modelling as aws-cloudformation-nested-template-s3-poisoning. Unversioned dynamic references are not guaranteed to refresh and are not covered." - + - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/cloudformation-supplied-parameter-types.html + notes: '{target.consumer_input_arn} is the Parameter Store parameter ARN named by the stack''s SSM parameter-typed template + parameter; that mapping is not collected, so the edge is unknown until it is. Same modelling as aws-cloudformation-nested-template-s3-poisoning. + Unversioned dynamic references are not guaranteed to refresh and are not covered. Required collector evidence is absent + from current snapshots; missing evidence remains UNKNOWN/unresolved.' - 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-cross-account-attacks/organizations-and-central-account-pivots.md#cloudformation-stacksets + source: + src/pentesting-cloud/aws-security/aws-cross-account-attacks/organizations-and-central-account-pivots.md#cloudformation-stacksets source_revision: 6fb9ac51fd - summary: A management-account (or delegated-administrator) principal that can create or update service-managed StackSets can deploy templates it controls into member accounts of the targeted OUs through the administrator execution roles StackSets creates there, gaining control of those accounts. + summary: A management-account (or delegated-administrator) principal that can create or update service-managed + StackSets can deploy templates it controls into member accounts of the targeted OUs through the administrator + execution roles StackSets creates there, gaining control of those accounts. requires: any_of: - - - action: cloudformation:CreateStackSet - resource: "arn:aws:cloudformation:*:{source.account}:stackset/*" - bind: stackset - - action: cloudformation:CreateStackInstances - resource: "arn:aws:cloudformation:*:{source.account}:stackset/*" - bind: stackset - - - action: cloudformation:UpdateStackSet - resource: "arn:aws:cloudformation:*:{source.account}:stackset/*" + - - action: cloudformation:CreateStackSet + resource: "arn:aws:cloudformation:*:{source.account}:stackset/*" + bind: stackset + - action: cloudformation:CreateStackInstances + resource: "arn:aws:cloudformation:*:{source.account}:stackset/*" + bind: stackset + - - action: cloudformation:UpdateStackSet + resource: "arn:aws:cloudformation:*:{source.account}:stackset/*" target: kind: aws_account_admin selector: @@ -393,23 +438,32 @@ 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 StackSet must use the SERVICE_MANAGED permission model; UpdateStackSet only applies to existing service-managed StackSets, whose targets and auto-deployment settings bound the reached accounts. - - id: delegated_administrator - description: A registered StackSets delegated administrator (CallAs DELEGATED_ADMIN) has the same reach; this entry only draws edges from the management account (see aws-organizations-registerdelegatedadministrator). - - id: management_account_not_targeted - description: Service-managed StackSets never deploy to the management account; member-account SCPs still constrain the template's resources. + - 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 StackSet must use the SERVICE_MANAGED permission model; UpdateStackSet only applies to existing + service-managed StackSets, whose targets and auto-deployment settings bound the reached accounts. + - id: delegated_administrator + description: A registered StackSets delegated administrator (CallAs DELEGATED_ADMIN) has the same reach; this entry + only draws edges from the management account (see aws-organizations-registerdelegatedadministrator). + - 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 + - source_in_org_management_account + - target_in_other_account blockers: - - scp_or_boundary_deny + - 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. + 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 and aws-cloudformation-updatestackset-attached, which model self-managed StackSets only (their service_managed_stacksets / stackset_permission_model conditions). No iam:PassRole is involved. StackSet permission model, trusted-access state and delegated administrators are not collected, so the edge stays conditional. + - 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 and aws-cloudformation-updatestackset-attached, which model + self-managed StackSets only (their service_managed_stacksets / stackset_permission_model conditions). No + iam:PassRole is involved. StackSet permission model, trusted-access state and delegated administrators are not + collected, so the edge stays conditional. diff --git a/src/privilege-escalation-paths/aws/cloudfront.yaml b/src/privilege-escalation-paths/aws/cloudfront.yaml index 089a003def..50754f6f26 100644 --- a/src/privilege-escalation-paths/aws/cloudfront.yaml +++ b/src/privilege-escalation-paths/aws/cloudfront.yaml @@ -5,10 +5,11 @@ 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: + 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. + 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 @@ -19,6 +20,8 @@ resource: '*' - action: lambda:EnableReplication resource: '*' + - action: lambda:DisableReplication + resource: '*' - action: iam:PassRole resource: '{target.arn}' - action: cloudfront:UpdateDistribution @@ -47,5 +50,6 @@ - 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 the replication permission as lambda:EnableReplication*; the concrete action - in the Service Authorization Reference is lambda:EnableReplication. + Lambda@Edge permissions page writes the replication permission as lambda:EnableReplication*; the concrete action in + the Service Authorization Reference is lambda:EnableReplication. The association also requires the concrete + lambda:DisableReplication authorization. diff --git a/src/privilege-escalation-paths/aws/codebuild.yaml b/src/privilege-escalation-paths/aws/codebuild.yaml index 6c7bbd3248..48c73e0261 100644 --- a/src/privilege-escalation-paths/aws/codebuild.yaml +++ b/src/privilege-escalation-paths/aws/codebuild.yaml @@ -5,16 +5,18 @@ 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: + 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. + 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}" - - - action: codebuild:StartBuildBatch - resource: "{target.attached_resource_arn}" + - - action: codebuild:StartBuild + resource: "{target.attached_resource_arn}" + - - action: codebuild:StartBuildBatch + resource: "{target.attached_resource_arn}" target: kind: aws_role selector: @@ -23,25 +25,29 @@ scope: same_account aggregate_as: "Service roles of CodeBuild projects covered by codebuild:StartBuild in {account}" conditions: - - id: override_available - description: StartBuild accepts buildspec, source and environment-variable overrides without extra permissions; StartBuildBatch requires the project to have batch configuration. + - id: override_available + description: StartBuild accepts buildspec, source and environment-variable overrides without extra permissions; + StartBuildBatch requires the project to have batch configuration. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: derived severity: critical - mitigation: Restrict codebuild:StartBuild/StartBuildBatch to pipelines and keep project service roles least-privileged. + 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 selector applies to whichever any_of action matched. Environment-variable overrides (StartBuild Env Var Override subsection) are a variant of the same edge. + - https://docs.aws.amazon.com/codebuild/latest/APIReference/API_StartBuild.html + notes: The selector applies to whichever any_of action matched. 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: + 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. + 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 @@ -51,8 +57,8 @@ selector: attached_to_service: codebuild scope: same_account - aggregate_as: Service roles of CodeBuild projects with sandboxes covered by codebuild:StartCommandExecution - in {account} + aggregate_as: Service roles of CodeBuild projects with sandboxes covered by codebuild:StartCommandExecution in + {account} outcome: workload_execution conditions: - id: running_sandbox @@ -63,18 +69,19 @@ severity: critical mitigation: Restrict sandbox actions and stop idle sandboxes. references: [] - notes: No iam:PassRole, StartBuild or UpdateProject is needed. The API resource is the sandbox ARN; {target.codebuild_sandbox_arn} - expands to sandbox/:* of each project running as the target role. + notes: No iam:PassRole, StartBuild or UpdateProject is needed. The API resource is the sandbox ARN; + {target.codebuild_sandbox_arn} expands to sandbox/:* of each project running as 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: + 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. + 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 @@ -84,15 +91,15 @@ selector: attached_to_service: codebuild scope: same_account - aggregate_as: Service roles of CodeBuild projects with sandboxes covered by codebuild:StartSandboxConnection - in {account} + aggregate_as: Service roles of CodeBuild projects with sandboxes covered by codebuild:StartSandboxConnection in + {account} outcome: workload_execution 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. + 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 @@ -100,28 +107,30 @@ 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 API resource is the sandbox ARN; {target.codebuild_sandbox_arn} - expands to sandbox/:* of each project running as the target role. + notes: Caller-side ssm:StartSession and iam:PassRole are not required. The API resource is the sandbox ARN; + {target.codebuild_sandbox_arn} expands to sandbox/:* of each project running as 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: + 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. + 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}" - - action: codebuild:CreateProject - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: codebuild:CreateProject + resource: "*" any_of: - - - action: codebuild:StartBuild - resource: "*" - - - action: codebuild:StartBuildBatch - resource: "*" + - - action: codebuild:StartBuild + resource: "*" + - - action: codebuild:StartBuildBatch + resource: "*" target: kind: aws_role selector: @@ -129,10 +138,10 @@ scope: same_account aggregate_as: "Roles trusting codebuild.amazonaws.com in {account}" conditions: - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict this. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict this. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: derived severity: critical mitigation: Restrict iam:PassRole on CodeBuild service roles and limit codebuild:CreateProject. @@ -143,20 +152,22 @@ 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: + 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. + 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}" - - action: codebuild:UpdateProject - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: codebuild:UpdateProject + resource: "*" any_of: - - - action: codebuild:StartBuild - resource: "*" - - - action: codebuild:StartBuildBatch - resource: "*" + - - action: codebuild:StartBuild + resource: "*" + - - action: codebuild:StartBuildBatch + resource: "*" target: kind: aws_role selector: @@ -164,10 +175,10 @@ scope: same_account aggregate_as: "Roles trusting codebuild.amazonaws.com in {account}" conditions: - - id: existing_project - description: At least one existing project must be covered by both UpdateProject and StartBuild/StartBuildBatch. + - id: existing_project + description: At least one existing project must be covered by both UpdateProject and StartBuild/StartBuildBatch. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: derived severity: critical mitigation: Restrict iam:PassRole on CodeBuild service roles and codebuild:UpdateProject. @@ -178,18 +189,20 @@ 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: + 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. + 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}" + - action: codebuild:UpdateProject + resource: "{target.attached_resource_arn}" any_of: - - - action: codebuild:StartBuild - resource: "{target.attached_resource_arn}" - - - action: codebuild:StartBuildBatch - resource: "{target.attached_resource_arn}" + - - action: codebuild:StartBuild + resource: "{target.attached_resource_arn}" + - - action: codebuild:StartBuildBatch + resource: "{target.attached_resource_arn}" target: kind: aws_role selector: @@ -198,27 +211,30 @@ scope: same_account aggregate_as: "Service roles of CodeBuild projects covered by codebuild:UpdateProject in {account}" conditions: - - id: automatic_trigger - description: Without StartBuild, a webhook or pipeline trigger may still run the modified project (delayed). + - id: automatic_trigger + description: Without StartBuild, a webhook or pipeline trigger may still run the modified project (delayed). blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: derived severity: critical mitigation: Restrict codebuild:UpdateProject to administrators. references: [] - notes: Largely subsumed by aws-codebuild-startbuild-attached-role (StartBuild alone allows overrides); kept as a distinct permission combination. + notes: Largely subsumed by aws-codebuild-startbuild-attached-role (StartBuild alone allows overrides); kept as a + distinct permission combination. - id: aws-codebuild-s3-source-poisoning provider: aws service: codebuild title: Replace the S3 source object of a CodeBuild project - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#s3putobject-on-a-configured-s3-source-codebuildstartbuild-optional + 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 - summary: The source can obtain (at the next build) the privileges of the service role of a project whose S3 source object (with buildspec) the source can overwrite. + summary: The source can obtain (at the next build) the privileges of the service role of a project whose S3 source + object (with buildspec) the source can overwrite. requires: all_of: - - action: s3:PutObject - resource: "{target.consumer_input_arn}" + - action: s3:PutObject + resource: "{target.consumer_input_arn}" target: kind: aws_role selector: @@ -227,12 +243,14 @@ scope: same_account aggregate_as: "Service roles of CodeBuild projects with writable S3 sources in {account}" conditions: - - id: delayed_trigger - description: A build must run afterwards (source-held codebuild:StartBuild, a schedule or a pipeline); otherwise the edge is delayed. - - id: buildspec_from_source - description: The project must take its buildspec from the source archive (no inline buildspec), or the source contents must otherwise be executed. + - id: delayed_trigger + description: A build must run afterwards (source-held codebuild:StartBuild, a schedule or a pipeline); otherwise the + edge is delayed. + - id: buildspec_from_source + description: The project must take its buildspec from the source archive (no inline buildspec), or the source + contents must otherwise be executed. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high mitigation: Use versioned, immutable source objects and restrict s3:PutObject on build source locations. @@ -243,18 +261,20 @@ 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: + 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. + 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}" + - 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}" + - - action: codebuild:StartCommandExecution + resource: "{target.codebuild_sandbox_arn}" + - - action: codebuild:StartSandboxConnection + resource: "{target.codebuild_sandbox_arn}" target: kind: aws_role selector: @@ -264,28 +284,35 @@ aggregate_as: "Service roles of CodeBuild projects covered by codebuild:StartSandbox in {account}" outcome: workload_execution conditions: - - 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. + - 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 + - scp_or_boundary_deny confidence: derived severity: critical - mitigation: Restrict codebuild:StartSandbox, StartCommandExecution and StartSandboxConnection to trusted operators on exact projects and keep project service roles least-privileged. + 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. + - 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-env-parameter-store-poisoning provider: aws service: codebuild title: Overwrite a Parameter Store value consumed as a CodeBuild environment variable - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#poison-a-secrets_manager-or-parameter_store-environment-value + 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 - summary: The source can obtain (at the next build) the privileges of the service role of a project whose PARAMETER_STORE environment variable feeds privileged build logic and references a parameter the source can overwrite. + summary: The source can obtain (at the next build) the privileges of the service role of a project whose + PARAMETER_STORE environment variable feeds privileged build logic and references a parameter the source can + overwrite. requires: all_of: - - action: ssm:PutParameter - resource: "{target.consumer_input_arn}" + - action: ssm:PutParameter + resource: "{target.consumer_input_arn}" target: kind: aws_role selector: @@ -295,30 +322,37 @@ aggregate_as: "Service roles of CodeBuild projects with writable PARAMETER_STORE variables in {account}" outcome: workload_execution conditions: - - id: delayed_trigger - description: A build must run afterwards (schedule, webhook, pipeline or operator); the write alone does not trigger CodeBuild. - - id: consumer_semantics - description: Code execution or credential substitution depends on how the trusted buildspec and tools use the variable; otherwise the impact is limited to configuration poisoning. + - id: delayed_trigger + description: A build must run afterwards (schedule, webhook, pipeline or operator); the write alone does not trigger + CodeBuild. + - id: consumer_semantics + description: Code execution or credential substitution depends on how the trusted buildspec and tools use the + variable; otherwise the impact is limited to configuration poisoning. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Scope ssm:PutParameter away from build-consumed parameters, validate values before use and prefer immutable, version-reviewed build inputs. + mitigation: Scope ssm:PutParameter away from build-consumed parameters, validate values before use and prefer + immutable, version-reviewed build inputs. references: - - https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html - notes: "{target.consumer_input_arn} is the Parameter Store parameter ARN referenced by the project's PARAMETER_STORE environment variable." + - https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html + notes: "{target.consumer_input_arn} is the Parameter Store parameter ARN referenced by the project's PARAMETER_STORE environment + variable." - id: aws-codebuild-env-secretsmanager-poisoning provider: aws service: codebuild title: Overwrite a Secrets Manager value consumed as a CodeBuild environment variable - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#poison-a-secrets_manager-or-parameter_store-environment-value + 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 - summary: The source can obtain (at the next build) the privileges of the service role of a project whose SECRETS_MANAGER environment variable feeds privileged build logic and references a secret the source can write a new value to. + summary: The source can obtain (at the next build) the privileges of the service role of a project whose + SECRETS_MANAGER environment variable feeds privileged build logic and references a secret the source can write a new + value to. requires: all_of: - - action: secretsmanager:PutSecretValue - resource: "{target.consumer_input_arn}" + - action: secretsmanager:PutSecretValue + resource: "{target.consumer_input_arn}" target: kind: aws_role selector: @@ -328,17 +362,79 @@ aggregate_as: "Service roles of CodeBuild projects with writable SECRETS_MANAGER variables in {account}" outcome: workload_execution conditions: - - id: delayed_trigger - description: A build must run afterwards (schedule, webhook, pipeline or operator); the write alone does not trigger CodeBuild. - - id: consumer_semantics - description: Code execution or credential substitution depends on how the trusted buildspec and tools use the variable; otherwise the impact is limited to configuration poisoning. - - id: version_pinning - description: A variable pinned to a specific version stage or version ID other than AWSCURRENT is not changed by a new current value. + - id: delayed_trigger + description: A build must run afterwards (schedule, webhook, pipeline or operator); the write alone does not trigger + CodeBuild. + - id: consumer_semantics + description: Code execution or credential substitution depends on how the trusted buildspec and tools use the + variable; otherwise the impact is limited to configuration poisoning. + - id: version_pinning + description: A variable pinned to a specific version stage or version ID other than AWSCURRENT is not changed by a + new current value. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Scope secretsmanager:PutSecretValue away from build-consumed secrets, validate values before use and prefer immutable, version-reviewed build inputs. + mitigation: Scope secretsmanager:PutSecretValue away from build-consumed secrets, validate values before use and + prefer immutable, version-reviewed build inputs. references: - - https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html + - https://docs.aws.amazon.com/codebuild/latest/userguide/build-spec-ref.html notes: "{target.consumer_input_arn} is the secret ARN referenced by the project's SECRETS_MANAGER environment variable." +- id: aws-codebuild-ssm-debug-session-role + provider: aws + service: codebuild + title: ssm:StartSession into CodeBuild sandboxes + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codebuild-privesc/README.md#ssm + source_revision: 0b36331 + summary: A live paused CodeBuild debug session gives shell access with the project service role. + requires: + all_of: + - action: ssm:StartSession + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-codebuild-ssm-debug-session-role + scope: same_account + 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: Required collector evidence is absent from current snapshots; missing evidence remains UNKNOWN/unresolved. +- 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: 0b36331 + 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_verified_authority + selector: + aws_challenge_fact: aws-codebuild-plaintext-env-credential + scope: same_account + conditions: + - 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: Required collector evidence is absent from current snapshots; missing evidence remains UNKNOWN/unresolved. diff --git a/src/privilege-escalation-paths/aws/codecommit.yaml b/src/privilege-escalation-paths/aws/codecommit.yaml index ce044ec457..6604261bf9 100644 --- a/src/privilege-escalation-paths/aws/codecommit.yaml +++ b/src/privilege-escalation-paths/aws/codecommit.yaml @@ -2,100 +2,97 @@ # 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). -- id: aws-codecommit-gitpush-pipeline-source +- id: aws-codecommit-gitpush-pipeline-source-cloudformation-role provider: aws service: codecommit - title: Push to a CodeCommit repository branch used as a pipeline source - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codecommit-pipeline-source-privesc/README.md#codecommitgitpush-on-a-codepipeline-source-repository + title: Push to a CodeCommit branch used as the source of a CloudFormation-deploying pipeline + 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 - summary: The source can obtain (at the next execution) the privileges of the roles of downstream pipeline actions - (CodeBuild projects, CloudFormation deploy roles) that build or deploy content from a CodeCommit branch it can - push to. + summary: The source can obtain (at the next execution) the privileges of the CloudFormation deploy-action roles of + pipelines whose CodeCommit source branch it can push to. requires: all_of: - action: codecommit:GitPush - resource: '{target.consumer_input_arn}' + resource: "{target.consumer_input_arn}" target: kind: aws_role selector: - attached_to_service: codepipeline + attached_to_service: cloudformation consumer_input_writable_via: codecommit:GitPush scope: same_account - aggregate_as: Roles of downstream actions of pipelines with writable CodeCommit sources in {account} + aggregate_as: "CloudFormation deploy roles of pipelines with writable CodeCommit sources in {account}" + outcome: workload_execution conditions: - id: delayed_trigger description: An execution must start afterwards (EventBridge source-change rule, schedule, operator or source-held StartPipelineExecution). - - id: source_executed - description: A downstream action must execute content from the pushed revision (buildspec, template, deploy - scripts). + - id: template_from_artifact + description: A CloudFormation deploy action must take its template from the pushed revision. - id: branch_condition description: codecommit:References conditions or approval-rule templates may block direct pushes to the source branch. - id: existing_git_objects - description: GitPush does not include GitPull; the source needs an existing working copy or enough history to - build a valid update. + description: GitPush does not include GitPull; the source needs an existing working copy or enough history to build + a valid update. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict codecommit:GitPush on pipeline source branches with codecommit:References conditions, require - reviewed pull requests, separate source publishers from pipeline runners and add approval gates before privileged - stages. + reviewed pull requests and gate CloudFormation deploy stages with approvals. references: - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodeCommit.html - - https://docs.aws.amazon.com/codecommit/latest/userguide/how-to-conditional-branch.html - notes: '{target.consumer_input_arn} is the CodeCommit repository ARN configured as a pipeline source. attached_to_service - codepipeline means roles of the executing downstream actions, not the pipeline role. Direct CodeBuild sources - are covered by aws-codecommit-gitpush-codebuild-source.' + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CloudFormation.html + notes: Companion of aws-codecommit-gitpush-pipeline-source (CodeBuild project roles). The page names CodeBuild or + deployment roles as the reached consumers; CloudFormation deploy-action roles trust cloudformation.amazonaws.com. + {target.consumer_input_arn} is the CodeCommit repository ARN configured as a pipeline source (not collected, + resolves unknown). - - -- id: aws-codecommit-gitpush-pipeline-source-cloudformation-role +- id: aws-codecommit-gitpush-codebuild-source provider: aws service: codecommit - title: Push to a CodeCommit branch used as the source of a CloudFormation-deploying pipeline - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codecommit-pipeline-source-privesc/README.md#codecommitgitpush-on-a-codepipeline-source-repository + title: Push a CodeCommit source revision executed by a CodeBuild project + source: + src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-codebuild-unauthenticated-access/README.md#buildspecyml source_revision: 6fb9ac51fd - summary: The source can obtain (at the next execution) the privileges of the CloudFormation deploy-action roles of pipelines whose CodeCommit source branch it can push to. + summary: The source can obtain a CodeBuild service role when a project later builds a writable CodeCommit revision. requires: all_of: - - action: codecommit:GitPush - resource: "{target.consumer_input_arn}" + - action: codecommit:GitPush + resource: '{target.consumer_input_arn}' target: kind: aws_role selector: - attached_to_service: cloudformation + attached_to_service: codebuild consumer_input_writable_via: codecommit:GitPush scope: same_account - aggregate_as: "CloudFormation deploy roles of pipelines with writable CodeCommit sources in {account}" + aggregate_as: Service roles of CodeBuild projects with writable CodeCommit sources in {account} outcome: workload_execution conditions: - - id: delayed_trigger - description: An execution must start afterwards (EventBridge source-change rule, schedule, operator or source-held StartPipelineExecution). - - id: template_from_artifact - description: A CloudFormation deploy action must take its template from the pushed revision. - - id: branch_condition - description: codecommit:References conditions or approval-rule templates may block direct pushes to the source branch. - - id: existing_git_objects - description: GitPush does not include GitPull; the source needs an existing working copy or enough history to build a valid update. + - id: delayed_trigger + description: A webhook, schedule, pipeline, or authorized operator must run a build after the push. + - id: source_executed + description: The project must execute buildspec or source content from the pushed revision. + - id: branch_condition + description: Branch protection or codecommit:References conditions may prevent the push. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional - severity: high - mitigation: Restrict codecommit:GitPush on pipeline source branches with codecommit:References conditions, require reviewed pull requests and gate CloudFormation deploy stages with approvals. - references: - - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodeCommit.html - - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CloudFormation.html - notes: Companion of aws-codecommit-gitpush-pipeline-source (CodeBuild project roles). The page names CodeBuild or deployment roles as the reached consumers; CloudFormation deploy-action roles trust cloudformation.amazonaws.com. {target.consumer_input_arn} is the CodeCommit repository ARN configured as a pipeline source (not collected, resolves unknown). - -- id: aws-codecommit-gitpush-codebuild-source + severity: critical + mitigation: Restrict CodeCommit pushes to repositories and branches used by privileged CodeBuild projects and review + buildspec changes. + references: [] + notes: The CodeCommit repository ARN is {target.consumer_input_arn}; the target is the directly consuming CodeBuild + project role. +- id: aws-codecommit-gitpush-pipeline-source provider: aws service: codecommit - title: Push a CodeCommit source revision executed by a CodeBuild project - source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-codebuild-unauthenticated-access/README.md#buildspecyml + title: Push to a CodeCommit repository branch used as a 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 - summary: The source can obtain a CodeBuild service role when a project later builds a writable CodeCommit revision. + summary: The source may execute pushed code under a downstream CodeBuild project role at the next pipeline execution. requires: all_of: - action: codecommit:GitPush @@ -106,21 +103,30 @@ attached_to_service: codebuild consumer_input_writable_via: codecommit:GitPush scope: same_account - aggregate_as: Service roles of CodeBuild projects with writable CodeCommit sources in {account} - outcome: workload_execution + aggregate_as: CodeBuild roles of pipeline actions consuming writable CodeCommit sources conditions: - id: delayed_trigger - description: A webhook, schedule, pipeline, or authorized operator must run a build after the push. + description: An execution must start afterwards (EventBridge source-change rule, schedule, operator or source-held + StartPipelineExecution). - id: source_executed - description: The project must execute buildspec or source content from the pushed revision. + description: A downstream action must execute content from the pushed revision (buildspec, template, deploy + scripts). - id: branch_condition - description: Branch protection or codecommit:References conditions may prevent the push. + description: codecommit:References conditions or approval-rule templates may block direct pushes to the source + branch. + - id: existing_git_objects + description: GitPush does not include GitPull; the source needs an existing working copy or enough history to build + a valid update. blockers: - scp_or_boundary_deny confidence: conditional - severity: critical - mitigation: Restrict CodeCommit pushes to repositories and branches used by privileged CodeBuild projects and - review buildspec changes. - references: [] - notes: The CodeCommit repository ARN is {target.consumer_input_arn}; the target is the directly consuming CodeBuild - project role. + severity: high + mitigation: Restrict codecommit:GitPush on pipeline source branches with codecommit:References conditions, require + reviewed pull requests, separate source publishers from pipeline runners and add approval gates before privileged + stages. + references: + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CodeCommit.html + - https://docs.aws.amazon.com/codecommit/latest/userguide/how-to-conditional-branch.html + notes: CodePipeline transports source artifacts but does not execute the pushed code. CloudFormation deployment roles + are covered separately by aws-codecommit-gitpush-pipeline-source-cloudformation-role. The + repository/branch-to-consumer join is unresolved without pipeline source inventory. diff --git a/src/privilege-escalation-paths/aws/codepipeline.yaml b/src/privilege-escalation-paths/aws/codepipeline.yaml index 280dee1249..cc2e9bf88b 100644 --- a/src/privilege-escalation-paths/aws/codepipeline.yaml +++ b/src/privilege-escalation-paths/aws/codepipeline.yaml @@ -5,19 +5,21 @@ provider: aws service: codepipeline title: Create a pipeline and CodeBuild project with passed roles and start it - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#iampassrole-codepipelinecreatepipeline-codebuildcreateproject-codepipelinestartpipelineexecution + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#iampassrole-codepipelinecreatepipeline-codebuildcreateproject-codepipelinestartpipelineexecution source_revision: 171e422299 - summary: The source can obtain the privileges of passable roles trusting codebuild.amazonaws.com by running a build it controls from a pipeline it creates. + summary: The source can obtain the privileges of passable roles trusting codebuild.amazonaws.com by running a build it + controls from a pipeline it creates. requires: all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: codepipeline:CreatePipeline - resource: "*" - - action: codebuild:CreateProject - resource: "*" - - action: codepipeline:StartPipelineExecution - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: codepipeline:CreatePipeline + resource: "*" + - action: codebuild:CreateProject + resource: "*" + - action: codepipeline:StartPipelineExecution + resource: "*" target: kind: aws_role selector: @@ -25,33 +27,37 @@ scope: same_account aggregate_as: "Roles trusting codebuild.amazonaws.com in {account}" conditions: - - id: passable_pipeline_role - description: iam:PassRole must also cover a role trusting codepipeline.amazonaws.com for the pipeline itself, and that role must be able to start the CodeBuild project. - - id: readable_source - description: The pipeline needs a source it can read (S3, ECR, connection). + - id: passable_pipeline_role + description: iam:PassRole must also cover a role trusting codepipeline.amazonaws.com for the pipeline itself, and + that role must be able to start the CodeBuild project. + - id: readable_source + description: The pipeline needs a source it can read (S3, ECR, connection). blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: critical mitigation: Restrict iam:PassRole on CodeBuild and CodePipeline service roles. references: [] - notes: Roles trusting codepipeline.amazonaws.com are not targets (the pipeline role does not run arbitrary code itself). + notes: Roles trusting codepipeline.amazonaws.com are not targets (the pipeline role does not run arbitrary code + itself). - id: aws-codepipeline-updatepipeline-codebuild-updateproject provider: aws service: codepipeline title: Alter 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: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#codebuildupdateproject-codepipelineupdatepipeline-codepipelinestartpipelineexecution source_revision: 171e422299 - summary: The source can obtain the privileges of the service role of a CodeBuild project used by a pipeline by changing the project/action configuration and starting the pipeline. + summary: The source can obtain the privileges of the service role of a CodeBuild project used by a pipeline by + changing the project/action configuration and starting the pipeline. requires: all_of: - - action: codebuild:UpdateProject - resource: "{target.attached_resource_arn}" - - action: codepipeline:UpdatePipeline - resource: "*" - - action: codepipeline:StartPipelineExecution - resource: "*" + - action: codebuild:UpdateProject + resource: "{target.attached_resource_arn}" + - action: codepipeline:UpdatePipeline + resource: "*" + - action: codepipeline:StartPipelineExecution + resource: "*" target: kind: aws_role selector: @@ -60,10 +66,10 @@ scope: same_account aggregate_as: "Service roles of CodeBuild projects covered by codebuild:UpdateProject in {account}" conditions: - - id: pipeline_can_start_project - description: The pipeline's service role must be allowed to start the covered project. + - id: pipeline_can_start_project + description: The pipeline's service role must be allowed to start the covered project. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: critical mitigation: Restrict codebuild:UpdateProject and codepipeline:UpdatePipeline to administrators. @@ -74,13 +80,15 @@ provider: aws service: codepipeline title: Replace the S3 source object of a pipeline - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#s3putobject-on-a-configured-s3-source-codepipelinestartpipelineexecution-optional + 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 - summary: The source can obtain (at the next execution) the privileges of the roles of downstream actions (CodeBuild projects, CloudFormation deploy roles) of a pipeline whose S3 source object it can overwrite. + summary: The source can obtain (at the next execution) the privileges of the roles of downstream actions (CodeBuild + projects, CloudFormation deploy roles) of a pipeline whose S3 source object it can overwrite. requires: all_of: - - action: s3:PutObject - resource: "{target.consumer_input_arn}" + - action: s3:PutObject + resource: "{target.consumer_input_arn}" target: kind: aws_role selector: @@ -89,29 +97,36 @@ scope: same_account aggregate_as: "Roles of downstream actions of pipelines with writable S3 sources in {account}" conditions: - - id: delayed_trigger - description: An execution must start afterwards (S3 change detection, schedule or source-held StartPipelineExecution). - - id: source_executed - description: A downstream action must execute content from the artifact (buildspec, template). + - id: delayed_trigger + description: An execution must start afterwards (S3 change detection, schedule or source-held + StartPipelineExecution). + - id: source_executed + description: A downstream action must execute content from the artifact (buildspec, template). blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high mitigation: Use versioned, immutable source objects and restrict s3:PutObject on pipeline source keys. references: [] - notes: The evaluator resolves attached_to_service codepipeline to roles trusting codepipeline.amazonaws.com, i.e. the pipeline role, which runs no artifact content; the selector therefore targets CodeBuild project roles (the main code-executing downstream action). CloudFormation deploy-action roles are also reachable but are not modelled here. Pipeline S3 sources are not collected, so {target.consumer_input_arn} resolves unknown. + notes: The evaluator resolves attached_to_service codepipeline to roles trusting codepipeline.amazonaws.com, i.e. the + pipeline role, which runs no artifact content; the selector therefore targets CodeBuild project roles (the main + code-executing downstream action). CloudFormation deploy-action roles are also reachable but are not modelled here. + Pipeline S3 sources are not collected, so {target.consumer_input_arn} resolves unknown. - id: aws-codepipeline-s3-source-poisoning-cloudformation-role provider: aws service: codepipeline title: Replace the S3 source object of a pipeline that deploys through CloudFormation - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-privesc/README.md#s3putobject-on-a-configured-s3-source-codepipelinestartpipelineexecution-optional + 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 - summary: The source can obtain (at the next execution) the privileges of the CloudFormation deploy-action roles of a pipeline whose S3 source object it can overwrite, because the deploy action applies the template carried in that artifact with its stored role. + summary: The source can obtain (at the next execution) the privileges of the CloudFormation deploy-action roles of a + pipeline whose S3 source object it can overwrite, because the deploy action applies the template carried in that + artifact with its stored role. requires: all_of: - - action: s3:PutObject - resource: "{target.consumer_input_arn}" + - action: s3:PutObject + resource: "{target.consumer_input_arn}" target: kind: aws_role selector: @@ -121,18 +136,78 @@ aggregate_as: "CloudFormation deploy roles of pipelines with writable S3 sources in {account}" outcome: workload_execution conditions: - - id: delayed_trigger - description: An execution must start afterwards (S3 change detection, schedule, operator or source-held StartPipelineExecution). - - id: template_from_artifact - description: A CloudFormation deploy action must take its template (or template configuration) from the replaced source artifact. - - id: approval_gates - description: Manual approval or validation stages before the deploy action may stop the poisoned revision. + - id: delayed_trigger + description: An execution must start afterwards (S3 change detection, schedule, operator or source-held + StartPipelineExecution). + - id: template_from_artifact + description: A CloudFormation deploy action must take its template (or template configuration) from the replaced + source artifact. + - id: approval_gates + description: Manual approval or validation stages before the deploy action may stop the poisoned revision. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Use versioned, immutable source objects, restrict s3:PutObject on pipeline source keys to a dedicated publisher, and gate CloudFormation deploy stages with reviewed approvals. + mitigation: Use versioned, immutable source objects, restrict s3:PutObject on pipeline source keys to a dedicated + publisher, and gate CloudFormation deploy stages with reviewed approvals. references: - - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-S3.html - - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CloudFormation.html - notes: Companion of aws-codepipeline-s3-source-poisoning, which targets CodeBuild project roles; the page states the impact reaches the roles of downstream build or deployment actions. The CloudFormation deploy action role trusts cloudformation.amazonaws.com. Pipeline S3 sources are not collected, so {target.consumer_input_arn} resolves unknown. + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-S3.html + - https://docs.aws.amazon.com/codepipeline/latest/userguide/action-reference-CloudFormation.html + notes: Companion of aws-codepipeline-s3-source-poisoning, which targets CodeBuild project roles; the page states the + impact reaches the roles of downstream build or deployment actions. The CloudFormation deploy action role trusts + cloudformation.amazonaws.com. Pipeline S3 sources are not collected, so {target.consumer_input_arn} resolves + unknown. +- id: aws-codepipeline-pollforjobs-artifact-session + provider: aws + service: codepipeline + title: codepipeline:PollForJobs + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-job-credentials-privesc/README.md#codepipelinepollforjobs--custom-action-artifact-credentials + source_revision: 0b36331 + summary: Receive temporary AWS credentials scoped to a pending custom-action job artifact store. + requires: + all_of: + - action: codepipeline:PollForJobs + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-codepipeline-pollforjobs-artifact-session + scope: same_account + conditions: + - 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/codepipeline/latest/APIReference/Welcome.html + notes: Required collector evidence is absent from current snapshots; missing evidence remains UNKNOWN/unresolved. +- id: aws-codepipeline-getjobdetails-artifact-session + provider: aws + service: codepipeline + title: codepipeline:GetJobDetails + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-codepipeline-job-credentials-privesc/README.md#codepipelinegetjobdetails--known-job-artifact-credentials + source_revision: 0b36331 + summary: Receive temporary AWS credentials scoped to a pending custom-action job artifact store. + requires: + all_of: + - action: codepipeline:GetJobDetails + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-codepipeline-getjobdetails-artifact-session + scope: same_account + conditions: + - 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/codepipeline/latest/APIReference/Welcome.html + notes: Required collector evidence is absent from current snapshots; missing evidence remains UNKNOWN/unresolved. diff --git a/src/privilege-escalation-paths/aws/connect.yaml b/src/privilege-escalation-paths/aws/connect.yaml index 9289b290b0..d45cce15eb 100644 --- a/src/privilege-escalation-paths/aws/connect.yaml +++ b/src/privilege-escalation-paths/aws/connect.yaml @@ -2,96 +2,112 @@ # 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. -- id: aws-connect-saml-session-name-impersonation +- id: aws-connect-updateuseridentityinfo-takeover provider: aws service: connect - title: Impersonate a SAML Connect user by choosing the role-session name - 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 + title: Take over a Connect-managed user by changing its email + 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 - summary: The source can obtain the Amazon Connect application privileges (for example the Admin security profile) of any SAML Connect user whose username it can use as its role-session name. + summary: The source can take over CONNECT_MANAGED Amazon Connect users (including administrators) by redirecting their + email and resetting the password. requires: all_of: - - action: connect:GetFederationToken - resource: "{target.resource_arn}" + - action: connect:UpdateUserIdentityInfo + resource: "{target.resource_arn}/agent/*" target: kind: aws_service_plane_admin selector: service_plane: connect - resource_permission_covers_target: connect:GetFederationToken + resource_permission_covers_target: connect:UpdateUserIdentityInfo scope: same_account aggregate_as: "Amazon Connect administrators in {account}" - grants: [Connect Admin security profile] + grants: [Connect user security profiles (Admin when the victim is an administrator)] conditions: - - id: saml_identity_and_session_name - description: The instance uses SAML identity management and the source can assume the federation role with an arbitrary RoleSessionName matching the victim's case-sensitive Connect username. - - id: broad_federation_grant - description: The federation role's connect:GetFederationToken grant is not restricted to the intended per-user identity pattern. + - id: connect_managed_identity + description: Only CONNECT_MANAGED identity; SAML rejects an email change and EXISTING_DIRECTORY identities are + managed by the directory. + - id: admin_victim + description: Administration is reached only when the targeted user holds an administrative security profile. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Prevent arbitrary RoleSessionName selection on Connect federation roles (sts:RoleSessionName conditions) and restrict connect:GetFederationToken to the caller's own user. - notes: Contact-center administration only; the Connect token is not AWS credentials. The requirement is evaluated on the source; when the source reaches it only through the federation role, that role's edge carries the chain. + mitigation: Restrict connect:UpdateUserIdentityInfo to identity administrators and alert on email changes of + administrators followed by password resets. + notes: Contact-center administration only; does not grant the victim's IAM identity. -- id: aws-connect-updateuseridentityinfo-takeover +- id: aws-connect-security-profile-admin provider: aws service: connect - title: Take over a Connect-managed user by changing its email - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-privesc/README.md#take-over-a-connect-managed-user-through-updateuseridentityinfo + title: Grant Connect Admin through security-profile assignment or mutation + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-privesc/README.md#grant-admin-through-security-profile-mutation source_revision: 171e422299 - summary: The source can take over CONNECT_MANAGED Amazon Connect users (including administrators) by redirecting their email and resetting the password. + summary: The source can give a Connect user it controls the Admin security profile, or widen a profile already + assigned to it, gaining Amazon Connect application administration. requires: - all_of: - - action: connect:UpdateUserIdentityInfo + any_of: + - - action: connect:UpdateUserSecurityProfiles resource: "{target.resource_arn}/agent/*" + - action: connect:UpdateUserSecurityProfiles + resource: "{target.resource_arn}/security-profile/*" + - - action: connect:UpdateSecurityProfile + resource: "{target.resource_arn}/security-profile/*" target: kind: aws_service_plane_admin selector: service_plane: connect - resource_permission_covers_target: connect:UpdateUserIdentityInfo scope: same_account aggregate_as: "Amazon Connect administrators in {account}" - grants: [Connect user security profiles (Admin when the victim is an administrator)] + grants: [Connect Admin security profile] conditions: - - id: connect_managed_identity - description: Only CONNECT_MANAGED identity; SAML rejects an email change and EXISTING_DIRECTORY identities are managed by the directory. - - id: admin_victim - description: Administration is reached only when the targeted user holds an administrative security profile. + - id: controlled_connect_user + description: The source must control a Connect user (to assign the profile to, or whose assigned profile it widens). blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Restrict connect:UpdateUserIdentityInfo to identity administrators and alert on email changes of administrators followed by password resets. - notes: Contact-center administration only; does not grant the victim's IAM identity. - -- id: aws-connect-security-profile-admin + mitigation: Restrict connect:UpdateUserSecurityProfiles and connect:UpdateSecurityProfile (connect:InstanceId / + resource tags) and alert on Admin-profile assignment. + notes: UpdateUserSecurityProfiles must allow both the user ARN and every supplied security-profile ARN. Service-level + escalation only, not IAM administrator access. +- id: aws-connect-saml-session-name-impersonation provider: aws service: connect - title: Grant Connect Admin through security-profile assignment or mutation - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-connect-privesc/README.md#grant-admin-through-security-profile-mutation + title: Impersonate a SAML Connect user by choosing the role-session name + 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 - summary: The source can give a Connect user it controls the Admin security profile, or widen a profile already assigned to it, gaining Amazon Connect application administration. + summary: The source can obtain the Amazon Connect application privileges (for example the Admin security profile) of + any SAML Connect user whose username it can use as its role-session name. requires: - any_of: - - - action: connect:UpdateUserSecurityProfiles - resource: "{target.resource_arn}/agent/*" - - action: connect:UpdateUserSecurityProfiles - resource: "{target.resource_arn}/security-profile/*" - - - action: connect:UpdateSecurityProfile - resource: "{target.resource_arn}/security-profile/*" + all_of: + - action: connect:GetFederationToken + resource: '*' target: kind: aws_service_plane_admin selector: service_plane: connect scope: same_account - aggregate_as: "Amazon Connect administrators in {account}" - grants: [Connect Admin security profile] + aggregate_as: Amazon Connect administrators in {account} + grants: + - Connect Admin security profile conditions: - - id: controlled_connect_user - description: The source must control a Connect user (to assign the profile to, or whose assigned profile it widens). + - id: saml_identity_and_session_name + description: The instance uses SAML identity management and the source can assume the federation role with an + arbitrary RoleSessionName matching the victim's case-sensitive Connect username. + - id: broad_federation_grant + description: The federation role's connect:GetFederationToken grant is not restricted to the intended per-user + identity pattern. + - id: resource_pattern + description: A caller-specific /user/${aws:userid} grant can also work when its policy expansion matches the assumed + role session; ordinary instance and /agent ARNs do not authorize GetFederationToken. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Restrict connect:UpdateUserSecurityProfiles and connect:UpdateSecurityProfile (connect:InstanceId / resource tags) and alert on Admin-profile assignment. - notes: UpdateUserSecurityProfiles must allow both the user ARN and every supplied security-profile ARN. Service-level escalation only, not IAM administrator access. + mitigation: Prevent arbitrary RoleSessionName selection on Connect federation roles (sts:RoleSessionName conditions) + and restrict connect:GetFederationToken to the caller's own user. + notes: Contact-center administration only; the Connect token is not AWS credentials. The requirement is evaluated on + the source; when the source reaches it only through the federation role, that role's edge carries the chain. diff --git a/src/privilege-escalation-paths/aws/devicefarm.yaml b/src/privilege-escalation-paths/aws/devicefarm.yaml index 00a963269e..01ef47382b 100644 --- a/src/privilege-escalation-paths/aws/devicefarm.yaml +++ b/src/privilege-escalation-paths/aws/devicefarm.yaml @@ -5,13 +5,15 @@ provider: aws service: devicefarm title: Replace the content of a custom test specification used by privileged runs - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-device-farm-privesc/README.md#trojanize-an-existing-custom-test-specification + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-device-farm-privesc/README.md#trojanize-an-existing-custom-test-specification source_revision: 171e422299 - summary: The source can obtain (at the next run that uses the specification) the privileges of the execution role of Device Farm projects or runs that use a test-spec upload it can update. + summary: The source can obtain (at the next run that uses the specification) the privileges of the execution role of + Device Farm projects or runs that use a test-spec upload it can update. requires: all_of: - - action: devicefarm:UpdateUpload - resource: "{target.consumer_input_arn}" + - action: devicefarm:UpdateUpload + resource: "{target.consumer_input_arn}" target: kind: aws_role selector: @@ -20,32 +22,34 @@ scope: same_account aggregate_as: "Device Farm execution roles of runs using updatable test specs in {account}" conditions: - - id: delayed_run - description: A later run must schedule the same test-spec upload with a project or run execution role. + - id: delayed_run + description: A later run must schedule the same test-spec upload with a project or run execution role. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict devicefarm:UpdateUpload on test-spec uploads to CI publishers and pin test specs per run. references: - - https://docs.aws.amazon.com/devicefarm/latest/APIReference/API_UpdateUpload.html + - https://docs.aws.amazon.com/devicefarm/latest/APIReference/API_UpdateUpload.html notes: "{target.consumer_input_arn} is the *_TEST_SPEC upload ARN; the upload-to-run mapping is not collected." - 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: + 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 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: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: devicefarm:ScheduleRun + resource: "*" + - action: devicefarm:CreateUpload + resource: "*" target: kind: aws_role selector: @@ -54,15 +58,54 @@ scope: same_account aggregate_as: "Roles trusting devicefarm.amazonaws.com passable in {account}" 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: 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 + - 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. + 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-environment-iam-roles.html + notes: The role can be set on the project (CreateProject / UpdateProject) or overridden per run (ScheduleRun + configuration). +- 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. + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-device-farm-privesc/README.md#devicefarmcreateprojectupdateprojectschedulerun--iampassrole + source_revision: 0b36331 + requires: + all_of: + - action: devicefarm:ScheduleRun + resource: '*' + - action: iam:PassRole + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-devicefarm-schedulerun-existing-test-spec-passrole + scope: same_account + 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: Required collector evidence is absent from current snapshots; missing evidence remains UNKNOWN/unresolved. diff --git a/src/privilege-escalation-paths/aws/dynamodb.yaml b/src/privilege-escalation-paths/aws/dynamodb.yaml new file mode 100644 index 0000000000..2a3e1059ea --- /dev/null +++ b/src/privilege-escalation-paths/aws/dynamodb.yaml @@ -0,0 +1,34 @@ +- id: aws-dynamodb-deleteresourcepolicy-guardrail + provider: aws + service: dynamodb + title: Delete DynamoDB resource policy to lift a Deny + summary: Previously denied DynamoDB table action becomes effective for the source. + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-dynamodb-privesc/README.md#dynamodbputresourcepolicy-and-optionally-dynamodbgetresourcepolicy + source_revision: 0b36331 + requires: + all_of: + - action: dynamodb:DeleteResourcePolicy + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-dynamodb-deleteresourcepolicy-guardrail + scope: same_account + conditions: + - id: condition_1 + description: Existing table policy has a Deny that blocks a source-controlled principal's independently allowed + table action. + - id: condition_2 + description: Deletion removes the entire resource policy, not only the Deny; recompute effective IAM after the + deletion and do not assume access when no underlying allow exists. + - 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: Required collector evidence is absent from current snapshots; missing evidence remains UNKNOWN/unresolved. diff --git a/src/privilege-escalation-paths/aws/ec2.yaml b/src/privilege-escalation-paths/aws/ec2.yaml index b947986261..29a44b6dd4 100644 --- a/src/privilege-escalation-paths/aws/ec2.yaml +++ b/src/privilege-escalation-paths/aws/ec2.yaml @@ -5,15 +5,17 @@ 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: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#iampassrole-ec2runinstances source_revision: 171e422299 - summary: The source can obtain the privileges of passable roles trusting ec2.amazonaws.com that are in an instance profile by launching an instance it controls with that profile. + summary: The source can obtain the privileges of passable roles trusting ec2.amazonaws.com that are in an instance + profile by launching an instance it controls with that profile. requires: all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: ec2:RunInstances - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: ec2:RunInstances + resource: "*" target: kind: aws_role selector: @@ -22,18 +24,21 @@ scope: same_account aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" 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. + - 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 + - scp_or_boundary_deny confidence: derived severity: critical - mitigation: Restrict iam:PassRole on EC2 roles with iam:PassedToService and specific role ARNs; require IMDSv2 and monitor RunInstances with instance profiles. + 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. + - 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-runinstances-join-ecs-cluster provider: aws @@ -41,14 +46,15 @@ title: Launch an instance that joins an ECS cluster to receive task roles source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#privesc-to-ecs source_revision: a66f094ede - summary: The source can obtain the privileges of ECS task roles of tasks that get scheduled on an instance it launches into an EC2-backed ECS cluster. + summary: The source can obtain the privileges of ECS task roles of tasks that get scheduled on an instance it launches + into an EC2-backed ECS cluster. requires: all_of: - - action: iam:PassRole - resource: "arn:aws:iam::{source.account}:role/*" - bind: ecs_instance_role - - action: ec2:RunInstances - resource: "*" + - action: iam:PassRole + resource: "arn:aws:iam::{source.account}:role/*" + bind: ecs_instance_role + - action: ec2:RunInstances + resource: "*" target: kind: aws_role selector: @@ -56,31 +62,37 @@ scope: same_account aggregate_as: "ECS task roles of tasks on EC2 capacity in {account}" conditions: - - id: ecs_instance_role_passable - description: iam:PassRole must cover an ECS container-instance role (one with ecs:RegisterContainerInstance permissions, trusting ec2.amazonaws.com). - - id: tasks_scheduled_on_instance - description: Tasks must be placed on the new instance (scaling, rescheduling, or the source draining other instances); placement constraints may prevent it. + - id: ecs_instance_role_passable + description: iam:PassRole must cover an ECS container-instance role (one with ecs:RegisterContainerInstance + permissions, trusting ec2.amazonaws.com). + - id: tasks_scheduled_on_instance + description: Tasks must be placed on the new instance (scaling, rescheduling, or the source draining other + instances); placement constraints may prevent it. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict iam:PassRole on ECS instance roles; use Fargate or placement constraints for privileged tasks. references: [] - notes: "The PassRole Resource is a same-account ECS container-instance role, not the target task role. The role's trust and ecs:RegisterContainerInstance permission, and actual task placement, remain conditions because the catalog has no intermediate ECS instance-role-to-task-role binding." + notes: "The PassRole Resource is a same-account ECS container-instance role, not the target task role. The role's trust + and ecs:RegisterContainerInstance permission, and actual task placement, remain conditions because the catalog has no + intermediate ECS instance-role-to-task-role binding." - id: aws-ec2-passrole-addroletoinstanceprofile provider: aws service: ec2 title: Add a role to an instance profile used by an instance the source controls - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#iampassrole-iamaddroletoinstanceprofile + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#iampassrole-iamaddroletoinstanceprofile source_revision: 171e422299 - summary: The source can obtain the privileges of passable roles trusting ec2.amazonaws.com by placing them into an instance profile of an instance it already controls. + summary: The source can obtain the privileges of passable roles trusting ec2.amazonaws.com by placing them into an + instance profile of an instance it already controls. requires: all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: iam:AddRoleToInstanceProfile - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: iam:AddRoleToInstanceProfile + resource: "*" target: kind: aws_role selector: @@ -88,68 +100,35 @@ scope: same_account aggregate_as: "Roles trusting ec2.amazonaws.com in {account}" conditions: - - id: controls_ec2_instance - description: The source must already control an EC2 instance whose profile it can change. - - id: profile_has_role - description: An instance profile holds one role; replacing it needs iam:RemoveRoleFromInstanceProfile, otherwise an empty/new profile (iam:CreateInstanceProfile) plus ec2:AssociateIamInstanceProfile is needed. + - id: controls_ec2_instance + description: The source must already control an EC2 instance whose profile it can change. + - id: profile_has_role + description: An instance profile holds one role; replacing it needs iam:RemoveRoleFromInstanceProfile, otherwise an + empty/new profile (iam:CreateInstanceProfile) plus ec2:AssociateIamInstanceProfile is needed. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict iam:AddRoleToInstanceProfile and iam:PassRole on EC2 roles. references: - - https://docs.aws.amazon.com/IAM/latest/APIReference/API_AddRoleToInstanceProfile.html - notes: "" - -- 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}" - 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. - 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/IAM/latest/APIReference/API_AddRoleToInstanceProfile.html notes: "" - 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: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2requestspotinstances-iampassrole source_revision: 171e422299 - summary: The source can obtain the privileges of passable roles trusting ec2.amazonaws.com with an instance profile by requesting a Spot Instance it controls. + summary: The source can obtain the privileges of passable roles trusting ec2.amazonaws.com with an instance profile by + requesting a Spot Instance it controls. requires: all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: ec2:RequestSpotInstances - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: ec2:RequestSpotInstances + resource: "*" target: kind: aws_role selector: @@ -159,18 +138,22 @@ scope: same_account aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" 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. + - 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 + - scp_or_boundary_deny confidence: derived 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. + - 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 @@ -178,15 +161,16 @@ 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. + 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:StopInstances - resource: "{target.attached_resource_arn}" - - action: ec2:StartInstances - resource: "{target.attached_resource_arn}" + - action: ec2:ModifyInstanceAttribute + resource: "{target.attached_resource_arn}" + - action: ec2:StopInstances + resource: "{target.attached_resource_arn}" + - action: ec2:StartInstances + resource: "{target.attached_resource_arn}" target: kind: aws_role selector: @@ -195,28 +179,32 @@ scope: same_account aggregate_as: "Instance roles of instances covered by ec2:ModifyInstanceAttribute in {account}" conditions: - - id: userdata_execution - description: Default cloud-init runs user-data scripts only on first boot; execution on restart requires a multipart/cloud-config that runs on every boot (still attacker-controllable through the user data itself). Instance-store-backed instances cannot be stopped. + - id: userdata_execution + description: Default cloud-init runs user-data scripts only on first boot; execution on restart requires a + multipart/cloud-config that runs on every boot (still attacker-controllable through the user data itself). + Instance-store-backed instances cannot be stopped. blockers: - - scp_or_boundary_deny + - 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 + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/user-data.html notes: The security-group replacement variant of ModifyInstanceAttribute is a network change only and 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: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2createlaunchtemplateversion-ec2createlaunchtemplate-ec2modifylaunchtemplate source_revision: 171e422299 - summary: The source can obtain the privileges of EC2 instance-profile roles launched by an Auto Scaling group that uses a $Latest/$Default launch-template version the source can replace. + summary: The source can obtain the privileges of EC2 instance-profile roles launched by an Auto Scaling group that + uses a $Latest/$Default launch-template version the source can replace. requires: all_of: - - action: ec2:CreateLaunchTemplateVersion - resource: "{target.consumer_input_arn}" + - action: ec2:CreateLaunchTemplateVersion + resource: "{target.consumer_input_arn}" target: kind: aws_role selector: @@ -225,53 +213,59 @@ scope: same_account aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" conditions: - - id: asg_uses_unpinned_version - description: An Auto Scaling group (or EC2 Fleet) must reference the template with $Latest (CreateLaunchTemplateVersion is enough) or $Default (ModifyLaunchTemplate also needed). - - id: delayed_launch - description: A new instance must launch (scale-out, replacement, instance refresh); the source may not control timing. - - id: slr_passrole - description: Launches are performed by the Auto Scaling service-linked role, which can pass any EC2 role, so no iam:PassRole is checked on the source for later launches. + - id: asg_uses_unpinned_version + description: An Auto Scaling group (or EC2 Fleet) must reference the template with $Latest + (CreateLaunchTemplateVersion is enough) or $Default (ModifyLaunchTemplate also needed). + - id: delayed_launch + description: A new instance must launch (scale-out, replacement, instance refresh); the source may not control + timing. + - id: slr_passrole + description: Launches are performed by the Auto Scaling service-linked role, which can pass any EC2 role, so no + iam:PassRole is checked on the source for later launches. blockers: - - scp_or_boundary_deny + - 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/autoscaling/ec2/userguide/ec2-auto-scaling-launch-template-permissions.html - notes: "{target.consumer_input_arn} is the launch template ARN. ec2:ModifyLaunchTemplate on the same template is additionally required only when the group uses $Default (see condition asg_uses_unpinned_version)." + - https://docs.aws.amazon.com/autoscaling/ec2/userguide/ec2-auto-scaling-launch-template-permissions.html + notes: "{target.consumer_input_arn} is the launch template ARN. ec2:ModifyLaunchTemplate on the same template is additionally + required only when the group uses $Default (see condition asg_uses_unpinned_version)." - 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: + 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 obtain the privileges of passable roles trusting ec2.amazonaws.com with an instance profile by having Auto Scaling launch instances from a configuration it controls. + summary: The source can obtain the privileges of passable roles trusting ec2.amazonaws.com with an instance profile by + having Auto Scaling launch instances from a configuration it controls. requires: all_of: - - action: iam:PassRole - resource: "{target.arn}" + - 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: "*" + - - 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: @@ -280,28 +274,33 @@ scope: same_account aggregate_as: "Roles trusting ec2.amazonaws.com with an instance profile in {account}" conditions: - - id: launch_configurations_deprecated - description: New accounts cannot create launch configurations (deprecated since 2023-2024); the launch-template groups apply there. + - 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 + - scp_or_boundary_deny confidence: derived severity: critical - mitigation: Restrict iam:PassRole on EC2 roles; Auto Scaling validates the caller's ec2:RunInstances and iam:PassRole for launch templates. + 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. + - 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: + 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. + 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}" + - action: ec2-instance-connect:SendSSHPublicKey + resource: "{target.attached_resource_arn}" target: kind: aws_role selector: @@ -310,21 +309,23 @@ scope: same_account aggregate_as: "Instance roles of instances covered by ec2-instance-connect:SendSSHPublicKey in {account}" preconditions: - - ec2_instance_running + - ec2_instance_running 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. + - 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 + - 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. + 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 + - https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-instance-connect-methods.html notes: "" - id: aws-ec2-createreplacerootvolumetask-existing-role @@ -333,11 +334,12 @@ title: Replace the root volume of an existing role-bearing EC2 instance source: src/pentesting-cloud/aws-security/aws-persistence/aws-ec2-replace-root-volume-persistence/README.md#ec2 source_revision: 6fb9ac51fd - summary: The source can run code under the instance-profile role of an existing EC2 instance by replacing its root volume with an attacker-controlled image. + summary: The source can run code under the instance-profile role of an existing EC2 instance by replacing its root + volume with an attacker-controlled image. requires: all_of: - - action: ec2:CreateReplaceRootVolumeTask - resource: "{target.resource_arn}" + - action: ec2:CreateReplaceRootVolumeTask + resource: "{target.resource_arn}" target: kind: aws_role selector: @@ -348,18 +350,22 @@ aggregate_as: Instance-profile roles on replaceable EC2 instances in {account} outcome: workload_execution conditions: - - id: compatible_root_image - description: The target must be a running EBS-backed instance and the source must control a compatible AMI or eligible root-volume snapshot. - - id: boot_execution - description: The replacement reboots the instance, and the planted code must run after boot to use the instance profile. + - id: compatible_root_image + description: The target must be a running EBS-backed instance and the source must control a compatible AMI or + eligible root-volume snapshot. + - id: boot_execution + description: The replacement reboots the instance, and the planted code must run after boot to use the instance + profile. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: critical - mitigation: Restrict ec2:CreateReplaceRootVolumeTask on instances with privileged profiles and monitor root-volume replacement tasks. + mitigation: Restrict ec2:CreateReplaceRootVolumeTask on instances with privileged profiles and monitor root-volume + replacement tasks. references: - - https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateReplaceRootVolumeTask.html - notes: The replacement retains the existing instance profile. An AMI or eligible snapshot must be available to the source; copied snapshots are not eligible. + - https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateReplaceRootVolumeTask.html + notes: The replacement retains the existing instance profile. An AMI or eligible snapshot must be available to the + source; copied snapshots are not eligible. - id: aws-ec2-passrole-requestspotfleet provider: aws @@ -370,12 +376,12 @@ 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:aws:ec2:*:{source.account}:spot-fleet-request/*" - - action: ec2:RunInstances - resource: "arn:aws:ec2:*:{source.account}:instance/*" + - action: iam:PassRole + resource: "{target.arn}" + - action: ec2:RequestSpotFleet + resource: "arn:aws:ec2:*:{source.account}:spot-fleet-request/*" + - action: ec2:RunInstances + resource: "arn:aws:ec2:*:{source.account}:instance/*" target: kind: aws_role selector: @@ -386,17 +392,90 @@ aggregate_as: EC2 instance-profile roles passable to Spot Fleet in {account} outcome: workload_execution conditions: - - id: fleet_role - description: The Spot Fleet role must exist and the source must also be allowed to pass it; a new service-linked role may need iam:CreateServiceLinkedRole. - - id: launch_capacity - description: The requested fleet must obtain compatible instance capacity and use controlled user data or an image that runs source code. - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict use of the instance-profile role. + - id: fleet_role + description: The Spot Fleet role must exist and the source must also be allowed to pass it; a new service-linked + role may need iam:CreateServiceLinkedRole. + - id: launch_capacity + description: The requested fleet must obtain compatible instance capacity and use controlled user data or an image + that runs source code. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict use of the instance-profile role. blockers: - - scp_or_boundary_deny + - 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. + - 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. +- 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: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} + conditions: + - id: controls_ec2_instance + description: The source controls an EC2 instance. AssociateIamInstanceProfile alone suffices for a profile-less + instance; replacing an existing profile uses ReplaceIamInstanceProfileAssociation. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict instance-profile association actions and iam:PassRole on EC2 roles. + references: [] + notes: '' +- id: aws-ec2-launchtemplate-embedded-iam-key + provider: aws + service: ec2 + title: Read IAM access keys embedded in EC2 launch-template user data + summary: Credentials of the IAM user whose live keys are embedded in UserData. + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ec2-privesc/README.md#ec2describelaunchtemplateversions-ec2describelaunchtemplates-optional + source_revision: 0b36331 + requires: + all_of: + - action: ec2:DescribeLaunchTemplateVersions + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-ec2-launchtemplate-embedded-iam-key + scope: same_account + conditions: + - id: condition_1 + description: A template version the caller can read contains a still-valid access-key ID and secret for a more + privileged IAM user; DescribeLaunchTemplates is discovery only. + - id: condition_2 + description: The target user must be mapped from the key ID and its effective permissions verified; many versions + contain no credentials. + - 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 access to sensitive resources and remove secrets from the artifact. + references: [] + notes: Required collector evidence is absent from current snapshots; missing evidence remains UNKNOWN/unresolved. diff --git a/src/privilege-escalation-paths/aws/ecr.yaml b/src/privilege-escalation-paths/aws/ecr.yaml index d2dc910d8e..f6068c8037 100644 --- a/src/privilege-escalation-paths/aws/ecr.yaml +++ b/src/privilege-escalation-paths/aws/ecr.yaml @@ -5,26 +5,28 @@ provider: aws service: ecr title: Push an image over a mutable tag consumed by a workload with a role - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrgetauthorizationtoken-ecrbatchchecklayeravailability-ecrbatchgetimage-ecrcompletelayerupload-ecrinitiatelayerupload-ecrputimage-ecruploadlayerpart + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrgetauthorizationtoken-ecrbatchchecklayeravailability-ecrbatchgetimage-ecrcompletelayerupload-ecrinitiatelayerupload-ecrputimage-ecruploadlayerpart source_revision: 171e422299 - summary: The source can obtain (on the next pull) the privileges of the roles of workloads (ECS tasks, Batch jobs, App Runner services, Lambda on redeploy, SageMaker, EKS pods) that run an image tag it can overwrite. + summary: The source can obtain (on the next pull) the privileges of the roles of workloads (ECS tasks, Batch jobs, App + Runner services, Lambda on redeploy, SageMaker, EKS pods) that run an image tag it can overwrite. requires: all_of: - - action: ecr:PutImage - resource: "{target.consumer_input_arn}" + - action: ecr:PutImage + resource: "{target.consumer_input_arn}" any_of: - - - action: ecr:GetAuthorizationToken - resource: "*" - - action: ecr:InitiateLayerUpload - resource: "{target.consumer_input_arn}" - - action: ecr:UploadLayerPart - resource: "{target.consumer_input_arn}" - - action: ecr:CompleteLayerUpload - resource: "{target.consumer_input_arn}" - - action: ecr:BatchCheckLayerAvailability - resource: "{target.consumer_input_arn}" - - - action: ecr:BatchGetImage - resource: "{target.consumer_input_arn}" + - - action: ecr:GetAuthorizationToken + resource: "*" + - action: ecr:InitiateLayerUpload + resource: "{target.consumer_input_arn}" + - action: ecr:UploadLayerPart + resource: "{target.consumer_input_arn}" + - action: ecr:CompleteLayerUpload + resource: "{target.consumer_input_arn}" + - action: ecr:BatchCheckLayerAvailability + resource: "{target.consumer_input_arn}" + - - action: ecr:BatchGetImage + resource: "{target.consumer_input_arn}" target: kind: aws_role selector: @@ -32,45 +34,55 @@ scope: same_account aggregate_as: "Roles of workloads running images from repositories covered by ecr:PutImage in {account}" conditions: - - id: tag_mutable - description: The repository must have mutable tags (immutable repositories need PutImageTagMutability, separate entry) and consumers must reference a tag, not a digest. - - id: refresh_boundary - description: ECS pins the digest per deployment (new deployment/scale re-resolves); Lambda pins at deployment, so the image runs only after a later CreateFunction/UpdateFunctionCode with the tag; App Runner re-pulls only with automatic deployments; Batch resolves at each job run; SageMaker Processing and Training resolve when a later job starts. - - id: retag_needs_attacker_image - description: The BatchGetImage-only group just retags a manifest already in the repository; it yields code execution only if an attacker-controlled image already exists there (otherwise layer-upload permissions are needed). + - id: tag_mutable + description: The repository must have mutable tags (immutable repositories need PutImageTagMutability, separate + entry) and consumers must reference a tag, not a digest. + - id: refresh_boundary + description: ECS pins the digest per deployment (new deployment/scale re-resolves); Lambda pins at deployment, so + the image runs only after a later CreateFunction/UpdateFunctionCode with the tag; App Runner re-pulls only with + automatic deployments; Batch resolves at each job run; SageMaker Processing and Training resolve when a later job + starts. + - id: retag_needs_attacker_image + description: The BatchGetImage-only group just retags a manifest already in the repository; it yields code execution + only if an attacker-controlled image already exists there (otherwise layer-upload permissions are needed). blockers: - - scp_or_boundary_deny - - ecr_tag_immutability + - scp_or_boundary_deny + - ecr_tag_immutability confidence: conditional severity: high mitigation: Use immutable tags or digest references, enable image signing verification and restrict push permissions. references: - - https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-push-iam.html - notes: "{target.consumer_input_arn} is the repository ARN the workload's image comes from. Cross-account consumers can be reached if they pull from this registry. The service-specific ECR-tag sections of the App Runner, Batch, ECS, Lambda (ecrputimage-on-a-mutable-lambda-image-tag-later-code-deployment-required) and SageMaker (ecrputimage-on-a-mutable-processing-image-later-job-required) pages are folded into this entry, which replaces the former aws-lambda-ecr-putimage-mutable-tag and aws-sagemaker-ecr-putimage-processing-image entries." + - https://docs.aws.amazon.com/AmazonECR/latest/userguide/image-push-iam.html + notes: "{target.consumer_input_arn} is the repository ARN the workload's image comes from. Cross-account consumers can be + reached if they pull from this registry. The service-specific ECR-tag sections of the App Runner, Batch, ECS, Lambda (ecrputimage-on-a-mutable-lambda-image-tag-later-code-deployment-required) + and SageMaker (ecrputimage-on-a-mutable-processing-image-later-job-required) pages are folded into this entry, which replaces + the former aws-lambda-ecr-putimage-mutable-tag and aws-sagemaker-ecr-putimage-processing-image entries." - id: aws-ecr-public-push-consumed-image provider: aws service: ecr title: Push to an ECR Public repository consumed by workloads with roles - 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: + 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 - summary: The source can obtain the privileges of roles of workloads (in any account) that run an image tag from an ECR Public repository it can push to. + summary: The source can obtain the privileges of roles of workloads (in any account) that run an image tag from an ECR + Public repository it can push to. requires: all_of: - - action: ecr-public:GetAuthorizationToken - resource: "*" - - action: sts:GetServiceBearerToken - resource: "*" - - action: ecr-public:InitiateLayerUpload - resource: "{target.consumer_input_arn}" - - action: ecr-public:UploadLayerPart - resource: "{target.consumer_input_arn}" - - action: ecr-public:CompleteLayerUpload - resource: "{target.consumer_input_arn}" - - action: ecr-public:BatchCheckLayerAvailability - resource: "{target.consumer_input_arn}" - - action: ecr-public:PutImage - resource: "{target.consumer_input_arn}" + - action: ecr-public:GetAuthorizationToken + resource: "*" + - action: sts:GetServiceBearerToken + resource: "*" + - action: ecr-public:InitiateLayerUpload + resource: "{target.consumer_input_arn}" + - action: ecr-public:UploadLayerPart + resource: "{target.consumer_input_arn}" + - action: ecr-public:CompleteLayerUpload + resource: "{target.consumer_input_arn}" + - action: ecr-public:BatchCheckLayerAvailability + resource: "{target.consumer_input_arn}" + - action: ecr-public:PutImage + resource: "{target.consumer_input_arn}" target: kind: aws_role selector: @@ -78,64 +90,33 @@ scope: any aggregate_as: "Roles of workloads running images from ECR Public repositories covered by ecr-public:PutImage" conditions: - - id: refresh_boundary - description: Same digest/refresh semantics as private ECR consumers. + - id: refresh_boundary + description: Same digest/refresh semantics as private ECR consumers. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high mitigation: Pin public images by digest or mirror them to private repositories with immutable tags. references: [] notes: Only consumers visible in collected snapshots can be evaluated. -- id: aws-ecr-setrepositorypolicy - provider: aws - service: ecr - title: Rewrite a private repository policy to grant the source push access - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrsetrepositorypolicy--self-grant-private-image-access - source_revision: 171e422299 - summary: The source can obtain the privileges of roles of workloads running images from a repository whose policy it can rewrite to grant itself push access. - requires: - all_of: - - action: ecr:SetRepositoryPolicy - resource: "{target.consumer_input_arn}" - - action: ecr:GetAuthorizationToken - resource: "*" - target: - kind: aws_role - selector: - consumer_input_writable_via: ecr:SetRepositoryPolicy - scope: same_account - aggregate_as: "Roles of workloads running images from repositories covered by ecr:SetRepositoryPolicy in {account}" - conditions: - - id: tag_mutable - description: Tags must be mutable and consumed by tag. - - id: refresh_boundary - description: Same consumer refresh semantics as aws-ecr-push-consumed-tag. - blockers: - - scp_or_boundary_deny - - ecr_tag_immutability - confidence: conditional - severity: high - mitigation: Restrict ecr:SetRepositoryPolicy to administrators. - references: [] - notes: Same-account principals named in a repository policy get access without an identity-policy grant, except ecr:GetAuthorizationToken which is registry-level. - - id: aws-ecr-public-setrepositorypolicy provider: aws service: ecr title: Rewrite an ECR Public repository policy to grant the source push access - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecr-publicsetrepositorypolicy + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecr-publicsetrepositorypolicy source_revision: 171e422299 - summary: The source can obtain the privileges of roles of workloads running images from an ECR Public repository whose policy it can rewrite to grant itself push access. + summary: The source can obtain the privileges of roles of workloads running images from an ECR Public repository whose + policy it can rewrite to grant itself push access. requires: all_of: - - action: ecr-public:SetRepositoryPolicy - resource: "{target.consumer_input_arn}" - - action: ecr-public:GetAuthorizationToken - resource: "*" - - action: sts:GetServiceBearerToken - resource: "*" + - action: ecr-public:SetRepositoryPolicy + resource: "{target.consumer_input_arn}" + - action: ecr-public:GetAuthorizationToken + resource: "*" + - action: sts:GetServiceBearerToken + resource: "*" target: kind: aws_role selector: @@ -143,10 +124,10 @@ scope: any aggregate_as: "Roles of workloads running images from ECR Public repositories covered by ecr-public:SetRepositoryPolicy" conditions: - - id: refresh_boundary - description: Same consumer refresh semantics as private ECR. + - id: refresh_boundary + description: Same consumer refresh semantics as private ECR. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict ecr-public:SetRepositoryPolicy to administrators. @@ -159,13 +140,14 @@ title: Rewrite the registry policy to grant the source push access to all repositories source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrputregistrypolicy source_revision: 171e422299 - summary: The source can obtain the privileges of roles of workloads running images from any repository of the registry by granting itself push access through the V2 registry policy. + summary: The source can obtain the privileges of roles of workloads running images from any repository of the registry + by granting itself push access through the V2 registry policy. requires: all_of: - - action: ecr:PutRegistryPolicy - resource: "*" - - action: ecr:GetAuthorizationToken - resource: "*" + - action: ecr:PutRegistryPolicy + resource: "*" + - action: ecr:GetAuthorizationToken + resource: "*" target: kind: aws_role selector: @@ -173,13 +155,13 @@ scope: same_account aggregate_as: "Roles of workloads running images from the ECR registry of {account}" conditions: - - id: tag_mutable - description: Tags must be mutable and consumed by tag. - - id: registry_policy_v2 - description: Registry policy scope V2 (the only currently valid scope) is required for push actions. + - id: tag_mutable + description: Tags must be mutable and consumed by tag. + - id: registry_policy_v2 + description: Registry policy scope V2 (the only currently valid scope) is required for push actions. blockers: - - scp_or_boundary_deny - - ecr_tag_immutability + - scp_or_boundary_deny + - ecr_tag_immutability confidence: conditional severity: high mitigation: Restrict ecr:PutRegistryPolicy to administrators. @@ -190,13 +172,15 @@ provider: aws service: ecr title: Map a trusted private repository prefix (or ROOT) to an upstream the source controls - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrcreatepullthroughcacherule + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrcreatepullthroughcacherule source_revision: 171e422299 - summary: The source can obtain the privileges of roles of workloads that pull not-yet-existing repositories under a prefix it can map to an upstream registry namespace it controls. + summary: The source can obtain the privileges of roles of workloads that pull not-yet-existing repositories under a + prefix it can map to an upstream registry namespace it controls. requires: all_of: - - action: ecr:CreatePullThroughCacheRule - resource: "*" + - action: ecr:CreatePullThroughCacheRule + resource: "*" target: kind: aws_role selector: @@ -204,17 +188,20 @@ scope: same_account aggregate_as: "Roles of workloads pulling cacheable private ECR paths in {account}" conditions: - - id: repository_absent - description: Only paths whose private repository does not yet exist are served from upstream; existing repositories are not overwritten. - - id: consumer_import_permissions - description: The pulling workload (or its image-pull role) must hold ecr:BatchImportUpstreamImage and, when absent, ecr:CreateRepository. - - id: root_prefix - description: A ROOT-prefix rule covers every path of the registry (see the global-registry-hijack section). + - id: repository_absent + description: Only paths whose private repository does not yet exist are served from upstream; existing repositories + are not overwritten. + - id: consumer_import_permissions + description: The pulling workload (or its image-pull role) must hold ecr:BatchImportUpstreamImage and, when absent, + ecr:CreateRepository. + - id: root_prefix + description: A ROOT-prefix rule covers every path of the registry (see the global-registry-hijack section). blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: medium - mitigation: Restrict ecr:CreatePullThroughCacheRule and avoid granting workloads BatchImportUpstreamImage/CreateRepository broadly. + mitigation: Restrict ecr:CreatePullThroughCacheRule and avoid granting workloads + BatchImportUpstreamImage/CreateRepository broadly. references: [] notes: Covers both the prefix and the ROOT ('global registry hijack') sections. @@ -224,36 +211,111 @@ title: Make an immutable repository mutable and overwrite a consumed tag source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrputimagetagmutability source_revision: 171e422299 - summary: The source can obtain the privileges of roles of workloads running a tag from an immutable repository by turning off immutability and pushing over the tag. + summary: The source can obtain the privileges of roles of workloads running a tag from an immutable repository by + turning off immutability and pushing over the tag. requires: all_of: - - action: ecr:PutImageTagMutability - resource: "{target.consumer_input_arn}" - - action: ecr:GetAuthorizationToken - resource: "*" + - action: ecr:PutImageTagMutability + resource: '{target.consumer_input_arn}' + - action: ecr:PutImage + resource: '{target.consumer_input_arn}' + any_of: + - - action: ecr:BatchGetImage + resource: '{target.consumer_input_arn}' + - - action: ecr:GetAuthorizationToken + resource: '*' - action: ecr:InitiateLayerUpload - resource: "{target.consumer_input_arn}" + resource: '{target.consumer_input_arn}' - action: ecr:UploadLayerPart - resource: "{target.consumer_input_arn}" + resource: '{target.consumer_input_arn}' - action: ecr:CompleteLayerUpload - resource: "{target.consumer_input_arn}" + resource: '{target.consumer_input_arn}' - action: ecr:BatchCheckLayerAvailability - resource: "{target.consumer_input_arn}" - - action: ecr:PutImage - resource: "{target.consumer_input_arn}" + resource: '{target.consumer_input_arn}' target: kind: aws_role selector: consumer_input_writable_via: ecr:PutImage scope: same_account - aggregate_as: "Roles of workloads running images from immutable repositories covered by ecr:PutImageTagMutability in {account}" + aggregate_as: Roles of workloads running images from immutable repositories covered by ecr:PutImageTagMutability in + {account} conditions: - - id: refresh_boundary - description: Same consumer refresh semantics as aws-ecr-push-consumed-tag. + - id: refresh_boundary + description: Same consumer refresh semantics as aws-ecr-push-consumed-tag. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict ecr:PutImageTagMutability and reference images by digest. references: [] - notes: Distinct from aws-ecr-push-consumed-tag only for immutable repositories. + notes: Existing image manifests can be retagged with BatchGetImage and PutImage; new-layer upload remains an + alternative. +- id: aws-ecr-setrepositorypolicy + provider: aws + service: ecr + title: Rewrite a private repository policy to grant the source push access + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrsetrepositorypolicy--self-grant-private-image-access + source_revision: 171e422299 + summary: The source can obtain the privileges of roles of workloads running images from a repository whose policy it + can rewrite to grant itself push access. + requires: + all_of: + - action: ecr:SetRepositoryPolicy + resource: '{target.consumer_input_arn}' + target: + kind: aws_role + selector: + consumer_input_writable_via: ecr:SetRepositoryPolicy + scope: same_account + aggregate_as: Roles of workloads running images from repositories covered by ecr:SetRepositoryPolicy in {account} + conditions: + - id: tag_mutable + description: Tags must be mutable and consumed by tag. + - id: refresh_boundary + description: Same consumer refresh semantics as aws-ecr-push-consumed-tag. + blockers: + - scp_or_boundary_deny + - ecr_tag_immutability + confidence: conditional + severity: high + mitigation: Restrict ecr:SetRepositoryPolicy to administrators. + references: [] + notes: Raw SigV4 repository APIs work with resource-policy grants without GetAuthorizationToken; Docker login still + needs it. +- id: aws-ecr-image-embedded-credential + provider: aws + service: ecr + title: ECR image-layer embedded credential theft + summary: The identity represented by a live credential recovered from an ECR image. + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ecr-privesc/README.md#ecrgetauthorizationtoken-ecrbatchgetimage-ecrgetdownloadurlforlayer + source_revision: 0b36331 + requires: + all_of: + - action: ecr:BatchGetImage + resource: '*' + - action: ecr:GetDownloadUrlForLayer + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-ecr-image-embedded-credential + scope: same_account + conditions: + - id: condition_1 + description: The readable image layer actually contains a live credential for another cloud principal; + GetAuthorizationToken is needed for Docker registry login but not necessarily for direct signed API calls. + - id: condition_2 + description: A known repository and image tag/digest are needed; no IAM identity can be inferred from image-read + permission alone. + - 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 access to sensitive resources and remove secrets from the artifact. + references: [] + notes: Required collector evidence is absent from current snapshots; missing evidence remains UNKNOWN/unresolved. diff --git a/src/privilege-escalation-paths/aws/eks.yaml b/src/privilege-escalation-paths/aws/eks.yaml index 820ac32b3e..689f51dcac 100644 --- a/src/privilege-escalation-paths/aws/eks.yaml +++ b/src/privilege-escalation-paths/aws/eks.yaml @@ -10,10 +10,11 @@ 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: + 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. + 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 @@ -32,8 +33,8 @@ 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). + 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 @@ -47,16 +48,17 @@ 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. + 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 + 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. @@ -64,13 +66,15 @@ provider: aws service: eks title: Create an EKS access entry that places the source in an existing privileged Kubernetes group - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#ekscreateaccessentry-alone--join-an-existing-privileged-kubernetes-group + 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 - summary: The source can obtain the in-cluster permissions bound to an existing custom Kubernetes group by creating a STANDARD access entry for itself that lists that group in kubernetesGroups. + summary: The source can obtain the in-cluster permissions bound to an existing custom Kubernetes group by creating a + STANDARD access entry for itself that lists that group in kubernetesGroups. requires: all_of: - - action: eks:CreateAccessEntry - resource: "{target.scope}" + - action: eks:CreateAccessEntry + resource: "{target.scope}" target: kind: k8s_cluster_admin selector: @@ -79,35 +83,40 @@ scope: cluster aggregate_as: "EKS clusters where the source can map itself into privileged Kubernetes groups" conditions: - - id: authentication_mode_api - description: The cluster authenticationMode must be API or API_AND_CONFIG_MAP (checked by eks_authentication_mode). - - id: privileged_custom_group_bound - description: Only escalates when a ClusterRoleBinding/RoleBinding grants an admin-equivalent role to a custom group name; EKS rejects group names starting with system:, so system:masters cannot be requested. - - id: kubernetes_groups_condition_key - description: The eks:kubernetesGroups condition key on the grant can restrict which groups may be requested. - - id: api_endpoint_reachable - description: The source must reach the Kubernetes API endpoint. + - id: authentication_mode_api + description: The cluster authenticationMode must be API or API_AND_CONFIG_MAP (checked by eks_authentication_mode). + - id: privileged_custom_group_bound + description: Only escalates when a ClusterRoleBinding/RoleBinding grants an admin-equivalent role to a custom group + name; EKS rejects group names starting with system:, so system:masters cannot be requested. + - id: kubernetes_groups_condition_key + description: The eks:kubernetesGroups condition key on the grant can restrict which groups may be requested. + - id: api_endpoint_reachable + description: The source must reach the Kubernetes API endpoint. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Constrain eks:CreateAccessEntry with eks:kubernetesGroups and avoid binding cluster-admin to custom groups that access entries can request. + mitigation: Constrain eks:CreateAccessEntry with eks:kubernetesGroups and avoid binding cluster-admin to custom groups + that access entries can request. references: - - https://docs.aws.amazon.com/eks/latest/userguide/creating-access-entries.html - - https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateAccessEntry.html - notes: Severity is critical only when the bound group is admin-equivalent; the real target is the RBAC of that group, which the Kubernetes snapshot of the cluster exposes. + - https://docs.aws.amazon.com/eks/latest/userguide/creating-access-entries.html + - https://docs.aws.amazon.com/eks/latest/APIReference/API_CreateAccessEntry.html + notes: Severity is critical only when the bound group is admin-equivalent; the real target is the RBAC of that group, + which the Kubernetes snapshot of the cluster exposes. - id: aws-eks-updateaccessentry-kubernetes-groups provider: aws service: eks title: Rewrite the Kubernetes groups of an existing EKS access entry - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#eksupdateaccessentry--escalate-an-access-entry-that-already-exists + 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 - summary: The source can escalate an existing STANDARD access entry of a principal it controls by replacing its kubernetesGroups with a privileged custom group. + summary: The source can escalate an existing STANDARD access entry of a principal it controls by replacing its + kubernetesGroups with a privileged custom group. requires: all_of: - - action: eks:UpdateAccessEntry - resource: "arn:aws:eks:*:{target.account}:access-entry/{target.name}/*" + - action: eks:UpdateAccessEntry + resource: "arn:aws:eks:*:{target.account}:access-entry/{target.name}/*" target: kind: k8s_cluster_admin selector: @@ -116,36 +125,40 @@ scope: cluster aggregate_as: "EKS clusters where the source can rewrite access-entry groups" conditions: - - id: source_controls_entry_principal - description: The edited access entry must belong to a principal the source can authenticate as (itself or a role it can assume). - - id: standard_entry_type - description: Only STANDARD entries carry custom kubernetesGroups; EC2_LINUX / EC2_WINDOWS / FARGATE_LINUX node entries have fixed groups. - - id: privileged_custom_group_bound - description: A binding must grant an admin-equivalent role to a custom (non system:) group the source can request. + - id: source_controls_entry_principal + description: The edited access entry must belong to a principal the source can authenticate as (itself or a role it + can assume). + - id: standard_entry_type + description: Only STANDARD entries carry custom kubernetesGroups; EC2_LINUX / EC2_WINDOWS / FARGATE_LINUX node + entries have fixed groups. + - id: privileged_custom_group_bound + description: A binding must grant an admin-equivalent role to a custom (non system:) group the source can request. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict eks:UpdateAccessEntry with eks:kubernetesGroups and to administrators only. references: - - https://docs.aws.amazon.com/eks/latest/APIReference/API_UpdateAccessEntry.html + - https://docs.aws.amazon.com/eks/latest/APIReference/API_UpdateAccessEntry.html notes: Complements aws-eks-createaccessentry-privileged-kubernetes-group when the entry already exists. - id: aws-eks-createpodidentityassociation-passrole provider: aws service: eks title: Bind a passable role to a Kubernetes service account through EKS Pod Identity - 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: + 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 - summary: The source can obtain the privileges of any passable role trusting pods.eks.amazonaws.com by associating it with a service account in a namespace where it can run pods. + summary: The source can obtain the privileges of any passable role trusting pods.eks.amazonaws.com by associating it + with a service account in a namespace where it can run pods. requires: all_of: - - action: eks:CreatePodIdentityAssociation - resource: "arn:aws:eks:*:{target.account}:cluster/*" - - action: iam:PassRole - resource: "{target.arn}" - - action: iam:GetRole - resource: "{target.arn}" + - action: eks:CreatePodIdentityAssociation + resource: "arn:aws:eks:*:{target.account}:cluster/*" + - action: iam:PassRole + resource: "{target.arn}" + - action: iam:GetRole + resource: "{target.arn}" target: kind: aws_role selector: @@ -154,78 +167,47 @@ scope: same_account aggregate_as: "Roles trusting pods.eks.amazonaws.com passable to EKS Pod Identity in {account}" preconditions: - - eks_cluster_exists - conditions: - - id: pod_execution_in_namespace - description: The source must be able to run a pod using the associated service account (Kubernetes create pods / workload permissions in that namespace), or control an existing pod using it. - - id: pod_identity_agent_installed - description: The cluster must run the EKS Pod Identity Agent add-on. - - id: trust_actions - description: The role trust must allow both sts:AssumeRole and sts:TagSession for pods.eks.amazonaws.com; aws:SourceArn / aws:SourceAccount or eks-cluster-* session-tag conditions may limit which clusters and namespaces can use it. - - id: passrole_condition_key - description: iam:PassedToService / iam:AssociatedResourceArn conditions may restrict passing the role to EKS. - blockers: - - scp_or_boundary_deny - confidence: conditional - severity: critical - mitigation: Scope iam:PassRole for EKS Pod Identity to specific roles with iam:PassedToService=pods.eks.amazonaws.com, and pin trusted roles to cluster ARNs and namespaces with session-tag conditions. - references: - - https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html - - https://docs.aws.amazon.com/eks/latest/userguide/pod-id-role.html - - https://docs.aws.amazon.com/eks/latest/APIReference/API_CreatePodIdentityAssociation.html - notes: The edge is the AWS half; the Kubernetes half (ability to run a pod with the service account) is evaluated in the cluster's K8s snapshot. - -- id: aws-eks-updatepodidentityassociation-passrole - provider: aws - service: eks - title: Repoint an existing EKS Pod Identity association to another passable role - 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 - summary: The source can obtain the privileges of any passable role trusting pods.eks.amazonaws.com by swapping it into an existing Pod Identity association whose pods it can run or control. - requires: - all_of: - - action: eks:UpdatePodIdentityAssociation - resource: "arn:aws:eks:*:{target.account}:podidentityassociation/*" - - 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: "Roles trusting pods.eks.amazonaws.com swappable into Pod Identity associations in {account}" - preconditions: - - eks_cluster_exists + - eks_cluster_exists conditions: - - id: pod_execution_for_association - description: The source must run or control a pod using the association's service account, or the gained role only reaches the existing workload. - - id: target_role_chaining - description: A targetRoleArn on the association makes EKS chain into a role in another account; that role must trust the association role. - - id: session_tag_conditions - description: Disabling session tags on the association can bypass trust conditions that expect eks-cluster-* tags only when those conditions use *IfExists or Null checks. + - id: pod_execution_in_namespace + description: The source must be able to run a pod using the associated service account (Kubernetes create pods / + workload permissions in that namespace), or control an existing pod using it. + - id: pod_identity_agent_installed + description: The cluster must run the EKS Pod Identity Agent add-on. + - id: trust_actions + description: The role trust must allow both sts:AssumeRole and sts:TagSession for pods.eks.amazonaws.com; + aws:SourceArn / aws:SourceAccount or eks-cluster-* session-tag conditions may limit which clusters and namespaces + can use it. + - id: passrole_condition_key + description: iam:PassedToService / iam:AssociatedResourceArn conditions may restrict passing the role to EKS. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: critical - mitigation: Restrict eks:UpdatePodIdentityAssociation as tightly as eks:CreatePodIdentityAssociation and scope iam:PassRole to the intended roles. + mitigation: Scope iam:PassRole for EKS Pod Identity to specific roles with iam:PassedToService=pods.eks.amazonaws.com, + and pin trusted roles to cluster ARNs and namespaces with session-tag conditions. references: - - https://docs.aws.amazon.com/eks/latest/APIReference/API_UpdatePodIdentityAssociation.html - notes: Useful when CreatePodIdentityAssociation is denied but updates are allowed. + - https://docs.aws.amazon.com/eks/latest/userguide/pod-identities.html + - https://docs.aws.amazon.com/eks/latest/userguide/pod-id-role.html + - https://docs.aws.amazon.com/eks/latest/APIReference/API_CreatePodIdentityAssociation.html + notes: The edge is the AWS half; the Kubernetes half (ability to run a pod with the service account) is evaluated in + the cluster's K8s snapshot. - id: aws-eks-passrole-createnodegroup provider: aws service: eks title: Create a managed node group with a passed node role - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-eks-privesc/README.md#iampassrole-ekscreatenodegroup--ekscreatefargateprofile--run-pods-on-capacity-you-control + 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 - summary: The source can obtain the privileges of any passable role trusting ec2.amazonaws.com by launching an EKS managed node group with it and reaching the node. + summary: The source can obtain the privileges of any passable role trusting ec2.amazonaws.com by launching an EKS + managed node group with it and reaching the node. requires: all_of: - - action: eks:CreateNodegroup - resource: "arn:aws:eks:*:{target.account}:cluster/*" - - action: iam:PassRole - resource: "{target.arn}" + - action: eks:CreateNodegroup + resource: "arn:aws:eks:*:{target.account}:cluster/*" + - action: iam:PassRole + resource: "{target.arn}" target: kind: aws_role selector: @@ -234,35 +216,43 @@ scope: same_account aggregate_as: "Roles trusting ec2.amazonaws.com passable as EKS node roles in {account}" preconditions: - - eks_cluster_exists + - eks_cluster_exists conditions: - - id: node_access - description: The source must execute code on the node to read the instance role credentials (remote access key, a launch template it controls, or a pod scheduled onto the node with host access). - - id: subnet_and_launch_template_permissions - description: Using a custom launch template or remote access needs the corresponding EC2 permissions and reachable subnets. - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict passing the role to EKS. + - id: node_access + description: The source must execute code on the node to read the instance role credentials (remote access key, a + launch template it controls, or a pod scheduled onto the node with host access). + - id: subnet_and_launch_template_permissions + description: Using a custom launch template or remote access needs the corresponding EC2 permissions and reachable + subnets. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict passing the role to EKS. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Scope iam:PassRole for node roles to the approved node role and restrict eks:CreateNodegroup to platform administrators. + mitigation: Scope iam:PassRole for node roles to the approved node role and restrict eks:CreateNodegroup to platform + administrators. references: - - https://docs.aws.amazon.com/eks/latest/userguide/create-managed-node-group.html - - https://docs.aws.amazon.com/eks/latest/userguide/create-node-role.html - notes: Pods later scheduled onto the node also expose their service-account tokens and Pod Identity credentials. The Fargate variant is not modelled as an edge because the Fargate pod execution role (trusting eks-fargate-pods.amazonaws.com) is used by the Fargate infrastructure for image pulls and logging and its credentials are not exposed to pods. + - https://docs.aws.amazon.com/eks/latest/userguide/create-managed-node-group.html + - https://docs.aws.amazon.com/eks/latest/userguide/create-node-role.html + notes: Pods later scheduled onto the node also expose their service-account tokens and Pod Identity credentials. The + Fargate variant is not modelled as an edge because the Fargate pod execution role (trusting + eks-fargate-pods.amazonaws.com) is used by the Fargate infrastructure for image pulls and logging and its + credentials are not exposed to pods. - id: aws-eks-associateidentityproviderconfig-privileged-group provider: aws service: eks title: Associate an attacker-controlled OIDC identity provider with an EKS cluster that binds a privileged RBAC group - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation/README.md#eksassociateidentityproviderconfig-with-a-matching-privileged-rbac-group + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation/README.md#eksassociateidentityproviderconfig-with-a-matching-privileged-rbac-group source_revision: 6fb9ac51fd - summary: The source can become Kubernetes cluster-admin of an EKS cluster by making the cluster trust an OIDC issuer it controls and presenting tokens whose group claim matches an existing privileged RBAC binding. + summary: The source can become Kubernetes cluster-admin of an EKS cluster by making the cluster trust an OIDC issuer + it controls and presenting tokens whose group claim matches an existing privileged RBAC binding. requires: all_of: - - action: eks:AssociateIdentityProviderConfig - resource: "{target.scope}" + - action: eks:AssociateIdentityProviderConfig + resource: "{target.scope}" target: kind: k8s_cluster_admin selector: @@ -270,97 +260,206 @@ scope: cluster aggregate_as: "Cluster-admin of EKS clusters whose OIDC identity providers the source can associate" conditions: - - id: privileged_group_binding - description: A pre-existing RoleBinding or ClusterRoleBinding must grant high privileges to a group (or to all authenticated users) that the configured group claim and prefix can produce; EKS rejects system-prefixed username and group prefixes, so system:masters cannot be targeted directly. - - id: issuer_controlled - description: The source must operate an OIDC issuer reachable by EKS and mint tokens whose audience and required claims match the association. - - id: api_endpoint_reachable - description: The source must reach the Kubernetes API endpoint (public endpoint CIDR allowlist or private VPC access). + - id: privileged_group_binding + description: A pre-existing RoleBinding or ClusterRoleBinding must grant high privileges to a group (or to all + authenticated users) that the configured group claim and prefix can produce; EKS rejects system-prefixed username + and group prefixes, so system:masters cannot be targeted directly. + - id: issuer_controlled + description: The source must operate an OIDC issuer reachable by EKS and mint tokens whose audience and required + claims match the association. + - 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 + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Restrict eks:AssociateIdentityProviderConfig to platform administrators, alert on new identity provider associations and avoid RBAC bindings that grant broad privileges to groups an external issuer could assert. + mitigation: Restrict eks:AssociateIdentityProviderConfig to platform administrators, alert on new identity provider + associations and avoid RBAC bindings that grant broad privileges to groups an external issuer could assert. references: - - https://docs.aws.amazon.com/eks/latest/userguide/authenticate-oidc-identity-provider.html - - https://docs.aws.amazon.com/eks/latest/APIReference/API_AssociateIdentityProviderConfig.html - notes: The association creates authentication only; authorization comes from existing RBAC bindings, which are not collected as AWS facts, hence conditional. + - https://docs.aws.amazon.com/eks/latest/userguide/authenticate-oidc-identity-provider.html + - https://docs.aws.amazon.com/eks/latest/APIReference/API_AssociateIdentityProviderConfig.html + notes: The association creates authentication only; authorization comes from existing RBAC bindings, which are not + collected as AWS facts, hence conditional. - id: aws-eks-associateaccesspolicy-existing-entry provider: aws service: eks title: Associate a cluster-admin access policy with an existing EKS access entry the source controls - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation/README.md#abusing-access-entries + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation/README.md#abusing-access-entries source_revision: 6fb9ac51fd - summary: The source can become Kubernetes cluster-admin of an EKS cluster by associating AmazonEKSClusterAdminPolicy with an already existing access entry for a principal it can authenticate as, without creating an entry. + summary: The source can become Kubernetes cluster-admin of an EKS cluster by associating AmazonEKSClusterAdminPolicy + with an already existing access entry for a principal it can authenticate as, without creating an entry. requires: all_of: - - action: eks:AssociateAccessPolicy - resource: "arn:aws:eks:*:{target.account}:access-entry/{target.name}/*" + - action: eks:AssociateAccessPolicy + resource: "arn:aws:eks:*:{target.account}:access-entry/{target.name}/*" target: kind: k8s_cluster_admin selector: any_principal_in_scope: true eks_authentication_mode: - - API - - API_AND_CONFIG_MAP + - API + - API_AND_CONFIG_MAP scope: cluster aggregate_as: "Cluster-admin of EKS clusters whose existing access entries the source can extend" outcome: permission_grant conditions: - - id: existing_entry_for_controlled_principal - description: A STANDARD access entry must already exist for an IAM principal the source can authenticate as (often itself, created by a pipeline or the cluster creator bootstrap entry). - - 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). + - id: existing_entry_for_controlled_principal + description: A STANDARD access entry must already exist for an IAM principal the source can authenticate as (often + itself, created by a pipeline or the cluster creator bootstrap entry). + - 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 + - scp_or_boundary_deny confidence: conditional severity: critical - mitigation: Treat eks:AssociateAccessPolicy as a cluster-admin grant even without eks:CreateAccessEntry and use the eks:policyArn / eks:accessScope condition keys to forbid AmazonEKSClusterAdminPolicy. + mitigation: Treat eks:AssociateAccessPolicy as a cluster-admin grant even without eks:CreateAccessEntry and use the + eks:policyArn / eks:accessScope condition keys to forbid AmazonEKSClusterAdminPolicy. references: - - https://docs.aws.amazon.com/eks/latest/APIReference/API_AssociateAccessPolicy.html - - https://docs.aws.amazon.com/eks/latest/userguide/access-policies.html - notes: Variant of aws-eks-createaccessentry-associateaccesspolicy without the create step; access entries are not inventoried per principal, so whether a controlled entry exists is a condition. + - https://docs.aws.amazon.com/eks/latest/APIReference/API_AssociateAccessPolicy.html + - https://docs.aws.amazon.com/eks/latest/userguide/access-policies.html + notes: Variant of aws-eks-createaccessentry-associateaccesspolicy without the create step; access entries are not + inventoried per principal, so whether a controlled entry exists is a condition. - 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-post-exploitation/aws-eks-post-exploitation/README.md#abusing-access-entries + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation/README.md#abusing-access-entries source_revision: 6fb9ac51fd - 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. + 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}" - - action: eks:CreateAccessEntry - resource: "{target.scope}" - - action: eks:AssociateAccessPolicy - resource: "arn:aws:eks:*:{target.account}:access-entry/{target.name}/*" + - action: eks:UpdateClusterConfig + resource: "{target.scope}" + - action: eks:CreateAccessEntry + resource: "{target.scope}" + - action: eks:AssociateAccessPolicy + resource: "arn:aws:eks:*:{target.account}:access-entry/{target.name}/*" target: kind: k8s_cluster_admin selector: any_principal_in_scope: true eks_authentication_mode: - - CONFIG_MAP + - CONFIG_MAP scope: cluster aggregate_as: "Cluster-admin of CONFIG_MAP EKS clusters whose authentication mode the source can change" outcome: permission_grant conditions: - - 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). + - 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-updatepodidentityassociation-passrole + provider: aws + service: eks + title: Repoint an existing EKS Pod Identity association to another passable role + 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 + summary: The source can obtain the privileges of any passable role trusting pods.eks.amazonaws.com by swapping it into + an existing Pod Identity association whose pods it can run or control. + requires: + all_of: + - action: eks:UpdatePodIdentityAssociation + resource: arn:aws:eks:*:{target.account}:podidentityassociation/* + - action: iam:PassRole + resource: '{target.arn}' + - action: iam:GetRole + 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: Roles trusting pods.eks.amazonaws.com swappable into Pod Identity associations in {account} + preconditions: + - eks_cluster_exists + conditions: + - id: pod_execution_for_association + description: The source must run or control a pod using the association's service account, or the gained role only + reaches the existing workload. + - id: target_role_chaining + description: A targetRoleArn on the association makes EKS chain into a role in another account; that role must trust + the association role. + - id: session_tag_conditions + description: Disabling session tags on the association can bypass trust conditions that expect eks-cluster-* tags + only when those conditions use *IfExists or Null checks. + - id: cross_account_chain + description: A cross-account targetRoleArn requires the actual association roleArn to allow sts:AssumeRole and the + target role to trust that role; do not infer this from PassRole alone. blockers: - - scp_or_boundary_deny + - 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. + mitigation: Restrict eks:UpdatePodIdentityAssociation as tightly as eks:CreatePodIdentityAssociation and scope + iam:PassRole to the intended roles. 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. + - https://docs.aws.amazon.com/eks/latest/APIReference/API_UpdatePodIdentityAssociation.html + notes: Useful when CreatePodIdentityAssociation is denied but updates are allowed. +- id: aws-eks-updatepodidentityassociation-targetrole + provider: aws + service: eks + title: Repoint EKS Pod Identity targetRoleArn to a cross-account role + summary: Credentials of a target role in another account reached through the Pod Identity intermediate role. + 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: 0b36331 + requires: + all_of: + - action: eks:UpdatePodIdentityAssociation + resource: '*' + - action: iam:PassRole + resource: '*' + - action: iam:GetRole + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-eks-updatepodidentityassociation-targetrole + scope: any + conditions: + - id: condition_1 + description: An existing association supplies or is updated to an intermediate role that trusts + pods.eks.amazonaws.com with sts:AssumeRole and sts:TagSession. + - id: condition_2 + description: The intermediate role may sts:AssumeRole into a targetRoleArn in another account and that target trusts + the intermediate role; the source controls a pod using the association’s service account. + - id: condition_3 + description: Session-tag conditions must be evaluated as they actually apply; removing tags only bypasses + IfExists/Null-style conditions, not mandatory tag checks. + - 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: Required collector evidence is absent from current snapshots; missing evidence remains UNKNOWN/unresolved. diff --git a/src/privilege-escalation-paths/aws/elasticbeanstalk.yaml b/src/privilege-escalation-paths/aws/elasticbeanstalk.yaml index 355e1ff104..f9b1b305f5 100644 --- a/src/privilege-escalation-paths/aws/elasticbeanstalk.yaml +++ b/src/privilege-escalation-paths/aws/elasticbeanstalk.yaml @@ -8,13 +8,15 @@ provider: aws service: elasticbeanstalk title: Inject runtime-influencing environment properties into an existing environment - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkupdateenvironment + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkupdateenvironment source_revision: 171e422299 - summary: The source can obtain the privileges of the EC2 instance-profile role of existing Beanstalk environments it can update. + summary: The source can obtain the privileges of the EC2 instance-profile role of existing Beanstalk environments it + can update. requires: all_of: - - action: elasticbeanstalk:UpdateEnvironment - resource: "{target.resource_arn}" + - action: elasticbeanstalk:UpdateEnvironment + resource: "{target.resource_arn}" target: kind: aws_role selector: @@ -23,32 +25,37 @@ scope: same_account aggregate_as: "Instance-profile roles of updatable Beanstalk environments in {account}" conditions: - - id: runtime_supports_env_injection - description: Code execution via environment properties depends on the platform runtime and, for most runtimes, on attacker-controlled content already readable on the instances. - - id: supporting_permissions - description: Applying the update needs the CloudFormation/Auto Scaling/EC2 permissions Beanstalk uses with the caller's credentials. + - id: runtime_supports_env_injection + description: Code execution via environment properties depends on the platform runtime and, for most runtimes, on + attacker-controlled content already readable on the instances. + - id: supporting_permissions + description: Applying the update needs the CloudFormation/Auto Scaling/EC2 permissions Beanstalk uses with the + caller's credentials. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Restrict elasticbeanstalk:UpdateEnvironment to deployment principals on specific environments and keep instance-profile roles least-privileged. + mitigation: Restrict elasticbeanstalk:UpdateEnvironment to deployment principals on specific environments and keep + instance-profile roles least-privileged. references: - - https://docs.aws.amazon.com/elasticbeanstalk/latest/api/API_UpdateEnvironment.html + - https://docs.aws.amazon.com/elasticbeanstalk/latest/api/API_UpdateEnvironment.html notes: Reach is only the instance profile configured on environments in Resource scope. - id: aws-elasticbeanstalk-rebuildenvironment-s3-code provider: aws service: elasticbeanstalk title: Replace an environment's source bundle in S3 and rebuild it - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkrebuildenvironment-s3-write-permissions--many-others + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkrebuildenvironment-s3-write-permissions--many-others source_revision: 171e422299 - summary: The source can obtain the privileges of the EC2 instance-profile role of an existing environment whose deployed source bundle it can overwrite. + summary: The source can obtain the privileges of the EC2 instance-profile role of an existing environment whose + deployed source bundle it can overwrite. requires: all_of: - - action: elasticbeanstalk:RebuildEnvironment - resource: "{target.resource_arn}" - - action: s3:PutObject - resource: "{target.artifact_arn}" + - action: elasticbeanstalk:RebuildEnvironment + resource: "{target.resource_arn}" + - action: s3:PutObject + resource: "{target.artifact_arn}" target: kind: aws_role selector: @@ -58,26 +65,31 @@ scope: same_account aggregate_as: "Instance-profile roles of rebuildable Beanstalk environments in {account}" conditions: - - id: supporting_permissions - description: RebuildEnvironment needs the CloudFormation, EC2 and Auto Scaling permissions Beanstalk uses with the caller's credentials. - - id: artifact_is_deployed_bundle - description: The overwritten object must be the source bundle of the application version deployed to that environment (typically in elasticbeanstalk--). + - id: supporting_permissions + description: RebuildEnvironment needs the CloudFormation, EC2 and Auto Scaling permissions Beanstalk uses with the + caller's credentials. + - id: artifact_is_deployed_bundle + description: The overwritten object must be the source bundle of the application version deployed to that + environment (typically in elasticbeanstalk--). blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Restrict write access to the elasticbeanstalk-- bucket to the deployment pipeline and restrict RebuildEnvironment. + mitigation: Restrict write access to the elasticbeanstalk-- bucket to the deployment pipeline and + restrict RebuildEnvironment. references: - - https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/environment-management-rebuild.html + - https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/environment-management-rebuild.html notes: Both selectors must refer to the same environment (the artifact is that environment's deployed bundle). - 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: + 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. + 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 @@ -113,62 +125,60 @@ aggregate_as: EC2 instance-profile roles passable in {account} 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. + 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. + 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. + 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: A principal with these supporting permissions (ec2:RunInstances + PassRole) is usually already covered by the + EC2 PassRole edge; this entry records the Beanstalk route. - id: aws-elasticbeanstalk-createapplicationversion-updateenvironment provider: aws service: elasticbeanstalk title: Deploy an attacker-hosted application version to an existing environment - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-elastic-beanstalk-privesc/README.md#elasticbeanstalkcreateapplicationversion-elasticbeanstalkupdateenvironment-cloudformationgettemplate-cloudformationdescribestackresources-cloudformationdescribestackresource-autoscalingdescribeautoscalinggroups-autoscalingsuspendprocesses + 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 - summary: The source can obtain the privileges of the EC2 instance-profile role of existing environments it can deploy a new version to. + summary: The source can obtain the privileges of the EC2 instance-profile role of existing environments it can deploy + a new version to. requires: all_of: - - action: elasticbeanstalk:CreateApplicationVersion - resource: "*" - - action: elasticbeanstalk:UpdateEnvironment - resource: "{target.resource_arn}" - - action: cloudformation:GetTemplate - resource: "*" - - action: cloudformation:DescribeStackResources - resource: "*" - - action: cloudformation:DescribeStackResource - resource: "*" - - action: autoscaling:DescribeAutoScalingGroups - resource: "*" - - action: autoscaling:SuspendProcesses - resource: "*" + - action: elasticbeanstalk:CreateApplicationVersion + resource: '*' + - action: elasticbeanstalk:UpdateEnvironment + resource: '{target.resource_arn}' target: kind: aws_role selector: has_instance_profile: true via_resource_type: elasticbeanstalk_environment scope: same_account - aggregate_as: "Instance-profile roles of updatable Beanstalk environments in {account}" + aggregate_as: Instance-profile roles of updatable Beanstalk environments in {account} conditions: - - id: bundle_readable_by_environment - description: The source bundle must be in a location the deployment can read (e.g. an attacker-owned bucket made readable to the victim account). - - id: deployment_policy_permissions - description: Depending on the environment's deployment policy, additional Auto Scaling/EC2/ELB permissions may be required. + - id: bundle_readable_by_environment + description: The source bundle must be in a location the deployment can read (e.g. an attacker-owned bucket made + readable to the victim account). + - id: deployment_policy_permissions + description: Depending on the environment's deployment policy, additional Auto Scaling/EC2/ELB permissions may be + required. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Restrict elasticbeanstalk:CreateApplicationVersion and UpdateEnvironment to the deployment pipeline on specific applications and environments. + mitigation: Restrict elasticbeanstalk:CreateApplicationVersion and UpdateEnvironment to the deployment pipeline on + specific applications and environments. references: - - https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/applications-versions.html - notes: Reach is the instance profile of the environments covered by UpdateEnvironment. + - https://docs.aws.amazon.com/elasticbeanstalk/latest/dg/applications-versions.html + notes: CloudFormation/Auto Scaling discovery and SuspendProcesses are optional for a known existing environment. diff --git a/src/privilege-escalation-paths/aws/events.yaml b/src/privilege-escalation-paths/aws/events.yaml index 2ff0ad9cac..28738c5143 100644 --- a/src/privilege-escalation-paths/aws/events.yaml +++ b/src/privilege-escalation-paths/aws/events.yaml @@ -1,39 +1,4 @@ # 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: The source can obtain the write privileges of any passable role trusting events.amazonaws.com, exercised through the supported service actions of a universal target. - requires: - all_of: - - action: iam:PassRole - resource: '{target.arn}' - - action: events:CreateSubscriber - resource: '*' - target: - kind: aws_role - selector: - trust_allows_service: events.amazonaws.com - resource_permission_covers_target: iam:PassRole - scope: same_account - aggregate_as: Roles trusting events.amazonaws.com passable in {account} - conditions: - - id: enhanced_bus_and_event - description: An enhanced custom event bus must exist in the source's account and a matching retained or live event must reach the subscriber (events:PutEvents on the bus, or natural traffic). - - 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: events:CreateSubscriber is authorized on both the bus ARN and the subscriber ARN; the "*" requirement matches any CreateSubscriber grant by overlap, so a grant scoped to a different bus can produce - a false positive. A subscriber on a cross-account shared bus runs as a role of the subscriber owner's account. +[] diff --git a/src/privilege-escalation-paths/aws/flink.yaml b/src/privilege-escalation-paths/aws/flink.yaml index 7305a9b8cf..6c32bd2129 100644 --- a/src/privilege-escalation-paths/aws/flink.yaml +++ b/src/privilege-escalation-paths/aws/flink.yaml @@ -7,13 +7,15 @@ provider: aws service: kinesisanalytics title: Repoint the code of an existing Managed Flink application that keeps 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: + 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 obtain the IAM privileges of the execution role of Managed Flink applications it can update, once they start or update. + summary: The source can obtain the IAM privileges of the execution role of Managed Flink applications it can update, + once they start or update. requires: all_of: - - action: kinesisanalytics:UpdateApplication - resource: "{target.resource_arn}" + - action: kinesisanalytics:UpdateApplication + resource: "{target.resource_arn}" target: kind: aws_role selector: @@ -22,34 +24,39 @@ scope: same_account aggregate_as: "Execution roles of Managed Flink applications in {account}" conditions: - - id: code_readable_by_role - description: The execution role must be able to read code the source controls (writable existing key, a covered bucket, a cross-account bucket allowing the role, or an unpinned artifact). - - id: application_restart - description: The code runs when the application next starts or updates; a stopped application needs kinesisanalytics:StartApplication or an operator. + - id: code_readable_by_role + description: The execution role must be able to read code the source controls (writable existing key, a covered + bucket, a cross-account bucket allowing the role, or an unpinned artifact). + - id: application_restart + description: The code runs when the application next starts or updates; a stopped application needs + kinesisanalytics:StartApplication or an operator. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Restrict kinesisanalytics:UpdateApplication to the deployment pipeline, protect code buckets, and keep execution roles least-privileged. + mitigation: Restrict kinesisanalytics:UpdateApplication to the deployment pipeline, protect code buckets, and keep + execution roles least-privileged. references: - - https://docs.aws.amazon.com/managed-flink/latest/apiv2/API_UpdateApplication.html + - https://docs.aws.amazon.com/managed-flink/latest/apiv2/API_UpdateApplication.html notes: No PassRole is needed while the current role is kept; supplying a role update requires iam:PassRole. - 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: + 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 obtain the IAM privileges of any passable role trusting kinesisanalytics.amazonaws.com by running its own application code under it. + summary: The source can obtain the IAM privileges of any passable role trusting kinesisanalytics.amazonaws.com by + running its own application code under it. requires: all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: kinesisanalytics:CreateApplication - resource: "*" - - action: kinesisanalytics:StartApplication - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: kinesisanalytics:CreateApplication + resource: "*" + - action: kinesisanalytics:StartApplication + resource: "*" target: kind: aws_role selector: @@ -58,30 +65,33 @@ scope: same_account aggregate_as: "Roles trusting kinesisanalytics.amazonaws.com passable in {account}" conditions: - - id: code_readable_by_role - description: The passed role must be able to read the application code the source supplies. - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict which roles can be passed. + - id: code_readable_by_role + description: The passed role must be able to read the application code the source supplies. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: derived severity: high - mitigation: Restrict iam:PassRole on Flink roles with iam:PassedToService=kinesisanalytics.amazonaws.com and restrict CreateApplication to the deployment pipeline. + 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 + - 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. - id: aws-flink-studio-presigned-url provider: aws service: kinesisanalytics title: Open a running Managed Flink Studio notebook through a presigned URL - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#studio-presigned-url-to-zeppelin-execution + 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: The source can obtain the IAM privileges of the execution role of running Studio (INTERACTIVE) applications it can mint URLs for. + summary: The source can obtain the IAM privileges of the execution role of running Studio (INTERACTIVE) applications + it can mint URLs for. requires: all_of: - - action: kinesisanalytics:CreateApplicationPresignedUrl - resource: "{target.resource_arn}" + - action: kinesisanalytics:CreateApplicationPresignedUrl + resource: "{target.resource_arn}" target: kind: aws_role selector: @@ -90,13 +100,48 @@ scope: same_account aggregate_as: "Execution roles of Managed Flink Studio applications in {account}" conditions: - - id: running_studio_application - description: The application must be an INTERACTIVE (Studio) application in RUNNING state, or the source must also start it. + - id: running_studio_application + description: The application must be an INTERACTIVE (Studio) application in RUNNING state, or the source must also + start it. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Restrict kinesisanalytics:CreateApplicationPresignedUrl to notebook owners and keep Studio execution roles least-privileged. + mitigation: Restrict kinesisanalytics:CreateApplicationPresignedUrl to notebook owners and keep Studio execution roles + least-privileged. references: - - https://docs.aws.amazon.com/managed-flink/latest/apiv2/API_CreateApplicationPresignedUrl.html - notes: Streaming (non-Studio) applications are also matched by the selector; the condition limits the edge to Studio applications. + - https://docs.aws.amazon.com/managed-flink/latest/apiv2/API_CreateApplicationPresignedUrl.html + notes: Streaming (non-Studio) applications are also matched by the selector; the condition limits the edge to Studio + applications. +- id: aws-s05-28-studio-presigned-url-to-zeppelin-execution + provider: aws + service: managed-flink + title: Studio presigned URL to Zeppelin execution + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-managed-flink-privesc/README.md#studio-presigned-url-to-zeppelin-execution + source_revision: 0b36331 + summary: 'Conditional gain: interactive notebook execution.' + requires: + all_of: + - action: kinesisanalytics:CreateApplicationPresignedUrl + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-28-studio-presigned-url-to-zeppelin-execution + scope: same_account + conditions: + - id: exact_verified_prerequisites + description: Exact application is INTERACTIVE and RUNNING; UI URL reachable. + - 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 listed action to approved principals and exact resources. + references: [] + notes: Draft only. Missing exact evidence remains UNKNOWN; replace placeholder with the typed selector or collector + fact described alongside this draft. Required collector evidence is absent from current snapshots; missing evidence + remains UNKNOWN/unresolved. diff --git a/src/privilege-escalation-paths/aws/gameliftstreams.yaml b/src/privilege-escalation-paths/aws/gameliftstreams.yaml index 7045ed70e9..27c892a4c2 100644 --- a/src/privilege-escalation-paths/aws/gameliftstreams.yaml +++ b/src/privilege-escalation-paths/aws/gameliftstreams.yaml @@ -2,57 +2,24 @@ # 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 an admin shell in a live stream session that has a role - 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 - summary: The source can obtain the privileges of the role of live GameLift Streams sessions in stream groups it can open admin shells in. - requires: - all_of: - - action: gameliftstreams:CreateStreamSessionAdminShell - resource: '*' - target: - kind: aws_role - selector: - trust_allows_service: gameliftstreams.amazonaws.com - name_prefix: GameLiftStreams- - via_resource_type: gameliftstreams_stream_session - scope: same_account - aggregate_as: Roles of live GameLift Streams sessions in {account} - conditions: - - id: live_session_with_role - description: A stream session started with a RoleArn must be live; the role is only exposed for the session lifetime. - - id: stream_group_scope - description: The action authorizes the parent stream-group ARN; the "*" requirement matches any CreateStreamSessionAdminShell grant by overlap, so the specific stream group holding the role-bearing - session must be within the grant. - blockers: - - scp_or_boundary_deny - confidence: conditional - severity: high - mitigation: Restrict gameliftstreams:CreateStreamSessionAdminShell to operators and give session roles only what the application needs. - references: - - https://docs.aws.amazon.com/gameliftstreams/latest/apireference/API_StartStreamSession.html - notes: Stream sessions are not collected; attachment resolves as unknown. No iam:PassRole is needed because the backend already attached the role. - - - 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: + 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 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}" + - action: iam:PassRole + resource: "{target.arn}" any_of: - - - action: gameliftstreams:StartStreamSession - resource: "*" - - - action: gameliftstreams:CreateStreamUrl - resource: "*" + - - action: gameliftstreams:StartStreamSession + resource: "*" + - - action: gameliftstreams:CreateStreamUrl + resource: "*" target: kind: aws_role selector: @@ -62,15 +29,18 @@ scope: same_account aggregate_as: "GameLiftStreams-* roles passable in {account}" 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. + - 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 + - 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. + 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. + - 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/aws/grafana.yaml b/src/privilege-escalation-paths/aws/grafana.yaml index e50f8c0504..ceaf4bf680 100644 --- a/src/privilege-escalation-paths/aws/grafana.yaml +++ b/src/privilege-escalation-paths/aws/grafana.yaml @@ -6,13 +6,15 @@ 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: + 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. + 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}" + - action: grafana:CreateWorkspaceApiKey + resource: "{target.resource_arn}" target: kind: aws_service_plane_admin selector: @@ -22,10 +24,11 @@ aggregate_as: "Managed Grafana administrators in {account}" grants: [Grafana ADMIN] conditions: - - id: legacy_api_keys_supported - description: The workspace must still support legacy API keys (AWS is removing them for Grafana 9+ workspaces); workspace network access controls still apply. + - id: legacy_api_keys_supported + description: The workspace must still support legacy API keys (AWS is removing them for Grafana 9+ workspaces); + workspace network access controls still apply. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict grafana:CreateWorkspaceApiKey, migrate to service accounts and alert on ADMIN key creation. @@ -35,15 +38,17 @@ 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: + 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. + 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}" + - action: grafana:CreateWorkspaceServiceAccount + resource: "{target.resource_arn}" + - action: grafana:CreateWorkspaceServiceAccountToken + resource: "{target.resource_arn}" target: kind: aws_service_plane_admin selector: @@ -53,26 +58,29 @@ aggregate_as: "Managed Grafana administrators in {account}" grants: [Grafana ADMIN] conditions: - - id: grafana_9_or_later - description: Service accounts require Grafana 9 or later; workspace network access controls still apply. + - id: grafana_9_or_later + description: Service accounts require Grafana 9 or later; workspace network access controls still apply. blockers: - - scp_or_boundary_deny + - 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. + 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-persistence/aws-managed-grafana-persistence/README.md#grafanaupdateworkspaceauthentication--attacker-controlled-saml-idp + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-managed-grafana-persistence/README.md#grafanaupdateworkspaceauthentication--attacker-controlled-saml-idp source_revision: 6fb9ac51fd 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}" + - action: grafana:UpdateWorkspaceAuthentication + resource: "{target.resource_arn}" target: kind: aws_service_plane_admin selector: @@ -83,28 +91,33 @@ outcome: application_admin grants: [Grafana ADMIN] 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. + - 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 + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Restrict workspace authentication updates and alert on SAML metadata and administrator role-mapping changes. + 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. + - 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-updatepermissions-sso-admin provider: aws service: grafana title: Grant a controlled Identity Center identity Grafana administrator access - source: src/pentesting-cloud/aws-security/aws-persistence/aws-managed-grafana-persistence/README.md#grafanaupdatepermissions--iam-identity-center-administrator + source: + src/pentesting-cloud/aws-security/aws-persistence/aws-managed-grafana-persistence/README.md#grafanaupdatepermissions--iam-identity-center-administrator source_revision: 6fb9ac51fd - summary: The source can gain Grafana administrator access to a workspace by granting ADMIN to a controlled Identity Center user or group. + summary: The source can gain Grafana administrator access to a workspace by granting ADMIN to a controlled Identity + Center user or group. requires: all_of: - - action: grafana:UpdatePermissions - resource: "{target.resource_arn}" + - action: grafana:UpdatePermissions + resource: "{target.resource_arn}" target: kind: aws_service_plane_admin selector: @@ -115,13 +128,47 @@ outcome: application_admin grants: [Grafana ADMIN] conditions: - - id: controlled_sso_identity - description: The workspace must enable IAM Identity Center and the source must control an existing user or group member that can authenticate to it. + - id: controlled_sso_identity + description: The workspace must enable IAM Identity Center and the source must control an existing user or group + member that can authenticate to it. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict grafana:UpdatePermissions and review ADMIN grants to users and groups in each workspace. references: - - https://docs.aws.amazon.com/grafana/latest/APIReference/API_UpdatePermissions.html - notes: The grant is limited to Grafana's application plane; an individual or group still needs a valid Identity Center sign-in. + - https://docs.aws.amazon.com/grafana/latest/APIReference/API_UpdatePermissions.html + notes: The grant is limited to Grafana's application plane; an individual or group still needs a valid Identity Center + sign-in. +- id: aws-s05-01-token-for-an-existing-admin-grafana-service-account + provider: aws + service: managed-grafana + title: Token for an existing ADMIN Grafana 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: 0b36331 + summary: 'Conditional gain: ADMIN bearer token.' + requires: + all_of: + - action: grafana:CreateWorkspaceServiceAccountToken + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-01-token-for-an-existing-admin-grafana-service-account + scope: same_account + conditions: + - id: exact_verified_prerequisites + description: Known existing ADMIN service-account ID; Grafana 9+; endpoint reachable. + - 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 listed action to approved principals and exact resources. + references: [] + notes: Draft only. Missing exact evidence remains UNKNOWN; replace placeholder with the typed selector or collector + fact described alongside this draft. Required collector evidence is absent from current snapshots; missing evidence + remains UNKNOWN/unresolved. diff --git a/src/privilege-escalation-paths/aws/iam.yaml b/src/privilege-escalation-paths/aws/iam.yaml index f136d8785c..4a3ef51c13 100644 --- a/src/privilege-escalation-paths/aws/iam.yaml +++ b/src/privilege-escalation-paths/aws/iam.yaml @@ -7,11 +7,12 @@ 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). + 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}" + - action: iam:CreatePolicyVersion + resource: "{source.attached_policy_arn}" target: kind: aws_account_admin selector: @@ -20,58 +21,34 @@ scope: same_account aggregate_as: "Administrator of {account} (self-escalation)" 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). + - 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 + - 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. + 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)" - 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. + - 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-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: + 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}" + - action: iam:CreateAccessKey + resource: "{target.arn}" target: kind: aws_user selector: @@ -79,28 +56,32 @@ scope: same_account aggregate_as: "IAM users covered by iam:CreateAccessKey in {account}" conditions: - - id: access_key_limit - description: A user can hold at most two access keys; if the target already has two, iam:DeleteAccessKey on the target is also required. + - id: access_key_limit + description: A user can hold at most two access keys; if the target already has two, iam:DeleteAccessKey on the + target is also required. blockers: - - scp_or_boundary_deny + - 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. + 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. + - 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: + 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}" + - action: iam:CreateLoginProfile + resource: "{target.arn}" target: kind: aws_user selector: @@ -109,28 +90,29 @@ scope: same_account aggregate_as: "IAM users without a console password covered by iam:CreateLoginProfile in {account}" conditions: - - id: target_mfa - description: If the target has an MFA device enrolled, console sign-in requires it and the technique is blocked. + - 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 + - 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 + - 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: + 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}" + - action: iam:UpdateLoginProfile + resource: "{target.arn}" target: kind: aws_user selector: @@ -139,31 +121,34 @@ scope: same_account aggregate_as: "IAM users with a console password covered by iam:UpdateLoginProfile in {account}" conditions: - - id: target_mfa - description: If the target has an MFA device enrolled, console sign-in requires it and the technique is blocked. + - 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 + - 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. + 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 + - 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: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamcreateservicespecificcredential--iamresetservicespecificcredential source_revision: 171e422299 - summary: The source can obtain the service-scoped privileges (CodeCommit, Keyspaces, Bedrock) of IAM users for which it can create or reset service-specific credentials. + summary: The source can obtain the service-scoped privileges (CodeCommit, Keyspaces, Bedrock) 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}" + - - action: iam:CreateServiceSpecificCredential + resource: "{target.arn}" + - - action: iam:ResetServiceSpecificCredential + resource: "{target.arn}" target: kind: aws_user selector: @@ -171,30 +156,33 @@ scope: same_account aggregate_as: "IAM users covered by service-specific credential management in {account}" conditions: - - id: service_scoped_credential - description: The credential only works against the specific service (CodeCommit, Keyspaces, Bedrock), so only the target's permissions on that service are gained. - - id: reset_requires_existing_credential - description: The Reset variant only applies when the target already has a service-specific credential. + - id: service_scoped_credential + description: The credential only works against the specific service (CodeCommit, Keyspaces, Bedrock), so only the + target's permissions on that service are gained. + - 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 + - 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: The selector key resource_permission_covers_target uses whichever of the any_of actions matched. Partial privilege gain only. + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateServiceSpecificCredential.html + notes: The selector key resource_permission_covers_target uses whichever of the any_of actions matched. 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: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamuploadsshpublickey--iamdeactivatemfadevice source_revision: 171e422299 summary: The source can obtain the CodeCommit privileges of IAM users for which it can upload an SSH public key. requires: all_of: - - action: iam:UploadSSHPublicKey - resource: "{target.arn}" + - action: iam:UploadSSHPublicKey + resource: "{target.arn}" target: kind: aws_user selector: @@ -202,28 +190,31 @@ scope: same_account aggregate_as: "IAM users covered by iam:UploadSSHPublicKey in {account}" conditions: - - id: service_scoped_credential - description: IAM SSH keys are only accepted by CodeCommit; only the target's CodeCommit permissions are gained (CodeCommit is closed to new customers since 2024). + - id: service_scoped_credential + description: IAM SSH keys are only accepted by CodeCommit; only the target's CodeCommit permissions are gained + (CodeCommit is closed to new customers since 2024). blockers: - - scp_or_boundary_deny + - 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). + - 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: + 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}" + - action: iam:AttachUserPolicy + resource: "{source.arn}" target: kind: aws_account_admin selector: @@ -232,27 +223,31 @@ scope: same_account aggregate_as: "Administrator of {account} (self-escalation)" conditions: - - id: policyarn_condition - description: An iam:PolicyARN condition limiting which managed policies may be attached removes or limits the escalation. + - 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 + - scp_or_boundary_deny confidence: derived severity: critical - mitigation: Never grant iam:AttachUserPolicy on the principal itself; constrain with iam:PolicyARN and permissions boundaries. + 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. + 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: + 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}" + - action: iam:PutUserPolicy + resource: "{source.arn}" target: kind: aws_account_admin selector: @@ -262,10 +257,11 @@ aggregate_as: "Administrator of {account} (self-escalation)" conditions: [] blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: derived severity: critical - mitigation: Never grant iam:PutUserPolicy on the principal itself; use permissions boundaries for delegated IAM administration. + mitigation: Never grant iam:PutUserPolicy on the principal itself; use permissions boundaries for delegated IAM + administration. references: [] notes: "" @@ -273,13 +269,14 @@ 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: + 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}" + - action: iam:AttachGroupPolicy + resource: "{source.group_arn}" target: kind: aws_account_admin selector: @@ -289,27 +286,29 @@ scope: same_account aggregate_as: "Administrator of {account} (self-escalation)" conditions: - - id: policyarn_condition - description: An iam:PolicyARN condition limiting attachable policies removes or limits the escalation. + - id: policyarn_condition + description: An iam:PolicyARN condition limiting attachable policies removes or limits the escalation. blockers: - - scp_or_boundary_deny + - 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)." + 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: + 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}" + - action: iam:PutGroupPolicy + resource: "{source.group_arn}" target: kind: aws_account_admin selector: @@ -320,24 +319,26 @@ aggregate_as: "Administrator of {account} (self-escalation)" conditions: [] blockers: - - scp_or_boundary_deny + - 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)." + 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: + 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}" + - action: iam:AttachRolePolicy + resource: "{source.arn}" target: kind: aws_account_admin selector: @@ -346,13 +347,14 @@ scope: same_account aggregate_as: "Administrator of {account} (self-escalation)" conditions: - - id: policyarn_condition - description: An iam:PolicyARN condition limiting attachable policies removes or limits the escalation. + - id: policyarn_condition + description: An iam:PolicyARN condition limiting attachable policies removes or limits the escalation. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: derived severity: critical - mitigation: Never grant iam:AttachRolePolicy on the role itself; use permissions boundaries for delegated role administration. + 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)." @@ -360,13 +362,14 @@ 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: + 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}" + - action: iam:PutRolePolicy + resource: "{source.arn}" target: kind: aws_account_admin selector: @@ -376,10 +379,11 @@ aggregate_as: "Administrator of {account} (self-escalation)" conditions: [] blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: derived severity: critical - mitigation: Never grant iam:PutRolePolicy on the role itself; use permissions boundaries for delegated role administration. + 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)." @@ -387,15 +391,16 @@ 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: + 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}" - - - action: iam:PutRolePolicy - resource: "{source.assumable_role_arn}" + - - action: iam:AttachRolePolicy + resource: "{source.assumable_role_arn}" + - - action: iam:PutRolePolicy + resource: "{source.assumable_role_arn}" target: kind: aws_account_admin selector: @@ -403,32 +408,38 @@ scope: same_account aggregate_as: "Administrator of {account} (via an assumable role)" 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. + - 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 + - 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. + 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)." + 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: + 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. + 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: "*" + - action: iam:CreateRole + resource: "*" any_of: - - - action: iam:AttachRolePolicy - resource: "*" - - - action: iam:PutRolePolicy - resource: "*" + - - action: iam:AttachRolePolicy + resource: "*" + - - action: iam:PutRolePolicy + resource: "*" target: kind: aws_account_admin selector: @@ -436,20 +447,26 @@ scope: same_account aggregate_as: "Administrator of {account} (via a newly created role)" conditions: - - id: permissions_boundary_condition - description: An iam:PermissionsBoundary condition on CreateRole forces new roles to carry a boundary and removes the escalation. - - 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). + - id: permissions_boundary_condition + description: An iam:PermissionsBoundary condition on CreateRole forces new roles to carry a boundary and removes the + escalation. + - 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 + - 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. + 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: "Resource \"*\" means the actions must cover a common (newly creatable) role ARN; the evaluator should intersect their Resources." + - https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html + notes: "Resource \"*\" means the actions must cover a common (newly creatable) role ARN; the evaluator should intersect + their Resources." - id: aws-iam-addusertogroup provider: aws @@ -460,8 +477,8 @@ 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}" + - action: iam:AddUserToGroup + resource: "{target.arn}" target: kind: aws_group selector: @@ -471,12 +488,13 @@ aggregate_as: "IAM groups covered by iam:AddUserToGroup in {account}" conditions: [] blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: derived 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; role sources cannot use this (they could add some other user they control, covered by user-credential techniques). + notes: The Resource of iam:AddUserToGroup is the group ARN. Only IAM users can be group members; role sources cannot + use this (they could add some other user they control, covered by user-credential techniques). - id: aws-iam-updateassumerolepolicy provider: aws @@ -487,8 +505,8 @@ summary: The source can obtain the privileges of roles whose trust policy it can rewrite. requires: all_of: - - action: iam:UpdateAssumeRolePolicy - resource: "{target.arn}" + - action: iam:UpdateAssumeRolePolicy + resource: "{target.arn}" target: kind: aws_role selector: @@ -496,28 +514,30 @@ scope: same_account aggregate_as: "IAM roles covered by iam:UpdateAssumeRolePolicy in {account}" 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. + - 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 + - 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 + - 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: + 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}" + - action: iam:UpdateSAMLProvider + resource: "{target.saml_provider_arn}" target: kind: aws_role selector: @@ -525,31 +545,35 @@ 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. + - 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 + - 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." + - 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-putuserpermissionsboundary-self provider: aws service: iam title: Replace or remove the permissions boundary of the source user - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputuserpermissionsboundary + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputuserpermissionsboundary source_revision: 171e422299 - summary: The source IAM user can obtain the full privileges of its identity policies by replacing or removing its own permissions boundary. + summary: The source IAM user can obtain the full privileges of its identity policies by replacing or removing its own + permissions boundary. requires: all_of: [] any_of: - - - action: iam:PutUserPermissionsBoundary - resource: "{source.arn}" - - - action: iam:DeleteUserPermissionsBoundary - resource: "{source.arn}" + - - action: iam:PutUserPermissionsBoundary + resource: "{source.arn}" + - - action: iam:DeleteUserPermissionsBoundary + resource: "{source.arn}" target: kind: aws_account_admin selector: @@ -558,31 +582,35 @@ scope: same_account aggregate_as: "Administrator of {account} (self-escalation)" conditions: - - id: unbounded_identity_policy_is_admin - description: Only an escalation if the source currently has a boundary and its identity policies are broader than the boundary; reaching admin requires the identity policies to be admin-equivalent. + - id: unbounded_identity_policy_is_admin + description: Only an escalation if the source currently has a boundary and its identity policies are broader than + the boundary; reaching admin requires the identity policies to be admin-equivalent. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high mitigation: Explicitly deny iam:Put/DeleteUserPermissionsBoundary on self inside every permissions boundary. references: - - https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html - notes: DeleteUserPermissionsBoundary is added as an equivalent alternative (official API); HackTricks documents the Put variant. + - https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html + notes: DeleteUserPermissionsBoundary is added as an equivalent alternative (official API); HackTricks documents the + Put variant. - id: aws-iam-putrolepermissionsboundary-self provider: aws service: iam title: Replace or remove the permissions boundary of the source role - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputrolepermissionsboundary + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputrolepermissionsboundary source_revision: 171e422299 - summary: The source role can obtain the full privileges of its identity policies by replacing or removing its own permissions boundary. + summary: The source role can obtain the full privileges of its identity policies by replacing or removing its own + permissions boundary. requires: all_of: [] any_of: - - - action: iam:PutRolePermissionsBoundary - resource: "{source.arn}" - - - action: iam:DeleteRolePermissionsBoundary - resource: "{source.arn}" + - - action: iam:PutRolePermissionsBoundary + resource: "{source.arn}" + - - action: iam:DeleteRolePermissionsBoundary + resource: "{source.arn}" target: kind: aws_account_admin selector: @@ -591,101 +619,34 @@ scope: same_account aggregate_as: "Administrator of {account} (self-escalation)" conditions: - - id: unbounded_identity_policy_is_admin - description: Only an escalation if the source currently has a boundary and its identity policies are broader than the boundary; reaching admin requires the identity policies to be admin-equivalent. + - id: unbounded_identity_policy_is_admin + description: Only an escalation if the source currently has a boundary and its identity policies are broader than + the boundary; reaching admin requires the identity policies to be admin-equivalent. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high mitigation: Explicitly deny iam:Put/DeleteRolePermissionsBoundary on self inside every permissions boundary. references: - - https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html - notes: Changing a boundary of another role the source can assume is the same edge via an assumable role; not modelled separately. - -- id: aws-iam-updateuser-path-move - provider: aws - service: iam - title: Move another user into an IAM path where the source's credential permissions already apply - 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 - summary: The source can obtain the privileges of a user it can rename by changing the user's path into one where it already holds credential-creation permissions. - requires: - all_of: - - action: iam:UpdateUser - resource: "{target.arn}" - any_of: - - - action: iam:CreateAccessKey - resource: "arn:aws:iam::{target.account}:user/*" - - - action: iam:CreateLoginProfile - resource: "arn:aws:iam::{target.account}:user/*" - - - action: iam:UpdateLoginProfile - resource: "arn:aws:iam::{target.account}:user/*" - target: - kind: aws_user - selector: - resource_permission_covers_target: iam:UpdateUser - scope: same_account - aggregate_as: "Users the source can move into a path it controls in {account}" - conditions: - - id: new_path_covered - description: iam:UpdateUser is authorized on both the current and the new user ARN, and the credential permission must cover the user at its new path; the evaluator only checks that some user path is covered. - - id: login_profile_state - description: CreateLoginProfile needs the user to have no password yet; UpdateLoginProfile needs an existing one; CreateAccessKey needs fewer than two keys. - blockers: - - scp_or_boundary_deny - confidence: conditional - severity: critical - mitigation: Treat iam:UpdateUser as a credential-management permission; do not scope IAM write permissions by path when principals can change paths. - references: - - https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateUser.html - - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html - notes: Path-scoped policy and boundary attachment variants (AttachUserPolicy / PutUserPolicy on a path) are covered by the same reasoning but drawn only through credential creation here. - -- id: aws-iam-updategroup-path-move - provider: aws - service: iam - title: Move a group into an IAM path where the source can add members - 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 - summary: The source user can obtain the privileges of a group it can rename by moving it into a path where it holds iam:AddUserToGroup and joining it. - requires: - all_of: - - action: iam:UpdateGroup - resource: "{target.arn}" - - action: iam:AddUserToGroup - resource: "arn:aws:iam::{target.account}:group/*" - target: - kind: aws_group - selector: - resource_permission_covers_target: iam:UpdateGroup - source_kind: aws_user - scope: same_account - aggregate_as: "Groups the source can move into a path it controls in {account}" - conditions: - - id: new_path_covered - description: iam:UpdateGroup is authorized on both the current and the new group ARN, and iam:AddUserToGroup must cover the group at its new path; the evaluator only checks that some group path is covered. - blockers: - - scp_or_boundary_deny - confidence: conditional - severity: critical - mitigation: Treat iam:UpdateGroup as a membership-management permission and avoid path-scoped iam:AddUserToGroup grants. - references: - - https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateGroup.html - notes: Only IAM users can be group members, hence source_kind aws_user. + - https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html + notes: Changing a boundary of another role the source can assume is the same edge via an assumable role; not modelled + separately. - 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: + 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. + 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}" + - action: iam:DeleteSAMLProvider + resource: "{target.saml_provider_arn}" + - action: iam:CreateSAMLProvider + resource: "{target.saml_provider_arn}" target: kind: aws_role selector: @@ -693,35 +654,44 @@ 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. + - 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 + - scp_or_boundary_deny confidence: derived severity: critical - mitigation: Restrict iam:CreateSAMLProvider / DeleteSAMLProvider / UpdateSAMLProvider to administrators and alert on identity-provider changes. + 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. + - 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-oidcprovider-add-client-id provider: aws service: iam title: Register an attacker-chosen audience on an OIDC provider that roles trust - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamaddclientidtoopenidconnectprovider--widen-an-existing-federation-trust + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamaddclientidtoopenidconnectprovider--widen-an-existing-federation-trust source_revision: 171e422299 - summary: The source can obtain the privileges of roles trusting an IAM OIDC provider by registering an audience it can mint tokens for (AddClientIDToOpenIDConnectProvider, or deleting and recreating the provider with its own client-ID list), when the role's sub/other claim conditions are satisfiable by tokens of that issuer. + summary: The source can obtain the privileges of roles trusting an IAM OIDC provider by registering an audience it can + mint tokens for (AddClientIDToOpenIDConnectProvider, or deleting and recreating the provider with its own client-ID + list), when the role's sub/other claim conditions are satisfiable by tokens of that issuer. requires: any_of: - - - action: iam:AddClientIDToOpenIDConnectProvider - resource: "{target.oidc_provider_arn}" - - - action: iam:DeleteOpenIDConnectProvider - resource: "{target.oidc_provider_arn}" - - action: iam:CreateOpenIDConnectProvider - resource: "{target.oidc_provider_arn}" + - - action: iam:AddClientIDToOpenIDConnectProvider + resource: "{target.oidc_provider_arn}" + - - action: iam:DeleteOpenIDConnectProvider + resource: "{target.oidc_provider_arn}" + - action: iam:CreateOpenIDConnectProvider + resource: "{target.oidc_provider_arn}" target: kind: aws_role selector: @@ -729,33 +699,42 @@ scope: same_account aggregate_as: "Roles trusting an OIDC provider whose audiences the source can change in {account}" conditions: - - id: issuer_tokens_obtainable - description: The source must obtain tokens signed by the provider's issuer (the provider URL and its JWKS cannot be changed without changing the provider ARN), for example from a public CI issuer such as GitHub Actions or from a workload of an EKS cluster. - - id: trust_claim_conditions - description: Trust conditions on sub, repository, namespace or other claims must be satisfiable by those tokens; a trust pinning only the audience is satisfiable after the audience is registered. - - id: disruption - description: Deleting and recreating the provider breaks federation until it is recreated; AddClientIDToOpenIDConnectProvider is additive and silent. + - id: issuer_tokens_obtainable + description: The source must obtain tokens signed by the provider's issuer (the provider URL and its JWKS cannot be + changed without changing the provider ARN), for example from a public CI issuer such as GitHub Actions or from a + workload of an EKS cluster. + - id: trust_claim_conditions + description: Trust conditions on sub, repository, namespace or other claims must be satisfiable by those tokens; a + trust pinning only the audience is satisfiable after the audience is registered. + - id: disruption + description: Deleting and recreating the provider breaks federation until it is recreated; + AddClientIDToOpenIDConnectProvider is additive and silent. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Restrict iam:AddClientIDToOpenIDConnectProvider / CreateOpenIDConnectProvider / DeleteOpenIDConnectProvider to administrators, pin sub (and repository / namespace) claims in every OIDC trust, and alert on provider changes. + mitigation: Restrict iam:AddClientIDToOpenIDConnectProvider / CreateOpenIDConnectProvider / + DeleteOpenIDConnectProvider to administrators, pin sub (and repository / namespace) claims in every OIDC trust, and + alert on provider changes. references: - - https://docs.aws.amazon.com/IAM/latest/APIReference/API_AddClientIDToOpenIDConnectProvider.html - - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html - notes: The trust policy's own :aud condition still has to accept the new audience (or be absent). The role-to-provider join is the Federated oidc-provider ARN of the role's trust policy ({target.oidc_provider_arn}). + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_AddClientIDToOpenIDConnectProvider.html + - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html + notes: The trust policy's own :aud condition still has to accept the new audience (or be absent). The + role-to-provider join is the Federated oidc-provider ARN of the role's trust policy ({target.oidc_provider_arn}). - 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: + 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. + 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}" + - action: iam:CreateSAMLProvider + resource: "{target.saml_provider_arn}" target: kind: aws_role selector: @@ -763,28 +742,33 @@ 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. + - 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 + - scp_or_boundary_deny confidence: derived severity: critical - mitigation: Remove trust statements naming deleted identity providers and restrict iam:CreateSAMLProvider to administrators. + 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. + - 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-createoidcprovider-orphaned-trust provider: aws service: iam title: Register an OIDC 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: + 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 an OIDC provider ARN of the account that does not exist, by creating that provider (for the issuer URL in the ARN) with an audience it can obtain tokens for. + summary: The source can obtain the privileges of roles whose trust names an OIDC provider ARN of the account that does + not exist, by creating that provider (for the issuer URL in the ARN) with an audience it can obtain tokens for. requires: all_of: - - action: iam:CreateOpenIDConnectProvider - resource: "{target.oidc_provider_arn}" + - action: iam:CreateOpenIDConnectProvider + resource: "{target.oidc_provider_arn}" target: kind: aws_role selector: @@ -792,37 +776,43 @@ scope: same_account aggregate_as: "Roles trusting a missing OIDC provider in {account}" conditions: - - id: issuer_tokens_obtainable - description: The provider ARN fixes the issuer URL, so the source must obtain tokens of that issuer (public CI issuers such as GitHub Actions issue tokens to anyone's workflows) whose claims satisfy the trust conditions. + - id: issuer_tokens_obtainable + description: The provider ARN fixes the issuer URL, so the source must obtain tokens of that issuer (public CI + issuers such as GitHub Actions issue tokens to anyone's workflows) whose claims satisfy the trust conditions. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Remove trust statements naming deleted identity providers, pin sub claims, and restrict iam:CreateOpenIDConnectProvider to administrators. + mitigation: Remove trust statements naming deleted identity providers, pin sub claims, and restrict + iam:CreateOpenIDConnectProvider to administrators. references: - - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateOpenIDConnectProvider.html - notes: Needs the account's OIDC provider inventory (iam:ListOpenIDConnectProviders); without it the targets are unresolved placeholders. + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_CreateOpenIDConnectProvider.html + notes: Needs the account's OIDC provider inventory (iam:ListOpenIDConnectProviders); 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: + 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. + 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:aws:iam::{target.account}:mfa/*" - - action: iam:EnableMFADevice - resource: "{target.arn}" + - action: iam:CreateVirtualMFADevice + resource: "arn:aws: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}" + - - action: iam:CreateAccessKey + resource: "{target.arn}" + - - action: iam:CreateLoginProfile + resource: "{target.arn}" + - - action: iam:UpdateLoginProfile + resource: "{target.arn}" target: kind: aws_user selector: @@ -831,37 +821,46 @@ aggregate_as: IAM users on which the source can enrol its own MFA device and mint credentials in {account} outcome: credentials 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); CreateLoginProfile needs the user to have no console password; UpdateLoginProfile needs an existing one. + - 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); CreateLoginProfile needs + the user to have no console password; UpdateLoginProfile needs an existing one. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: derived 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. + 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. + - 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: + 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. + 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}" + - action: iam:DeactivateMFADevice + resource: "{target.arn}" any_of: - - - action: iam:CreateLoginProfile - resource: "{target.arn}" - - - action: iam:UpdateLoginProfile - resource: "{target.arn}" + - - action: iam:CreateLoginProfile + resource: "{target.arn}" + - - action: iam:UpdateLoginProfile + resource: "{target.arn}" target: kind: aws_user selector: @@ -870,38 +869,45 @@ aggregate_as: IAM users whose MFA the source can remove and whose password it can set in {account} outcome: credentials 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. + - 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 + - scp_or_boundary_deny confidence: derived severity: critical - mitigation: Restrict iam:DeactivateMFADevice and login-profile management on other users to break-glass administrators and alert on DeactivateMFADevice. + 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. + - 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-updateuser-path-move-self-policy provider: aws service: iam title: Move the source user into an IAM path where it can edit user policies - 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: + 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 - summary: The source IAM user can obtain administrator privileges by changing its own path into one where it holds path-scoped iam:AttachUserPolicy or iam:PutUserPolicy and then granting itself a policy. + summary: The source IAM user can obtain administrator privileges by changing its own path into one where it holds + path-scoped iam:AttachUserPolicy or iam:PutUserPolicy and then granting itself a policy. requires: all_of: - - action: iam:UpdateUser - resource: "{source.arn}" + - action: iam:UpdateUser + resource: "{source.arn}" any_of: - - - action: iam:AttachUserPolicy - resource: "arn:aws:iam::{source.account}:user/*" - - - action: iam:PutUserPolicy - resource: "arn:aws:iam::{source.account}:user/*" + - - action: iam:AttachUserPolicy + resource: "arn:aws:iam::{source.account}:user/*" + - - action: iam:PutUserPolicy + resource: "arn:aws:iam::{source.account}:user/*" target: kind: aws_account_admin selector: @@ -911,36 +917,42 @@ aggregate_as: Administrator of {account} (self-escalation via path move) outcome: permission_grant conditions: - - id: new_path_covered - description: iam:UpdateUser is authorized on both the current and the new user ARN, and the policy-edit permission must cover the source at its new path; the evaluator only checks that some user path is covered. - - id: policyarn_condition - description: An iam:PolicyARN condition limiting attachable policies removes or limits the AttachUserPolicy variant. + - id: new_path_covered + description: iam:UpdateUser is authorized on both the current and the new user ARN, and the policy-edit permission + must cover the source at its new path; the evaluator only checks that some user path is covered. + - id: policyarn_condition + description: An iam:PolicyARN condition limiting attachable policies removes or limits the AttachUserPolicy variant. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: critical - mitigation: Treat iam:UpdateUser as a privileged permission; do not scope IAM policy-edit permissions by path when principals can change their own path. + mitigation: Treat iam:UpdateUser as a privileged permission; do not scope IAM policy-edit permissions by path when + principals can change their own path. references: - - https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateUser.html - - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html - notes: Policy-edit counterpart of aws-iam-updateuser-path-move (which models credential creation on a moved victim). If the source already holds the policy permission on its current ARN, aws-iam-attachuserpolicy-self / putuserpolicy-self apply directly. + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateUser.html + - https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_identifiers.html + notes: Policy-edit counterpart of aws-iam-updateuser-path-move (which models credential creation on a moved victim). + If the source already holds the policy permission on its current ARN, aws-iam-attachuserpolicy-self / + putuserpolicy-self apply directly. - id: aws-iam-updategroup-path-move-self-policy provider: aws service: iam title: Move one of the source's groups into an IAM path where it can edit group policies - 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: + 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 - summary: The source IAM user can obtain administrator privileges by moving one of its groups into a path where it holds path-scoped iam:AttachGroupPolicy or iam:PutGroupPolicy and then granting the group a policy. + summary: The source IAM user can obtain administrator privileges by moving one of its groups into a path where it + holds path-scoped iam:AttachGroupPolicy or iam:PutGroupPolicy and then granting the group a policy. requires: all_of: - - action: iam:UpdateGroup - resource: "{source.group_arn}" + - action: iam:UpdateGroup + resource: "{source.group_arn}" any_of: - - - action: iam:AttachGroupPolicy - resource: "arn:aws:iam::{source.account}:group/*" - - - action: iam:PutGroupPolicy - resource: "arn:aws:iam::{source.account}:group/*" + - - action: iam:AttachGroupPolicy + resource: "arn:aws:iam::{source.account}:group/*" + - - action: iam:PutGroupPolicy + resource: "arn:aws:iam::{source.account}:group/*" target: kind: aws_account_admin selector: @@ -951,32 +963,37 @@ aggregate_as: Administrator of {account} (self-escalation via group path move) outcome: permission_grant conditions: - - id: new_path_covered - description: iam:UpdateGroup is authorized on both the current and the new group ARN, and the policy-edit permission must cover the group at its new path; the evaluator only checks that some group path is covered. - - id: policyarn_condition - description: An iam:PolicyARN condition limiting attachable policies removes or limits the AttachGroupPolicy variant. + - id: new_path_covered + description: iam:UpdateGroup is authorized on both the current and the new group ARN, and the policy-edit permission + must cover the group at its new path; the evaluator only checks that some group path is covered. + - id: policyarn_condition + description: An iam:PolicyARN condition limiting attachable policies removes or limits the AttachGroupPolicy + variant. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: critical mitigation: Treat iam:UpdateGroup as a privileged permission and avoid path-scoped group policy-edit grants. references: - - https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateGroup.html - notes: '{source.group_arn} is one of the source user''s groups. Policy-edit counterpart of aws-iam-updategroup-path-move (which models joining a moved group).' + - https://docs.aws.amazon.com/IAM/latest/APIReference/API_UpdateGroup.html + notes: '{source.group_arn} is one of the source user''s groups. Policy-edit counterpart of aws-iam-updategroup-path-move + (which models joining a moved group).' - id: aws-iam-rolepermissionsboundary-assumable-role provider: aws service: iam title: Replace or remove the permissions boundary of a role the source can assume - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputrolepermissionsboundary + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-iam-privesc/README.md#iamputrolepermissionsboundary source_revision: 6fb9ac51fd - summary: The source can obtain the full identity-policy privileges of a boundary-capped role it can assume by replacing or removing that role's permissions boundary. + summary: The source can obtain the full identity-policy privileges of a boundary-capped role it can assume by + replacing or removing that role's permissions boundary. requires: any_of: - - - action: iam:PutRolePermissionsBoundary - resource: "{source.assumable_role_arn}" - - - action: iam:DeleteRolePermissionsBoundary - resource: "{source.assumable_role_arn}" + - - action: iam:PutRolePermissionsBoundary + resource: "{source.assumable_role_arn}" + - - action: iam:DeleteRolePermissionsBoundary + resource: "{source.assumable_role_arn}" target: kind: aws_account_admin selector: @@ -985,38 +1002,44 @@ aggregate_as: Administrator of {account} (via an assumable role's boundary) outcome: scope_control conditions: - - id: unbounded_identity_policy_is_admin - description: Only an escalation if the assumable role currently has a boundary and its identity policies are broader than it; reaching admin requires those identity policies to be admin-equivalent. + - id: unbounded_identity_policy_is_admin + description: Only an escalation if the assumable role currently has a boundary and its identity policies are broader + than it; reaching admin requires those identity policies to be admin-equivalent. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Explicitly deny iam:Put/DeleteRolePermissionsBoundary for delegated administrators on roles they can assume, and require boundaries via iam:PermissionsBoundary conditions. + mitigation: Explicitly deny iam:Put/DeleteRolePermissionsBoundary for delegated administrators on roles they can + assume, and require boundaries via iam:PermissionsBoundary conditions. references: - - https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html - notes: Assumable-role counterpart of aws-iam-putrolepermissionsboundary-self (whose notes say this edge was not modelled). via_assumable_role_covered_by applies to whichever any_of action matched. + - https://docs.aws.amazon.com/IAM/latest/UserGuide/access_policies_boundaries.html + notes: Assumable-role counterpart of aws-iam-putrolepermissionsboundary-self (whose notes say this edge was not + modelled). via_assumable_role_covered_by applies to whichever any_of action matched. - id: aws-iam-createrole-satisfy-cross-account-trust provider: aws service: iam title: Create a role in a trusted account to satisfy another account's role trust - source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/iam-trust-and-federation-attacks.md#path-name-and-arn-conditions + source: + src/pentesting-cloud/aws-security/aws-cross-account-attacks/iam-trust-and-federation-attacks.md#path-name-and-arn-conditions source_revision: 6fb9ac51fd - summary: A principal that can create and grant permissions to a role in its own account can obtain the privileges of roles in other accounts whose trust delegates to that account (account root, or Principal "*" filtered by aws:PrincipalArn path/name patterns), even without holding sts:AssumeRole itself. + summary: A principal that can create and grant permissions to a role in its own account can obtain the privileges of + roles in other accounts whose trust delegates to that account (account root, or Principal "*" filtered by + aws:PrincipalArn path/name patterns), even without holding sts:AssumeRole itself. requires: all_of: - - action: iam:CreateRole + - action: iam:CreateRole + resource: "arn:aws:iam::{source.account}:role/*" + bind: new_role + request_context: + iam:PermissionsBoundary: {absent: true} + any_of: + - - action: iam:PutRolePolicy + resource: "arn:aws:iam::{source.account}:role/*" + bind: new_role + - - action: iam:AttachRolePolicy resource: "arn:aws:iam::{source.account}:role/*" bind: new_role - request_context: - iam:PermissionsBoundary: {absent: true} - any_of: - - - action: iam:PutRolePolicy - resource: "arn:aws:iam::{source.account}:role/*" - bind: new_role - - - action: iam:AttachRolePolicy - resource: "arn:aws:iam::{source.account}:role/*" - bind: new_role target: kind: aws_role selector: @@ -1025,25 +1048,35 @@ aggregate_as: "Roles in other accounts trusting {account} that a newly created role can satisfy" outcome: credentials conditions: - - id: principal_arn_pattern_matchable - description: Trusts filtered with aws:PrincipalArn (ArnLike path or name patterns, or a deleted-and-recreatable role name) are satisfied only when CreateRole/PutRolePolicy cover a role path and name matching the pattern. - - id: trust_names_specific_principal - description: Trusts that name a specific existing principal ARN in Principal (stored as its unique id) cannot be satisfied by a new role; those targets are false positives of this entry. - - id: other_trust_conditions - description: ExternalId, MFA, aws:PrincipalOrgID, source IP/VPC or tag conditions on the trust must also be satisfiable by the new role session. - - id: new_role_identity_policy - description: The source writes the new role's identity policy allowing sts:AssumeRole on the target; a permissions boundary forced on CreateRole or an SCP deny on sts:AssumeRole blocks it. + - id: principal_arn_pattern_matchable + description: Trusts filtered with aws:PrincipalArn (ArnLike path or name patterns, or a deleted-and-recreatable role + name) are satisfied only when CreateRole/PutRolePolicy cover a role path and name matching the pattern. + - id: trust_names_specific_principal + description: Trusts that name a specific existing principal ARN in Principal (stored as its unique id) cannot be + satisfied by a new role; those targets are false positives of this entry. + - id: other_trust_conditions + description: ExternalId, MFA, aws:PrincipalOrgID, source IP/VPC or tag conditions on the trust must also be + satisfiable by the new role session. + - id: new_role_identity_policy + description: The source writes the new role's identity policy allowing sts:AssumeRole on the target; a permissions + boundary forced on CreateRole or an SCP deny on sts:AssumeRole blocks it. preconditions: - - target_in_other_account + - target_in_other_account blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: critical - mitigation: Trust specific role ARNs in Principal instead of account roots or "*" with aws:PrincipalArn patterns, require iam:PermissionsBoundary on iam:CreateRole in trusted accounts, and pin cross-account trusts to aws:PrincipalOrgID plus exact role ARNs. + mitigation: Trust specific role ARNs in Principal instead of account roots or "*" with aws:PrincipalArn patterns, + require iam:PermissionsBoundary on iam:CreateRole in trusted accounts, and pin cross-account trusts to + aws:PrincipalOrgID plus exact role ARNs. 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: Complements aws-sts-assumerole-trusted (which needs sts:AssumeRole on the target in the source's own policy) and aws-iam-createrole-attach-assume (same-account admin). Same-account targets are left to aws-iam-createrole-attach-assume through target_in_other_account. A role trusting the source's account root, or "*" with an aws:PrincipalArn condition, is satisfiable by any new role in that account; trust conditions keep the edge conditional. + - 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: Complements aws-sts-assumerole-trusted (which needs sts:AssumeRole on the target in the source's own policy) + and aws-iam-createrole-attach-assume (same-account admin). Same-account targets are left to + aws-iam-createrole-attach-assume through target_in_other_account. A role trusting the source's account root, or "*" + with an aws:PrincipalArn condition, is satisfiable by any new role in that account; trust conditions keep the edge + conditional. - id: aws-iam-createpolicyversion-assumable-role provider: aws @@ -1054,8 +1087,8 @@ 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}" + - action: iam:CreatePolicyVersion + resource: "{source.assumable_role_attached_policy_arn}" target: kind: aws_account_admin selector: @@ -1063,8 +1096,8 @@ 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. + - 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 diff --git a/src/privilege-escalation-paths/aws/iot.yaml b/src/privilege-escalation-paths/aws/iot.yaml index 8be9df4fe1..e077ce8e76 100644 --- a/src/privilege-escalation-paths/aws/iot.yaml +++ b/src/privilege-escalation-paths/aws/iot.yaml @@ -5,25 +5,27 @@ 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: + 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 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 + - 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: "*" - - 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: @@ -33,17 +35,91 @@ 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. + - 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 + - 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 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. +- 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 + summary: A claim-derived device certificate can use an IoT policy permitting credential exchange through an existing + role alias. + requires: + all_of: + - action: iot:CreateProvisioningTemplate + resource: '*' + - action: iot:CreateProvisioningClaim + resource: '*' + - action: iam:PassRole + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-iot-provisioning-claim-existing-rolealias + scope: same_account + 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/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. + - 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: Required collector evidence is absent from current snapshots; missing evidence remains UNKNOWN/unresolved. +- 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 + summary: The source can register an attacker-held certificate and attach a policy that permits credential exchange + through an existing role alias. + requires: + all_of: + - action: iot:RegisterCertificateWithoutCA + resource: '*' + - action: iot:AttachPolicy + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-iot-byo-certificate-existing-rolealias + scope: same_account + 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: Required collector evidence is absent from current snapshots; missing evidence remains UNKNOWN/unresolved. diff --git a/src/privilege-escalation-paths/aws/lambda.yaml b/src/privilege-escalation-paths/aws/lambda.yaml index 84e5647362..eddfe947b8 100644 --- a/src/privilege-escalation-paths/aws/lambda.yaml +++ b/src/privilege-escalation-paths/aws/lambda.yaml @@ -13,17 +13,18 @@ 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: + 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}" - - action: lambda:CreateFunction - resource: "*" - - action: lambda:InvokeFunction - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: lambda:CreateFunction + resource: "*" + - action: lambda:InvokeFunction + resource: "*" target: kind: aws_role selector: @@ -32,34 +33,39 @@ scope: same_account aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" 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. + - 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 + - scp_or_boundary_deny confidence: derived 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. + 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 + - 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: + 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. + 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}" - - action: lambda:CreateFunction - resource: "*" - - action: lambda:AddPermission - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: lambda:CreateFunction + resource: "*" + - action: lambda:AddPermission + resource: "*" target: kind: aws_role selector: @@ -68,12 +74,13 @@ scope: same_account aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" conditions: - - id: passrole_condition_key - description: iam:PassedToService / iam:AssociatedResourceArn conditions may restrict which roles can be passed. - - id: function_url_or_invoke_path - description: Invocation relies on the function resource policy granting the source (or a public Function URL); a lambda:FunctionUrlAuthType or principal-restricting condition on AddPermission may limit it. + - id: passrole_condition_key + description: iam:PassedToService / iam:AssociatedResourceArn conditions may restrict which roles can be passed. + - id: function_url_or_invoke_path + description: Invocation relies on the function resource policy granting the source (or a public Function URL); a + lambda:FunctionUrlAuthType or principal-restricting condition on AddPermission may limit it. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: derived severity: critical mitigation: Restrict iam:PassRole and lambda:AddPermission; deny lambda:AddPermission except to deployment principals. @@ -84,17 +91,19 @@ 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: + 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. + 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: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: lambda:CreateFunction + resource: "*" + - action: lambda:CreateEventSourceMapping + resource: "*" target: kind: aws_role selector: @@ -103,38 +112,46 @@ scope: same_account aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" 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. + - 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 + - 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. + 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/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: + 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. + 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:aws:dynamodb:*:{target.account}:table/*" - - action: dynamodb:PutItem - resource: "arn:aws:dynamodb:*:{target.account}:table/*" + - action: iam:PassRole + resource: "{target.arn}" + - action: lambda:CreateFunction + resource: "*" + - action: lambda:CreateEventSourceMapping + resource: "*" + - action: dynamodb:CreateTable + resource: "arn:aws:dynamodb:*:{target.account}:table/*" + - action: dynamodb:PutItem + resource: "arn:aws:dynamodb:*:{target.account}:table/*" target: kind: aws_role selector: @@ -143,31 +160,37 @@ scope: same_account aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" 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. + - 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 + - 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. + 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. + - 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: + 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. + 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}" + - action: lambda:UpdateFunctionCode + resource: "{target.resource_arn}" target: kind: aws_role selector: @@ -176,71 +199,43 @@ scope: same_account aggregate_as: "Execution roles of Lambda functions updatable in {account}" conditions: - - id: function_invocation - description: The modified function must run, either via the source's lambda:InvokeFunction or an existing trigger (event source, schedule, API, resource policy). + - id: function_invocation + description: The modified function must run, either via the source's lambda:InvokeFunction or an existing trigger + (event source, schedule, API, resource policy). blockers: - - lambda_code_signing_enforced - - scp_or_boundary_deny + - lambda_code_signing_enforced + - scp_or_boundary_deny confidence: derived 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: Reaches exactly the execution roles of functions within the Resource of UpdateFunctionCode, not every Lambda-trusting role. - -- id: aws-lambda-updatefunctionconfiguration - provider: aws - service: lambda - title: Change environment variables or layers of an existing Lambda to execute code - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaupdatefunctionconfiguration - source_revision: 171e422299 - summary: The source can obtain the privileges of the execution role of existing Lambda functions whose configuration it can update. - requires: - all_of: - - action: lambda:UpdateFunctionConfiguration - 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 reconfigurable in {account}" - conditions: - - id: runtime_supports_env_injection - description: Environment-variable code execution depends on the runtime (interpreter options, or AWS_LAMBDA_EXEC_WRAPPER pointing at a wrapper staged in a layer attached in the same update, which works on every managed runtime); the layer variant requires a layer the source can publish (lambda:PublishLayerVersion) or a readable existing layer. - - id: function_invocation - description: The function must run after the change (own InvokeFunction permission or existing trigger). - blockers: - - lambda_code_signing_enforced - - scp_or_boundary_deny - confidence: conditional - severity: high - mitigation: Restrict lambda:UpdateFunctionConfiguration to deployment principals and enforce code signing (which also covers layers). + 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-envvars.html - notes: Code signing validates layers as well as function code; environment-variable injection is not prevented by code signing, so lambda_code_signing_enforced only blocks the layer variant. + - https://docs.aws.amazon.com/lambda/latest/dg/configuration-codesigning.html + notes: Reaches exactly the execution roles of functions within the Resource of UpdateFunctionCode, not every + Lambda-trusting role. - 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: + 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. + 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}" + - action: lambda:UpdateFunctionCode + resource: "{target.resource_arn}" any_of: - - - action: lambda:DeleteFunctionCodeSigningConfig - resource: "{target.resource_arn}" - - - action: lambda:CreateCodeSigningConfig - resource: "*" - - action: lambda:PutFunctionCodeSigningConfig - resource: "{target.resource_arn}" - - - action: lambda:PutFunctionCodeSigningConfig - resource: "{target.resource_arn}" + - - action: lambda:DeleteFunctionCodeSigningConfig + resource: "{target.resource_arn}" + - - action: lambda:CreateCodeSigningConfig + resource: "*" + - action: lambda:PutFunctionCodeSigningConfig + resource: "{target.resource_arn}" + - - action: lambda:PutFunctionCodeSigningConfig + resource: "{target.resource_arn}" target: kind: aws_role selector: @@ -249,44 +244,50 @@ scope: same_account aggregate_as: "Execution roles of code-signed Lambda functions in {account}" conditions: - - id: warn_config_available - description: The PutFunctionCodeSigningConfig-only alternative requires an existing code-signing configuration with UntrustedArtifactOnDeployment set to Warn; otherwise the source must also create such a configuration. - - 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. + - id: warn_config_available + description: The PutFunctionCodeSigningConfig-only alternative requires an existing code-signing configuration with + UntrustedArtifactOnDeployment set to Warn; otherwise the source must also create such a configuration. + - 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 + - scp_or_boundary_deny confidence: derived severity: critical - mitigation: Deny lambda:DeleteFunctionCodeSigningConfig, lambda:PutFunctionCodeSigningConfig and lambda:CreateCodeSigningConfig to non-admins, and enforce code signing via SCP with lambda:CodeSigningConfigArns. + 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 - notes: This entry is the code-signing-enforced counterpart of aws-lambda-updatefunctioncode; for functions without code signing that entry already applies. + - https://docs.aws.amazon.com/lambda/latest/dg/configuration-codesigning.html + notes: This entry is the code-signing-enforced counterpart of aws-lambda-updatefunctioncode; for functions without + code signing that entry already applies. - 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: + 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. + 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: "*" + - 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: @@ -295,36 +296,41 @@ 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. + - 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 + - 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. + 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. + - 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 an existing Lambda function's execution role to a passable 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: + 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 obtain the privileges of passable roles trusting lambda.amazonaws.com by changing the execution role of an existing function it can reconfigure and invoke. + summary: The source can obtain the privileges of passable roles trusting lambda.amazonaws.com by changing the + execution role of an existing function it can reconfigure and invoke. requires: all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: lambda:UpdateFunctionConfiguration - resource: "*" - - action: lambda:InvokeFunction - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: lambda:UpdateFunctionConfiguration + resource: "*" + - action: lambda:InvokeFunction + resource: "*" target: kind: aws_role selector: @@ -333,37 +339,43 @@ scope: same_account aggregate_as: "Roles trusting lambda.amazonaws.com passable in {account}" conditions: - - id: same_function - description: lambda:UpdateFunctionConfiguration and lambda:InvokeFunction must cover the same existing function. - - id: code_uses_role - description: The new role's privileges are only exercised by the function's code; the gain needs existing code that performs the desired actions, environment/wrapper injection under the same UpdateFunctionConfiguration, or a separate code update. - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict which roles can be passed. + - id: same_function + description: lambda:UpdateFunctionConfiguration and lambda:InvokeFunction must cover the same existing function. + - id: code_uses_role + description: The new role's privileges are only exercised by the function's code; the gain needs existing code that + performs the desired actions, environment/wrapper injection under the same UpdateFunctionConfiguration, or a + separate code update. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict which roles can be passed. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Restrict iam:PassRole on Lambda execution roles with iam:PassedToService and exact role ARNs, and restrict lambda:UpdateFunctionConfiguration to deployment principals. + mitigation: Restrict iam:PassRole on Lambda execution roles with iam:PassedToService and exact role ARNs, and restrict + lambda:UpdateFunctionConfiguration 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: Differs from aws-lambda-updatefunctionconfiguration, which keeps the function's current role; here the reachable roles are any passable Lambda-trusting role, not only roles already attached to functions. + - 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: Differs from aws-lambda-updatefunctionconfiguration, which keeps the function's current role; here the + reachable roles are any passable Lambda-trusting role, not only roles already attached to functions. - 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: + 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. + 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}" - - action: lambda:AddPermission - resource: "{target.resource_arn}" - - action: lambda:RemovePermission - resource: "{target.resource_arn}" + - action: lambda:PutResourcePolicy + resource: "{target.resource_arn}" + - action: lambda:AddPermission + resource: "{target.resource_arn}" + - action: lambda:RemovePermission + resource: "{target.resource_arn}" target: kind: aws_role selector: @@ -372,31 +384,38 @@ scope: same_account aggregate_as: "Execution roles of Lambda functions whose policy is writable in {account}" conditions: - - id: function_invocation - description: The modified function must run, either through an invoke permission the source also grants itself or an existing trigger. - - id: no_identity_deny - description: A resource-policy grant to a same-account principal is effective unless an identity-policy, boundary or SCP deny applies. + - id: function_invocation + description: The modified function must run, either through an invoke permission the source also grants itself or an + existing trigger. + - id: no_identity_deny + description: A resource-policy grant to a same-account principal is effective unless an identity-policy, boundary or + SCP deny applies. blockers: - - lambda_code_signing_enforced - - scp_or_boundary_deny + - 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. + 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. + - 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-microvm-createmicrovmshellauthtoken provider: aws service: lambda title: Open a shell into a running Lambda MicroVM - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdacreatemicrovmshellauthtoken--shell-into-an-existing-lambda-microvm + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdacreatemicrovmshellauthtoken--shell-into-an-existing-lambda-microvm source_revision: 171e422299 - summary: The source can obtain the privileges of the execution role of running Lambda MicroVMs launched from an image on which it can create shell tokens. + summary: The source can obtain the privileges of the execution role of running Lambda MicroVMs launched from an image + on which it can create shell tokens. requires: all_of: - - action: lambda:CreateMicrovmShellAuthToken - resource: "{target.resource_arn}" + - action: lambda:CreateMicrovmShellAuthToken + resource: "{target.resource_arn}" target: kind: aws_role selector: @@ -405,37 +424,42 @@ scope: same_account aggregate_as: "Execution roles of running Lambda MicroVMs in {account}" conditions: - - id: shell_ingress_running - description: A MicroVM from the covered image must be running and must have been launched with the SHELL_INGRESS network connector; connectors cannot be added to a running MicroVM. - - id: execution_role_attached - description: Escalation only applies when the MicroVM was launched with an execution role. + - id: shell_ingress_running + description: A MicroVM from the covered image must be running and must have been launched with the SHELL_INGRESS + network connector; connectors cannot be added to a running MicroVM. + - id: execution_role_attached + description: Escalation only applies when the MicroVM was launched with an execution role. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Grant lambda:CreateMicrovmShellAuthToken only to break-glass operators on exact image ARNs (optionally narrowed with aws:ResourceTag), and launch production MicroVMs without the SHELL_INGRESS connector. + mitigation: Grant lambda:CreateMicrovmShellAuthToken only to break-glass operators on exact image ARNs (optionally + narrowed with aws:ResourceTag), and launch production MicroVMs without the SHELL_INGRESS connector. references: - - https://docs.aws.amazon.com/lambda/latest/dg/microvms-security.html - - https://docs.aws.amazon.com/lambda/latest/microvm-api/API_CreateMicrovmShellAuthToken.html - notes: IAM authorizes the action on the microvm-image ARN, so one grant covers every current and future runtime from that image. MicroVM inventories are not collected; via_resource_type lambda_microvm resolves as unknown. + - https://docs.aws.amazon.com/lambda/latest/dg/microvms-security.html + - https://docs.aws.amazon.com/lambda/latest/microvm-api/API_CreateMicrovmShellAuthToken.html + notes: IAM authorizes the action on the microvm-image ARN, so one grant covers every current and future runtime from + that image. MicroVM inventories are not collected; via_resource_type lambda_microvm resolves as unknown. - 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: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#iampassrole-lambdacreatefunction-lambdacreatefunctionurlconfig-lambdainvokefunctionurl source_revision: 171e422299 - summary: The source can obtain the privileges of passable roles trusting lambda.amazonaws.com by creating a function with that execution role, adding a Function URL to it and invoking the URL instead of calling InvokeFunction. + summary: The source can obtain the privileges of passable roles trusting lambda.amazonaws.com by creating a function + with that execution role, adding a Function URL to it and invoking the URL instead of calling InvokeFunction. requires: all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: lambda:CreateFunction - resource: "*" - - action: lambda:CreateFunctionUrlConfig - resource: "*" - - action: lambda:InvokeFunctionUrl - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: lambda:CreateFunction + resource: "*" + - action: lambda:CreateFunctionUrlConfig + resource: "*" + - action: lambda:InvokeFunctionUrl + resource: "*" target: kind: aws_role selector: @@ -444,20 +468,25 @@ scope: same_account aggregate_as: "Roles trusting lambda.amazonaws.com in {account}" conditions: - - id: url_auth_type - description: With AuthType AWS_IAM the same-account caller's identity-based lambda:InvokeFunctionUrl allow is enough; AuthType NONE additionally needs a function resource policy allowing public invocation (lambda:AddPermission, covered by aws-lambda-passrole-createfunction-addpermission). - - id: invoke_permission_pairing - description: Newer Lambda authorization may also require lambda:InvokeFunction for Function URL invocation; where it does, the source effectively also matches aws-lambda-passrole-createfunction-invokefunction. - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict this. + - id: url_auth_type + description: With AuthType AWS_IAM the same-account caller's identity-based lambda:InvokeFunctionUrl allow is + enough; AuthType NONE additionally needs a function resource policy allowing public invocation + (lambda:AddPermission, covered by aws-lambda-passrole-createfunction-addpermission). + - id: invoke_permission_pairing + description: Newer Lambda authorization may also require lambda:InvokeFunction for Function URL invocation; where it + does, the source effectively also matches aws-lambda-passrole-createfunction-invokefunction. + - id: passrole_condition_key + description: iam:PassedToService conditions may restrict this. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: critical - mitigation: Restrict iam:PassRole on Lambda execution roles and lambda:CreateFunctionUrlConfig to deployment principals. + 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: HackTricks marks this combination as untested; the edge is conditional on the Function URL authorization behaviour described in the AWS documentation. + - https://docs.aws.amazon.com/lambda/latest/dg/urls-auth.html + notes: HackTricks marks this combination as untested; the edge is conditional on the Function URL authorization + behaviour described in the AWS documentation. - id: aws-lambda-microvm-passrole-runmicrovm-shell provider: aws @@ -465,15 +494,17 @@ title: Launch a Lambda MicroVM with a passed execution role and open a shell into it source: src/pentesting-cloud/aws-security/aws-services/aws-lambda-enum.md#lambda-microvms source_revision: 6fb9ac51fd - 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. + 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}" - - action: lambda:RunMicrovm - resource: "*" - - action: lambda:CreateMicrovmShellAuthToken - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: lambda:RunMicrovm + resource: "*" + - action: lambda:CreateMicrovmShellAuthToken + resource: "*" target: kind: aws_role selector: @@ -483,21 +514,261 @@ aggregate_as: "Roles passable as Lambda MicroVM execution roles 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 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. + - 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 + - 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. + 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: The enum page documents that RunMicrovm attaches an optional execution role whose credentials the guest receives through IMDSv2; the shell-token half follows the existing aws-lambda-microvm-createmicrovmshellauthtoken entry. The execution-role trust principal is assumed to be lambda.amazonaws.com, as in the existing MicroVM entry; verify against the MicroVM execution-role documentation. Resources are "*" because the image may be AWS-managed or customer-owned. + - 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: The enum page documents that RunMicrovm attaches an optional execution role whose credentials the guest + receives through IMDSv2; the shell-token half follows the existing aws-lambda-microvm-createmicrovmshellauthtoken + entry. The execution-role trust principal is assumed to be lambda.amazonaws.com, as in the existing MicroVM entry; + verify against the MicroVM execution-role documentation. Resources are "*" because the image may be AWS-managed or + customer-owned. +- id: aws-lambda-updatefunctionconfiguration + provider: aws + service: lambda + title: Change environment variables or layers of an existing Lambda to execute code + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaupdatefunctionconfiguration + source_revision: 171e422299 + summary: The source can obtain the privileges of the execution role of existing Lambda functions whose configuration + it can update. + requires: + all_of: + - action: lambda:UpdateFunctionConfiguration + 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 reconfigurable in {account} + conditions: + - id: runtime_supports_env_injection + description: Environment-variable code execution depends on the runtime (interpreter options, or + AWS_LAMBDA_EXEC_WRAPPER pointing at a wrapper staged in a layer attached in the same update, which works on every + managed runtime); the layer variant requires a layer the source can publish (lambda:PublishLayerVersion) or a + readable existing layer. + - id: function_invocation + description: The function must run after the change (own InvokeFunction permission or existing trigger). + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict lambda:UpdateFunctionConfiguration to deployment principals and enforce code signing (which also + covers layers). + references: + - https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html + notes: Environment-variable and wrapper injection bypass Lambda code signing; adding a layer still requires a + compatible, readable and signed layer when signing is enforced. +- id: aws-s05-06-lambda-addpermission + provider: aws + service: lambda + title: '`lambda:AddPermission`' + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaaddpermission + source_revision: 0b36331 + summary: 'Conditional gain: privileged handler invocation.' + requires: + all_of: + - action: lambda:AddPermission + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-06-lambda-addpermission + scope: same_account + conditions: + - id: exact_verified_prerequisites + description: Existing handler accepts controlled input and performs privileged action. + - 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 listed action to approved principals and exact resources. + references: [] + notes: Draft only. Missing exact evidence remains UNKNOWN; replace placeholder with the typed selector or collector + fact described alongside this draft. Required collector evidence is absent from current snapshots; missing evidence + remains UNKNOWN/unresolved. +- id: aws-s05-07-expose-a-pre-existing-authtype-none-function-url + provider: aws + service: lambda + title: Expose a pre-existing `AuthType=NONE` Function URL + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#expose-a-pre-existing-authtypenone-function-url + source_revision: 0b36331 + summary: 'Conditional gain: unauthenticated privileged handler access.' + requires: + all_of: + - action: lambda:AddPermission + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-07-expose-a-pre-existing-authtype-none-function-url + scope: same_account + conditions: + - id: exact_verified_prerequisites + description: Known existing NONE Function URL; add public InvokeFunctionUrl and InvokeFunction grants; handler is + security sensitive. + - 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 listed action to approved principals and exact resources. + references: [] + notes: Draft only. Missing exact evidence remains UNKNOWN; replace placeholder with the typed selector or collector + fact described alongside this draft. Required collector evidence is absent from current snapshots; missing evidence + remains UNKNOWN/unresolved. +- id: aws-s05-08-lambda-addlayerversionpermission + provider: aws + service: lambda + title: '`lambda:AddLayerVersionPermission`' + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdaaddlayerversionpermission + source_revision: 0b36331 + summary: 'Conditional gain: embedded credential.' + requires: + all_of: + - action: lambda:AddLayerVersionPermission + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-08-lambda-addlayerversionpermission + scope: same_account + conditions: + - id: exact_verified_prerequisites + description: Layer contains embedded credential; caller can obtain the newly granted GetLayerVersion response. + - 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 listed action to approved principals and exact resources. + references: [] + notes: Draft only. Missing exact evidence remains UNKNOWN; replace placeholder with the typed selector or collector + fact described alongside this draft. Required collector evidence is absent from current snapshots; missing evidence + remains UNKNOWN/unresolved. +- id: aws-s05-10-lambda-getfunction-download-a-function-deployment-packa + provider: aws + service: lambda + title: '`lambda:GetFunction` — Download a function deployment package' + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunction--download-a-function-deployment-package + source_revision: 0b36331 + summary: 'Conditional gain: embedded credential.' + requires: + all_of: + - action: lambda:GetFunction + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-10-lambda-getfunction-download-a-function-deployment-packa + scope: same_account + conditions: + - id: exact_verified_prerequisites + description: ZIP package embeds credential; GetFunction returns presigned archive URL. + - 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 listed action to approved principals and exact resources. + references: [] + notes: Draft only. Missing exact evidence remains UNKNOWN; replace placeholder with the typed selector or collector + fact described alongside this draft. Required collector evidence is absent from current snapshots; missing evidence + remains UNKNOWN/unresolved. +- id: aws-s05-11-lambda-getfunctionconfiguration-read-environment-variab + provider: aws + service: lambda + title: '`lambda:GetFunctionConfiguration` — Read environment variables' + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunctionconfiguration--read-environment-variables + source_revision: 0b36331 + summary: 'Conditional gain: plaintext credential.' + requires: + all_of: + - action: lambda:GetFunctionConfiguration + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-11-lambda-getfunctionconfiguration-read-environment-variab + scope: same_account + conditions: + - id: exact_verified_prerequisites + description: Environment contains credential; customer KMS key may additionally require kms:Decrypt. + - 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 listed action to approved principals and exact resources. + references: [] + notes: Draft only. Missing exact evidence remains UNKNOWN; replace placeholder with the typed selector or collector + fact described alongside this draft. Required collector evidence is absent from current snapshots; missing evidence + remains UNKNOWN/unresolved. +- id: aws-s05-12-lambda-getlayerversion-download-layer-code + provider: aws + service: lambda + title: '`lambda:GetLayerVersion` — Download layer code' + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetlayerversion--download-layer-code + source_revision: 0b36331 + summary: 'Conditional gain: embedded credential.' + requires: + all_of: + - action: lambda:GetLayerVersion + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-12-lambda-getlayerversion-download-layer-code + scope: same_account + conditions: + - id: exact_verified_prerequisites + description: Layer code contains credential. + - 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 listed action to approved principals and exact resources. + references: [] + notes: Draft only. Missing exact evidence remains UNKNOWN; replace placeholder with the typed selector or collector + fact described alongside this draft. Required collector evidence is absent from current snapshots; missing evidence + remains UNKNOWN/unresolved. diff --git a/src/privilege-escalation-paths/aws/migrationhub.yaml b/src/privilege-escalation-paths/aws/migrationhub.yaml index 2827f39ebc..ba31303276 100644 --- a/src/privilege-escalation-paths/aws/migrationhub.yaml +++ b/src/privilege-escalation-paths/aws/migrationhub.yaml @@ -5,19 +5,21 @@ 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: + 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 can obtain the privileges of any passable role trusting migrationhub.amazonaws.com through an automation unit whose runtime target it controls. + summary: The source can obtain the privileges of any passable role trusting migrationhub.amazonaws.com through an + automation unit whose runtime target it controls. requires: all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: mgh:CreateAutomationUnit - resource: "*" - - action: mgh:AssociateAutomationUnitRole - resource: "*" - - action: mgh:CreateAutomationRun - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: mgh:CreateAutomationUnit + resource: "*" + - action: mgh:AssociateAutomationUnitRole + resource: "*" + - action: mgh:CreateAutomationRun + resource: "*" target: kind: aws_role selector: @@ -26,68 +28,70 @@ scope: same_account aggregate_as: "Roles trusting migrationhub.amazonaws.com passable in {account}" 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. + - 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 + - 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. + 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 any action the service role allows. + - 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 any action the + service role allows. - 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: + 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: The source can run commands on SSM-managed EC2 instances through the Orchestrator - service-linked role and obtain their instance-profile roles. + summary: The source can run commands on SSM-managed EC2 instances through the Orchestrator service-linked role and + obtain their instance-profile roles. requires: any_of: - - action: migrationhub-orchestrator:CreateWorkflowStep - resource: arn:aws:migrationhub-orchestrator:*:{source.account}:workflow/* + resource: '*' bind: workflow - action: migrationhub-orchestrator:StartWorkflow - resource: arn:aws:migrationhub-orchestrator:*:{source.account}:workflow/* + resource: '*' bind: workflow - - action: migrationhub-orchestrator:UpdateWorkflowStep - resource: arn:aws:migrationhub-orchestrator:*:{source.account}:workflow/* + resource: '*' bind: workflow - action: migrationhub-orchestrator:RetryWorkflowStep - resource: arn:aws:migrationhub-orchestrator:*:{source.account}:workflow/* + resource: '*' bind: workflow target: - kind: aws_role + kind: aws_verified_authority selector: - has_instance_profile: true - via_resource_type: ec2_instance + aws_challenge_fact: aws-migrationhub-orchestrator-workflow-step scope: same_account - aggregate_as: Instance-profile roles of SSM-managed instances in {account} - outcome: workload_execution conditions: - id: script_in_prefixed_bucket - description: The script must be in a migrationhub-orchestrator-* bucket (s3:PutObject - there, or an existing usable script). + 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. + 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. + - 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: critical - mitigation: Restrict workflow-step create/update/start/retry actions to migration - administrators and restrict writes to migrationhub-orchestrator-* buckets. + 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 target is an instance-profile role on a selected SSM-managed - instance; actual reach depends on a usable script and workflow state. + notes: Requires aws_mho_step_targets evidence joining exact workflow, custom step, usable S3 script, online managed + instance and instance-profile role. Missing evidence remains UNKNOWN. Required collector evidence is absent from + current snapshots; missing evidence remains UNKNOWN/unresolved. diff --git a/src/privilege-escalation-paths/aws/mldataaccess.yaml b/src/privilege-escalation-paths/aws/mldataaccess.yaml index 3d8ab2f5d1..1394138942 100644 --- a/src/privilege-escalation-paths/aws/mldataaccess.yaml +++ b/src/privilege-escalation-paths/aws/mldataaccess.yaml @@ -6,15 +6,17 @@ provider: aws service: pcs title: Create a Parallel Computing Service (PCS) compute node group with a passed instance profile - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ml-dataaccess-passrole-privesc/README.md#affected-actions-non-exhaustive + 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 EC2 instance-profile roles accepted by PCS by launching compute nodes with them. + summary: The source can obtain the privileges of passable EC2 instance-profile roles accepted by PCS by launching + compute nodes with them. requires: all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: pcs:CreateComputeNodeGroup - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: pcs:CreateComputeNodeGroup + resource: "*" target: kind: aws_role selector: @@ -25,76 +27,47 @@ scope: same_account aggregate_as: "PCS-eligible instance-profile roles passable in {account}" conditions: - - id: existing_cluster - description: A PCS cluster must exist within the CreateComputeNodeGroup Resource scope. - - id: code_execution_on_node - description: The source needs a way to run code on the nodes, such as a launch template with user data it controls or job submission to the cluster. - - id: ec2_dependent_actions - description: Node group creation also needs EC2 launch-template, instance and network permissions on the referenced resources. - blockers: - - scp_or_boundary_deny - confidence: conditional - severity: high - mitigation: Restrict iam:PassRole on PCS instance profiles, restrict pcs:CreateComputeNodeGroup, and keep node roles least-privileged. - references: - - https://docs.aws.amazon.com/pcs/latest/userguide/security-instance-profiles.html - notes: PCS requires the instance profile name to start with AWSPCS or its path to contain /aws-pcs/; both forms are matched against the role's instance profiles (iam:ListInstanceProfilesForRole), and roles whose instance profiles were not collected are unresolved placeholders. - -- 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}" - - 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}" - 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. + - id: existing_cluster + description: A PCS cluster must exist within the CreateComputeNodeGroup Resource scope. + - id: code_execution_on_node + description: The source needs a way to run code on the nodes, such as a launch template with user data it controls + or job submission to the cluster. + - id: ec2_dependent_actions + description: Node group creation also needs EC2 launch-template, instance and network permissions on the referenced + resources. blockers: - - scp_or_boundary_deny + - 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. + mitigation: Restrict iam:PassRole on PCS instance profiles, restrict pcs:CreateComputeNodeGroup, and keep node 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. + - https://docs.aws.amazon.com/pcs/latest/userguide/security-instance-profiles.html + notes: PCS requires the instance profile name to start with AWSPCS or its path to contain /aws-pcs/; both forms are + matched against the role's instance profiles (iam:ListInstanceProfilesForRole), and roles whose instance profiles + were not collected are unresolved placeholders. - 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: + 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. + 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: any_of: - - - action: iam:PassRole - resource: "{target.arn}" - - action: kafkaconnect:CreateConnector - resource: "*" - - action: kafkaconnect:CreateCustomPlugin - resource: "*" - - - action: iam:PassRole - resource: "{target.arn}" - - action: kafkaconnect:CreateConnector - resource: "*" + - - action: iam:PassRole + resource: "{target.arn}" + - action: kafkaconnect:CreateConnector + resource: "*" + - action: kafkaconnect:CreateCustomPlugin + resource: "*" + - - action: iam:PassRole + resource: "{target.arn}" + - action: kafkaconnect:CreateConnector + resource: "*" target: kind: aws_role selector: @@ -104,39 +77,51 @@ aggregate_as: "Roles trusting kafkaconnect.amazonaws.com passable in {account}" outcome: workload_execution conditions: - - id: controlled_plugin_code - description: Without kafkaconnect:CreateCustomPlugin, an existing custom plugin whose code the source controls (for example a writable plugin object in S3) is required; AWS-provided connectors alone do not run arbitrary 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. + - id: controlled_plugin_code + description: Without kafkaconnect:CreateCustomPlugin, an existing custom plugin whose code the source controls (for + example a writable plugin object in S3) is required; AWS-provided connectors alone do not run arbitrary 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 + - 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. + 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, so arbitrary plugin code can act with that role. The second any_of branch covers reuse of an existing attacker-influenced plugin and is gated by the controlled_plugin_code condition. + - 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, so arbitrary plugin code can act with that role. + The second any_of branch covers reuse of an existing attacker-influenced plugin and is gated by the + controlled_plugin_code condition. - id: aws-pcs-getcluster-slurm-secret-node-roles provider: aws service: pcs title: Read a PCS cluster's Slurm authentication or REST JWT signing secret and run jobs on its compute nodes - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-pcs-post-exploitation/README.md#pcsgetcluster-secretsmanagergetsecretvalue--steal-the-slurm-scheduler-authentication-key + source: + src/pentesting-cloud/aws-security/aws-post-exploitation/aws-pcs-post-exploitation/README.md#pcsgetcluster-secretsmanagergetsecretvalue--steal-the-slurm-scheduler-authentication-key source_revision: 6fb9ac51fd - summary: The source can obtain the privileges of the instance-profile roles of PCS compute node groups by stealing the cluster's PCS-managed Slurm shared key (or Slurm REST JWT signing key) and submitting scheduler work as a forged cluster user. + summary: The source can obtain the privileges of the instance-profile roles of PCS compute node groups by stealing the + cluster's PCS-managed Slurm shared key (or Slurm REST JWT signing key) and submitting scheduler work as a forged + cluster user. requires: all_of: - - action: pcs:GetCluster - resource: "arn:aws:pcs:*:{target.account}:cluster/*" - - action: secretsmanager:GetSecretValue - resource: "arn:aws:secretsmanager:*:{target.account}:secret:pcs!*" + - action: pcs:GetCluster + resource: "arn:aws:pcs:*:{target.account}:cluster/*" + - action: secretsmanager:GetSecretValue + resource: "arn:aws:secretsmanager:*:{target.account}:secret:pcs!*" target: kind: aws_role selector: @@ -147,17 +132,26 @@ aggregate_as: "PCS compute node instance-profile roles in {account}" outcome: workload_execution conditions: - - id: scheduler_reachability - description: The source needs network reachability to the cluster's private Slurm scheduler endpoint (or, for the JWT variant, to the private Slurm REST endpoint, which must be enabled in STANDARD mode) and compatible Slurm client tooling. - - id: kms_decrypt - description: When the PCS secret is protected by a customer managed KMS key, the source also needs kms:Decrypt on that key and the key policy must allow it. - - id: node_group_exists - description: The cluster must have compute node groups (with a queue) that accept jobs; the reached roles are those of the node groups' instance profiles. + - id: scheduler_reachability + description: The source needs network reachability to the cluster's private Slurm scheduler endpoint (or, for the + JWT variant, to the private Slurm REST endpoint, which must be enabled in STANDARD mode) and compatible Slurm + client tooling. + - id: kms_decrypt + description: When the PCS secret is protected by a customer managed KMS key, the source also needs kms:Decrypt on + that key and the key policy must allow it. + - id: node_group_exists + description: The cluster must have compute node groups (with a queue) that accept jobs; the reached roles are those + of the node groups' instance profiles. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Restrict secretsmanager:GetSecretValue on pcs!-prefixed secrets to cluster administrators, restrict pcs:GetCluster, isolate scheduler and REST endpoints at the network layer, and keep PCS node roles least-privileged. + mitigation: Restrict secretsmanager:GetSecretValue on pcs!-prefixed secrets to cluster administrators, restrict + pcs:GetCluster, isolate scheduler and REST endpoints at the network layer, and keep PCS node roles least-privileged. references: - - https://docs.aws.amazon.com/pcs/latest/userguide/slurm-rest-api-authenticate.html - notes: Covers both page sections (Slurm shared-key theft and Slurm REST JWT forging, anchor pcsgetcluster-secretsmanagergetsecretvalue--forge-slurm-rest-jwts); both read a PCS-managed secret whose ARN GetCluster discloses. The secret pattern pcs!* is an account-level approximation because no cluster-to-secret placeholder exists; the role set approximates node-group roles by the PCS instance-profile naming rule, as in aws-pcs-passrole-createcomputenodegroup. + - https://docs.aws.amazon.com/pcs/latest/userguide/slurm-rest-api-authenticate.html + notes: Covers both page sections (Slurm shared-key theft and Slurm REST JWT forging, anchor + pcsgetcluster-secretsmanagergetsecretvalue--forge-slurm-rest-jwts); both read a PCS-managed secret whose ARN + GetCluster discloses. The secret pattern pcs!* is an account-level approximation because no cluster-to-secret + placeholder exists; the role set approximates node-group roles by the PCS instance-profile naming rule, as in + aws-pcs-passrole-createcomputenodegroup. diff --git a/src/privilege-escalation-paths/aws/msk.yaml b/src/privilege-escalation-paths/aws/msk.yaml new file mode 100644 index 0000000000..0e2ff51fae --- /dev/null +++ b/src/privilege-escalation-paths/aws/msk.yaml @@ -0,0 +1,32 @@ +- id: aws-s05-04-read-public-msk-sasl-scram-secret + provider: aws + service: msk + title: Read public MSK SASL/SCRAM secret + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-msk-privesc/README.md#kafkaupdatesecurity-to-expose-private-topics-without-credentials + source_revision: 0b36331 + summary: 'Conditional gain: broker login credential.' + requires: + all_of: + - action: secretsmanager:GetSecretValue + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-04-read-public-msk-sasl-scram-secret + scope: same_account + conditions: + - id: exact_verified_prerequisites + description: Associated SCRAM secret known; network controls and Kafka ACLs allow use. + - 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 listed action to approved principals and exact resources. + references: [] + notes: Draft only. Missing exact evidence remains UNKNOWN; replace placeholder with the typed selector or collector + fact described alongside this draft. Required collector evidence is absent from current snapshots; missing evidence + remains UNKNOWN/unresolved. diff --git a/src/privilege-escalation-paths/aws/organizations.yaml b/src/privilege-escalation-paths/aws/organizations.yaml index 3160cb1633..72a5fd1825 100644 --- a/src/privilege-escalation-paths/aws/organizations.yaml +++ b/src/privilege-escalation-paths/aws/organizations.yaml @@ -5,10 +5,11 @@ provider: aws service: organizations title: Assume the organization access role in member accounts from the management account - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-organizations-prinvesc/README.md#from-management-account-to-children-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 the cross-account admin role (OrganizationAccountAccessRole - by default) in member accounts that trust the management account. + summary: A management-account principal can obtain the privileges of the cross-account admin role + (OrganizationAccountAccessRole by default) in member accounts that trust the management account. requires: all_of: - action: sts:AssumeRole @@ -32,94 +33,110 @@ - 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. + 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: SCPs never apply to the management account but do apply to the assumed role in member accounts. Overlaps - with aws-sts-assumerole-trusted; kept so the org edge is labelled distinctly. + notes: SCPs never apply to the management account but do apply to the assumed role in member accounts. Overlaps with + aws-sts-assumerole-trusted; kept so the org edge is labelled distinctly. -- id: aws-organizations-registerdelegatedadministrator +- id: aws-organizations-createaccount-principalorgid-trust provider: aws service: organizations - title: Register an account the source controls as delegated administrator of an org-wide service - 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 + 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 make a member account it controls the delegated administrator of a service (CloudFormation StackSets, IAM root access, IAM Identity Center, ...) and then administer the other member accounts through that service. + 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:RegisterDelegatedAdministrator - resource: "arn:aws:organizations::*:account/*" - - action: organizations:EnableAWSServiceAccess - resource: "*" + - action: organizations:CreateAccount + resource: "*" + - action: sts:AssumeRole + resource: "arn:aws:iam::*:role/*" target: - kind: aws_account_admin + kind: aws_role selector: - any_principal_in_scope: true - org_member_account: true - scope: org - aggregate_as: "Member accounts administrable through a delegated-administrator service" + trust_allows_principal_org: true + scope: any + aggregate_as: "Roles trusting any principal of the organization" conditions: - - id: source_in_management_account - description: Only the management account can register delegated administrators. - - id: source_controls_delegate_account - description: The source must already control a principal in the member account it registers. - - id: service_reaches_accounts - description: The delegated service must grant control over member accounts (service-managed StackSets execution roles, sts:AssumeRoot, Identity Center assignments); delegated administrators can never target the management account. - - id: trusted_access_enabled - description: Trusted access for the service must be enabled (organizations:EnableAWSServiceAccess or the service's own enablement call). + - 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: - - target_in_other_account - - source_in_org_management_account + - source_in_org_management_account blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional - severity: critical - mitigation: Limit organizations:RegisterDelegatedAdministrator and EnableAWSServiceAccess to break-glass roles and alert on delegated-administrator changes. + 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_RegisterDelegatedAdministrator.html - - https://docs.aws.amazon.com/organizations/latest/userguide/orgs_integrate_services_list.html - - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-orgs-delegated-admin.html - notes: The management account usually already holds equivalent power through OrganizationAccountAccessRole; this edge matters when that role is absent or restricted and labels the delegation path. - -- id: aws-organizations-createaccount-principalorgid-trust + - 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. +- id: aws-organizations-registerdelegatedadministrator 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 + title: Register an account the source controls as delegated administrator of an org-wide service + 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_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 make a member account it controls the delegated administrator of a service + (CloudFormation StackSets, IAM root access, IAM Identity Center, ...) and then administer the other member accounts + through that service. requires: all_of: - - action: organizations:CreateAccount - resource: "*" - - action: sts:AssumeRole - resource: "arn:aws:iam::*:role/*" + - action: organizations:RegisterDelegatedAdministrator + resource: arn:aws:organizations::*:account/* + - action: organizations:EnableAWSServiceAccess + resource: '*' target: - kind: aws_role + kind: aws_verified_authority selector: - trust_allows_principal_org: true - scope: any - aggregate_as: "Roles trusting any principal of the organization" + aws_challenge_fact: aws-organizations-registerdelegatedadministrator + scope: org + aggregate_as: Verified delegated service authority + grants: + - service-specific delegated administration 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. + - id: source_in_management_account + description: Only the management account can register delegated administrators. + - id: source_controls_delegate_account + description: The source must already control a principal in the member account it registers. + - id: service_reaches_accounts + description: The delegated service must grant control over member accounts (service-managed StackSets execution + roles, sts:AssumeRoot, Identity Center assignments); delegated administrators can never target the management + account. + - id: trusted_access_enabled + description: Trusted access for the service must be enabled (organizations:EnableAWSServiceAccess or the service's + own enablement call). preconditions: - - source_in_org_management_account + - target_in_other_account + - source_in_org_management_account blockers: - - scp_or_boundary_deny + - 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. + severity: critical + mitigation: Limit organizations:RegisterDelegatedAdministrator and EnableAWSServiceAccess to break-glass roles and + alert on delegated-administrator changes. 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/APIReference/API_RegisterDelegatedAdministrator.html + - https://docs.aws.amazon.com/organizations/latest/userguide/orgs_integrate_services_list.html + - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/stacksets-orgs-delegated-admin.html + notes: Exact service principal, controlled delegate and service-specific privilege are required; no generic + aws_account_admin edge. diff --git a/src/privilege-escalation-paths/aws/pcaconnectorad.yaml b/src/privilege-escalation-paths/aws/pcaconnectorad.yaml index bd3a960d29..c7b3853c58 100644 --- a/src/privilege-escalation-paths/aws/pcaconnectorad.yaml +++ b/src/privilege-escalation-paths/aws/pcaconnectorad.yaml @@ -8,15 +8,17 @@ provider: aws service: pca-connector-ad title: Publish a malicious certificate template through PCA Connector for AD and enroll as a domain admin - 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--publish-a-malicious-certificate-template-esc1--esc9 source_revision: 171e422299 - summary: The source can obtain a certificate authenticating as any domain principal (ESC1-style enrollee-supplied subject) by publishing a template on a connector and granting enrollment on it to an AD group it controls. + summary: The source can obtain a certificate authenticating as any domain principal (ESC1-style enrollee-supplied + subject) by publishing a template on a connector and granting enrollment on it to an AD group it controls. requires: all_of: - - action: pca-connector-ad:CreateTemplate - resource: "arn:aws:pca-connector-ad:*:{target.account}:connector/*" - - action: pca-connector-ad:CreateTemplateGroupAccessControlEntry - resource: "arn:aws:pca-connector-ad:*:{target.account}:connector/*/template/*" + - action: pca-connector-ad:CreateTemplate + resource: "arn:aws:pca-connector-ad:*:{target.account}:connector/*" + - action: pca-connector-ad:CreateTemplateGroupAccessControlEntry + resource: "arn:aws:pca-connector-ad:*:{target.account}:connector/*/template/*" target: kind: aws_directory_domain_admin selector: @@ -24,33 +26,41 @@ scope: same_account aggregate_as: "Active Directory domains served by PCA connectors in {account}" conditions: - - id: connector_exists - description: A PCA Connector for AD must exist in the account, joined to a directory (AWS Managed Microsoft AD or AD Connector) and backed by an active private CA. - - id: domain_context - description: Enrollment happens from a domain-joined context with an AD identity in the group granted enrollment; the source needs such an identity. - - id: pkinit_or_schannel - description: Using the certificate as a domain admin needs PKINIT or Schannel authentication against the domain controllers and no strong certificate mapping enforcement that blocks enrollee-supplied subjects. + - id: connector_exists + description: A PCA Connector for AD must exist in the account, joined to a directory (AWS Managed Microsoft AD or AD + Connector) and backed by an active private CA. + - id: domain_context + description: Enrollment happens from a domain-joined context with an AD identity in the group granted enrollment; + the source needs such an identity. + - id: pkinit_or_schannel + description: Using the certificate as a domain admin needs PKINIT or Schannel authentication against the domain + controllers and no strong certificate mapping enforcement that blocks enrollee-supplied subjects. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: critical - mitigation: Restrict pca-connector-ad:CreateTemplate / UpdateTemplate / CreateTemplateGroupAccessControlEntry to PKI administrators, enforce strong certificate mapping on domain controllers, and alert on connector template changes. + mitigation: Restrict pca-connector-ad:CreateTemplate / UpdateTemplate / CreateTemplateGroupAccessControlEntry to PKI + administrators, enforce strong certificate mapping on domain controllers, and alert on connector template changes. references: - - https://docs.aws.amazon.com/service-authorization/latest/reference/list_pca-connector-ad.html - - https://docs.aws.amazon.com/privateca/latest/userguide/connector-for-ad.html - notes: CreateTemplateGroupAccessControlEntry alone only opens enrollment on an existing template and is kept as an exclusion; here it is the enrollment half of the chain. Further impact in the cloud account needs another hop (directory console-access roles, AD-federated SAML). + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_pca-connector-ad.html + - https://docs.aws.amazon.com/privateca/latest/userguide/connector-for-ad.html + notes: CreateTemplateGroupAccessControlEntry alone only opens enrollment on an existing template and is kept as an + exclusion; here it is the enrollment half of the chain. Further impact in the cloud account needs another hop + (directory console-access roles, AD-federated SAML). - id: aws-pca-connector-ad-updatetemplate provider: aws service: pca-connector-ad title: Weaken an existing PCA Connector for AD certificate template in place - 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--weaken-an-existing-legitimate-template-in-place source_revision: 171e422299 - summary: The source can obtain a certificate authenticating as any domain principal by changing an existing template it (or a group it belongs to) can already enroll in to accept an enrollee-supplied subject. + summary: The source can obtain a certificate authenticating as any domain principal by changing an existing template + it (or a group it belongs to) can already enroll in to accept an enrollee-supplied subject. requires: all_of: - - action: pca-connector-ad:UpdateTemplate - resource: "arn:aws:pca-connector-ad:*:{target.account}:connector/*/template/*" + - action: pca-connector-ad:UpdateTemplate + resource: "arn:aws:pca-connector-ad:*:{target.account}:connector/*/template/*" target: kind: aws_directory_domain_admin selector: @@ -58,18 +68,54 @@ scope: same_account aggregate_as: "Active Directory domains served by PCA connectors in {account}" conditions: - - id: connector_template_exists - description: A connector with at least one template must exist in the account. - - id: enrollment_rights - description: The source's AD identity must already be able to enroll in the template (or the source also holds CreateTemplateGroupAccessControlEntry on it). - - id: pkinit_or_schannel - description: Using the certificate as a domain admin needs PKINIT or Schannel authentication and no strong certificate mapping enforcement that blocks enrollee-supplied subjects. + - id: connector_template_exists + description: A connector with at least one template must exist in the account. + - id: enrollment_rights + description: The source's AD identity must already be able to enroll in the template (or the source also holds + CreateTemplateGroupAccessControlEntry on it). + - id: pkinit_or_schannel + description: Using the certificate as a domain admin needs PKINIT or Schannel authentication and no strong + certificate mapping enforcement that blocks enrollee-supplied subjects. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: critical - mitigation: Restrict pca-connector-ad:UpdateTemplate to PKI administrators, enforce strong certificate mapping, and alert on template updates. + mitigation: Restrict pca-connector-ad:UpdateTemplate to PKI administrators, enforce strong certificate mapping, and + alert on template updates. references: - - https://docs.aws.amazon.com/service-authorization/latest/reference/list_pca-connector-ad.html - - https://docs.aws.amazon.com/privateca/latest/userguide/connector-for-ad.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_pca-connector-ad.html + - https://docs.aws.amazon.com/privateca/latest/userguide/connector-for-ad.html notes: Editing a legitimate template also affects its normal enrollees and is easier to miss than a new template. +- id: aws-s05-83-pca-connector-ad-createtemplategroupaccesscontrolentry + provider: aws + service: pca-connector-ad + title: '`pca-connector-ad:CreateTemplateGroupAccessControlEntry` — grant enrollment to an attacker-chosen AD group' + 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 + source_revision: 0b36331 + summary: 'Conditional gain: certificate as chosen AD principal.' + requires: + all_of: + - action: pca-connector-ad:CreateTemplateGroupAccessControlEntry + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-83-pca-connector-ad-createtemplategroupaccesscontrolentry + scope: same_account + conditions: + - id: exact_verified_prerequisites + description: Existing unsafe client-auth template with enrollee-controlled identity; attacker controls AD group; + enrollment and PKINIT/Schannel available. + - 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 listed action to approved principals and exact resources. + references: [] + notes: Draft only. Missing exact evidence remains UNKNOWN; replace placeholder with the typed selector or collector + fact described alongside this draft. Required collector evidence is absent from current snapshots; missing evidence + remains UNKNOWN/unresolved. diff --git a/src/privilege-escalation-paths/aws/rds.yaml b/src/privilege-escalation-paths/aws/rds.yaml index a05fb04c8e..452c28604b 100644 --- a/src/privilege-escalation-paths/aws/rds.yaml +++ b/src/privilege-escalation-paths/aws/rds.yaml @@ -10,11 +10,12 @@ title: Reset the master password of a DB instance that has associated IAM roles source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdsmodifydbinstance source_revision: 171e422299 - summary: The source can obtain the integration-limited privileges (S3/Lambda) of IAM roles associated with a non-Aurora DB instance it can modify. + summary: The source can obtain the integration-limited privileges (S3/Lambda) of IAM roles associated with a + non-Aurora DB instance it can modify. requires: all_of: - - action: rds:ModifyDBInstance - resource: "{target.resource_arn}" + - action: rds:ModifyDBInstance + resource: "{target.resource_arn}" target: kind: aws_role selector: @@ -23,34 +24,40 @@ scope: same_account aggregate_as: "IAM roles associated with modifiable RDS instances in {account}" conditions: - - id: network_reachability - description: The source needs a network path to the database endpoint. - - id: integration_configured - description: The engine integration (e.g. aws_s3 / aws_lambda extensions, S3 load/export) must be supported and enabled for the associated role's feature. - - id: not_aurora_or_managed_password - description: Not applicable to Aurora instances (cluster-managed password) or instances whose master password is managed in Secrets Manager. + - id: network_reachability + description: The source needs a network path to the database endpoint. + - id: integration_configured + description: The engine integration (e.g. aws_s3 / aws_lambda extensions, S3 load/export) must be supported and + enabled for the associated role's feature. + - id: not_aurora_or_managed_password + description: Not applicable to Aurora instances (cluster-managed password) or instances whose master password is + managed in Secrets Manager. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: medium - mitigation: Restrict rds:ModifyDBInstance to DBAs, use Secrets Manager-managed master passwords, and keep RDS-associated roles least-privileged. + mitigation: Restrict rds:ModifyDBInstance to DBAs, use Secrets Manager-managed master passwords, and keep + RDS-associated roles least-privileged. references: - - https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_ModifyDBInstance.html - notes: HackTricks frames this as data access; the role edge is inferred from the page's "Abuse RDS Role IAM permissions" section. Pure data access belongs to exposure analysis, not this edge. + - https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_ModifyDBInstance.html + notes: HackTricks frames this as data access; the role edge is inferred from the page's "Abuse RDS Role IAM + permissions" section. Pure data access belongs to exposure analysis, not this edge. - id: aws-rds-addroletodbcluster-passrole provider: aws service: rds title: Associate a passed IAM role with an Aurora DB cluster - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdsaddroletodbcluster-iampassrole + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdsaddroletodbcluster-iampassrole source_revision: 171e422299 - summary: The source can obtain the integration-limited privileges of any passable role trusting rds.amazonaws.com through a cluster it can use. + summary: The source can obtain the integration-limited privileges of any passable role trusting rds.amazonaws.com + through a cluster it can use. requires: all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: rds:AddRoleToDBCluster - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: rds:AddRoleToDBCluster + resource: "*" target: kind: aws_role selector: @@ -59,32 +66,37 @@ scope: same_account aggregate_as: "Roles trusting rds.amazonaws.com passable in {account}" conditions: - - id: database_session - description: The source needs a database login on the cluster with SQL privileges to invoke the integration, and network reachability. - - id: engine_configuration - description: Some engines (Aurora MySQL) also require the role ARN in the cluster parameter group, needing rds:ModifyDBClusterParameterGroup. + - id: database_session + description: The source needs a database login on the cluster with SQL privileges to invoke the integration, and + network reachability. + - id: engine_configuration + description: Some engines (Aurora MySQL) also require the role ARN in the cluster parameter group, needing + rds:ModifyDBClusterParameterGroup. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: medium - mitigation: Restrict iam:PassRole with iam:PassedToService=rds.amazonaws.com to specific roles and restrict rds:AddRoleToDBCluster. + mitigation: Restrict iam:PassRole with iam:PassedToService=rds.amazonaws.com to specific roles and restrict + rds:AddRoleToDBCluster. references: - - https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_AddRoleToDBCluster.html + - https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_AddRoleToDBCluster.html notes: Covers the blue/green variant on the same page (CreateBlueGreenDeployment adds nothing to the reachable set). - id: aws-rds-addroletodbinstance-passrole provider: aws service: rds title: Associate a passed IAM role with an RDS DB instance - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdsaddroletodbinstance-iampassrole + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdsaddroletodbinstance-iampassrole source_revision: 171e422299 - summary: The source can obtain the integration-limited privileges of any passable role trusting rds.amazonaws.com through an instance it can use. + summary: The source can obtain the integration-limited privileges of any passable role trusting rds.amazonaws.com + through an instance it can use. requires: all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: rds:AddRoleToDBInstance - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: rds:AddRoleToDBInstance + resource: "*" target: kind: aws_role selector: @@ -93,36 +105,39 @@ scope: same_account aggregate_as: "Roles trusting rds.amazonaws.com passable in {account}" conditions: - - id: database_session - description: The source needs a database login with SQL privileges to invoke the integration, and network reachability. - - id: feature_supported - description: The engine must support the feature name (e.g. s3Import, Lambda); not applicable to RDS Custom. + - id: database_session + description: The source needs a database login with SQL privileges to invoke the integration, and network + reachability. + - id: feature_supported + description: The engine must support the feature name (e.g. s3Import, Lambda); not applicable to RDS Custom. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: medium mitigation: Restrict iam:PassRole with iam:PassedToService=rds.amazonaws.com and restrict rds:AddRoleToDBInstance. references: - - https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_AddRoleToDBInstance.html + - https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_AddRoleToDBInstance.html notes: "" - id: aws-rds-custom-createdbinstance-passrole provider: aws service: rds title: Create an RDS Custom instance with a passed AWSRDSCustom instance profile - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdscreatedbinstance-iampassrole-kms-key-use-permissions + source: + src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rdscreatedbinstance-iampassrole-kms-key-use-permissions source_revision: 171e422299 - summary: The source can obtain the privileges of passable EC2-trusting roles whose role and instance-profile names start with AWSRDSCustom. + summary: The source can obtain the privileges of passable EC2-trusting roles whose role and instance-profile names + start with AWSRDSCustom. requires: all_of: - - action: iam:PassRole - resource: "{target.arn}" - - action: rds:CreateDBInstance - resource: "*" - - action: kms:CreateGrant - resource: "*" - - action: kms:DescribeKey - resource: "*" + - action: iam:PassRole + resource: "{target.arn}" + - action: rds:CreateDBInstance + resource: "*" + - action: kms:CreateGrant + resource: "*" + - action: kms:DescribeKey + resource: "*" target: kind: aws_role selector: @@ -133,19 +148,26 @@ scope: same_account aggregate_as: "AWSRDSCustom* instance-profile roles passable in {account}" conditions: - - id: host_access - description: Credentials are only exposed if the source can obtain code execution or administrative access on the RDS Custom host (e.g. via SSM or the EC2 key pair). - - id: rds_custom_prerequisites - description: RDS Custom prerequisites (custom engine version, networking, customer managed symmetric KMS key usable by the source) must be met. For RDS Custom for Oracle the creator also needs s3:CreateBucket, s3:PutBucketPolicy, s3:PutBucketObjectLockConfiguration and s3:PutBucketVersioning on do-not-delete-rds-custom-* buckets, iam:SimulatePrincipalPolicy, and cloudtrail:CreateTrail and cloudtrail:StartLogging on do-not-delete-rds-custom-* trails (not modelled as requirements because they are engine-specific). + - id: host_access + description: Credentials are only exposed if the source can obtain code execution or administrative access on the + RDS Custom host (e.g. via SSM or the EC2 key pair). + - id: rds_custom_prerequisites + description: RDS Custom prerequisites (custom engine version, networking, customer managed symmetric KMS key usable + by the source) must be met. For RDS Custom for Oracle the creator also needs s3:CreateBucket, s3:PutBucketPolicy, + s3:PutBucketObjectLockConfiguration and s3:PutBucketVersioning on do-not-delete-rds-custom-* buckets, + iam:SimulatePrincipalPolicy, and cloudtrail:CreateTrail and cloudtrail:StartLogging on do-not-delete-rds-custom-* + trails (not modelled as requirements because they are engine-specific). blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict iam:PassRole on AWSRDSCustom* roles and restrict RDS Custom instance creation to DBAs. references: - - https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/custom-creating.html - - https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/custom-setup-orcl.html - notes: The RDS Custom setup guide confirms kms:CreateGrant and kms:DescribeKey on "*" for the creating principal, and the default AWSRDSCustomInstanceRole- trusts ec2.amazonaws.com. RDS Custom for Oracle reaches end of support on March 31, 2027. + - https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/custom-creating.html + - https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/custom-setup-orcl.html + notes: The RDS Custom setup guide confirms kms:CreateGrant and kms:DescribeKey on "*" for the creating principal, and + the default AWSRDSCustomInstanceRole- trusts ec2.amazonaws.com. RDS Custom for Oracle reaches end of support + on March 31, 2027. - id: aws-rds-dbconnect-iam-auth-associated-roles provider: aws @@ -153,11 +175,13 @@ title: Authenticate to an RDS instance with IAM database authentication and use its associated IAM roles source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#rds-dbconnect source_revision: 6fb9ac51fd - summary: The source can obtain the integration-limited privileges (S3/Lambda) of IAM roles associated with a DB instance by signing in as an IAM-mapped database user that may call the engine's S3 and Lambda integration functions. + summary: The source can obtain the integration-limited privileges (S3/Lambda) of IAM roles associated with a DB + instance by signing in as an IAM-mapped database user that may call the engine's S3 and Lambda integration + functions. requires: all_of: - - action: rds-db:connect - resource: "arn:aws:rds-db:*:{target.account}:dbuser:*/*" + - action: rds-db:connect + resource: "arn:aws:rds-db:*:{target.account}:dbuser:*/*" target: kind: aws_role selector: @@ -167,35 +191,45 @@ aggregate_as: "IAM roles associated with RDS instances reachable through IAM DB authentication in {account}" outcome: workload_execution conditions: - - id: iam_db_auth_enabled - description: IAM database authentication must be enabled on the instance, and an engine user mapped to IAM authentication (rds_iam grant or AWSAuthenticationPlugin) must exist that the rds-db:connect resource covers. - - id: db_user_can_use_integration - description: That database user needs SQL privileges on the engine's AWS integration features (for example aws_s3 / aws_lambda extensions or S3 load/export) bound to the associated role. - - id: network_reachability - description: The source needs a network path to the database endpoint. - - id: resource_scope_overapproximated - description: The requirement is evaluated account-wide; a policy limited to specific DbiResourceId/user pairs grants this only for those instances and users. + - id: iam_db_auth_enabled + description: IAM database authentication must be enabled on the instance, and an engine user mapped to IAM + authentication (rds_iam grant or AWSAuthenticationPlugin) must exist that the rds-db:connect resource covers. + - id: db_user_can_use_integration + description: That database user needs SQL privileges on the engine's AWS integration features (for example aws_s3 / + aws_lambda extensions or S3 load/export) bound to the associated role. + - id: network_reachability + description: The source needs a network path to the database endpoint. + - id: resource_scope_overapproximated + description: The requirement is evaluated account-wide; a policy limited to specific DbiResourceId/user pairs grants + this only for those instances and users. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: medium - mitigation: Scope rds-db:connect to exact DbiResourceId and database-user pairs, grant the engine's S3 and Lambda integration functions only to dedicated DB roles, and keep RDS-associated IAM roles least-privileged. + mitigation: Scope rds-db:connect to exact DbiResourceId and database-user pairs, grant the engine's S3 and Lambda + integration functions only to dedicated DB roles, and keep RDS-associated IAM roles least-privileged. references: - - https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.IAMPolicy.html - - https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Integrating.Authorizing.html - notes: The page frames rds-db:connect as authentication without a password into an existing IAM-mapped DB user; the role edge follows the page's "Abuse RDS Role IAM permissions" section, as in aws-rds-modifydbinstance-master-password-associated-roles. The resource uses the Redshift WithIAM account-wide over-approximation precedent because there is no per-instance dbuser placeholder. Aurora cluster-level role associations (rds_db_cluster) are not collected and are not covered. + - https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/UsingWithRDS.IAMDBAuth.IAMPolicy.html + - https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Integrating.Authorizing.html + notes: The page frames rds-db:connect as authentication without a password into an existing IAM-mapped DB user; the + role edge follows the page's "Abuse RDS Role IAM permissions" section, as in + aws-rds-modifydbinstance-master-password-associated-roles. The resource uses the Redshift WithIAM account-wide + over-approximation precedent because there is no per-instance dbuser placeholder. Aurora cluster-level role + associations (rds_db_cluster) are not collected and are not covered. - id: aws-rds-modifydbcluster-master-password-associated-roles provider: aws service: rds title: Reset the master password of an Aurora DB cluster that has associated IAM roles - 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 + 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 source_revision: 6fb9ac51fd - summary: The source can obtain the integration-limited privileges (S3 import/export, Lambda invocation, other engine integrations) of IAM roles associated with an Aurora cluster whose master password it can reset. + summary: The source can obtain the integration-limited privileges (S3 import/export, Lambda invocation, other engine + integrations) of IAM roles associated with an Aurora cluster whose master password it can reset. requires: all_of: - - action: rds:ModifyDBCluster - resource: "{target.resource_arn}" + - action: rds:ModifyDBCluster + resource: "{target.resource_arn}" target: kind: aws_role selector: @@ -205,32 +239,41 @@ aggregate_as: "IAM roles associated with modifiable Aurora clusters in {account}" outcome: workload_execution conditions: - - id: sql_path - description: The source needs a network path to the cluster endpoint, or the Data API path documented on the page (HTTP endpoint enabled via rds:ModifyDBCluster or rds:EnableHttpEndpoint, a Secrets Manager secret it can create and read, and rds-data:ExecuteStatement). - - id: integration_configured - description: The engine integration (aws_s3 / aws_lambda extensions, LOAD DATA FROM S3, SELECT INTO OUTFILE S3, invoke Lambda) must be supported and enabled for the associated role's feature; Aurora MySQL may also need the role ARN in the cluster parameter group. - - id: not_managed_password - description: Clusters whose master password is managed in Secrets Manager need the managed-secret path instead. + - id: sql_path + description: The source needs a network path to the cluster endpoint, or the Data API path documented on the page + (HTTP endpoint enabled via rds:ModifyDBCluster or rds:EnableHttpEndpoint, a Secrets Manager secret it can create + and read, and rds-data:ExecuteStatement). + - id: integration_configured + description: The engine integration (aws_s3 / aws_lambda extensions, LOAD DATA FROM S3, SELECT INTO OUTFILE S3, + invoke Lambda) must be supported and enabled for the associated role's feature; Aurora MySQL may also need the + role ARN in the cluster parameter group. + - id: not_managed_password + description: Clusters whose master password is managed in Secrets Manager need the managed-secret path instead. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: medium - mitigation: Restrict rds:ModifyDBCluster and rds:EnableHttpEndpoint to DBAs, use Secrets Manager-managed master passwords, and keep cluster-associated roles least-privileged. + mitigation: Restrict rds:ModifyDBCluster and rds:EnableHttpEndpoint to DBAs, use Secrets Manager-managed master + passwords, and keep cluster-associated roles least-privileged. references: - - https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_ModifyDBCluster.html - notes: Aurora counterpart of aws-rds-modifydbinstance-master-password-associated-roles, which explicitly excludes Aurora (cluster-managed password). rds_db_cluster is not collected, so attachment falls back to roles trusting rds.amazonaws.com with unknown confidence. + - https://docs.aws.amazon.com/AmazonRDS/latest/APIReference/API_ModifyDBCluster.html + notes: Aurora counterpart of aws-rds-modifydbinstance-master-password-associated-roles, which explicitly excludes + Aurora (cluster-managed password). rds_db_cluster is not collected, so attachment falls back to roles trusting + rds.amazonaws.com with unknown confidence. - id: aws-rds-managed-master-secret-associated-roles provider: aws service: rds title: Read an RDS-managed master password secret of a DB with associated IAM roles - 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 + 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 source_revision: 6fb9ac51fd - summary: The source can obtain the integration-limited privileges of IAM roles associated with RDS instances or Aurora clusters whose RDS-managed master secret it can read. + summary: The source can obtain the integration-limited privileges of IAM roles associated with RDS instances or Aurora + clusters whose RDS-managed master secret it can read. requires: all_of: - - action: secretsmanager:GetSecretValue - resource: "arn:aws:secretsmanager:*:{target.account}:secret:rds!*" + - action: secretsmanager:GetSecretValue + resource: "arn:aws:secretsmanager:*:{target.account}:secret:rds!*" target: kind: aws_role selector: @@ -240,17 +283,54 @@ aggregate_as: "IAM roles associated with RDS databases using managed master secrets in {account}" outcome: workload_execution conditions: - - id: managed_master_password - description: The database must use ManageMasterUserPassword (secret named rds!db-* or rds!cluster-*); the secret ARN is disclosed by DescribeDBInstances/DescribeDBClusters (MasterUserSecret). - - id: kms_decrypt - description: When the secret uses a customer managed KMS key, the source also needs kms:Decrypt and the key policy must allow it. - - id: sql_path_and_integration - description: The source needs a network path to the endpoint (or the Data API for Aurora) and the engine integration for the associated role must be enabled. + - id: managed_master_password + description: The database must use ManageMasterUserPassword (secret named rds!db-* or rds!cluster-*); the secret ARN + is disclosed by DescribeDBInstances/DescribeDBClusters (MasterUserSecret). + - id: kms_decrypt + description: When the secret uses a customer managed KMS key, the source also needs kms:Decrypt and the key policy + must allow it. + - id: sql_path_and_integration + description: The source needs a network path to the endpoint (or the Data API for Aurora) and the engine integration + for the associated role must be enabled. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: medium - mitigation: Scope secretsmanager:GetSecretValue on rds!-prefixed secrets to DBAs and break-glass roles, and keep RDS-associated roles least-privileged. + mitigation: Scope secretsmanager:GetSecretValue on rds!-prefixed secrets to DBAs and break-glass roles, and keep + RDS-associated roles least-privileged. references: - - https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-secrets-manager.html - notes: The secret resource is an account-level approximation (no database-to-secret placeholder), so a grant on one rds! secret over-reports all RDS-associated roles of the account. + - https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/rds-secrets-manager.html + notes: The secret resource is an account-level approximation (no database-to-secret placeholder), so a grant on one + rds! secret over-reports all RDS-associated roles of the account. +- id: aws-rds-dbconnect-aurora-role + provider: aws + service: rds + title: IAM DB authentication plus Aurora cluster role association + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-rds-privesc/README.md#postgresql-aurora + source_revision: 0b36331 + summary: Exercise the integration-limited IAM privileges of an Aurora cluster associated role. + requires: + all_of: + - action: rds-db:connect + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-rds-dbconnect-aurora-role + scope: same_account + conditions: + - id: condition_1 + description: Exact dbuser and active cluster role association required. Missing cluster or SQL facts yield UNKNOWN. + - id: condition_2 + description: SQL integration use and network path 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. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: medium + mitigation: Restrict rds-db:connect to authorized identities and exact resources. + references: + - https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Integrating.Authorizing.html + notes: Required collector evidence is absent from current snapshots; missing evidence remains UNKNOWN/unresolved. From a8c7fc7aabd120bab7503721b780c52d56d16f54 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Mon, 12 Oct 2026 20:35:17 +0200 Subject: [PATCH 02/17] Integrate verified AWS privesc v4 follow-up fragments Co-Authored-By: Codex --- .../aws/_excluded_a.yaml | 16 +- .../aws/_excluded_audit_6fb9.yaml | 69 +- .../aws/_excluded_b.yaml | 41 +- .../aws/_excluded_verify_a66f.yaml | 626 ++++++++++-------- .../aws/appconfig.yaml | 37 +- .../aws/appsync.yaml | 32 + .../aws/athena.yaml | 67 ++ .../aws/codeconnections.yaml | 29 + .../aws/cognito.yaml | 29 + .../aws/connect.yaml | 149 +++++ .../aws/controltower.yaml | 29 + src/privilege-escalation-paths/aws/ssm.yaml | 210 +++++- src/privilege-escalation-paths/aws/sso.yaml | 94 ++- .../aws/stepfunctions.yaml | 36 + src/privilege-escalation-paths/aws/sts.yaml | 90 ++- .../aws/synthetics.yaml | 34 + .../aws/timestream.yaml | 76 +++ .../aws/transfer.yaml | 272 ++++---- src/privilege-escalation-paths/aws/wickr.yaml | 34 + .../aws/workdocs.yaml | 34 + .../aws/workspaces.yaml | 47 +- 21 files changed, 1530 insertions(+), 521 deletions(-) create mode 100644 src/privilege-escalation-paths/aws/timestream.yaml create mode 100644 src/privilege-escalation-paths/aws/wickr.yaml create mode 100644 src/privilege-escalation-paths/aws/workdocs.yaml diff --git a/src/privilege-escalation-paths/aws/_excluded_a.yaml b/src/privilege-escalation-paths/aws/_excluded_a.yaml index b97d2399bc..280a06e7b4 100644 --- a/src/privilege-escalation-paths/aws/_excluded_a.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_a.yaml @@ -152,16 +152,16 @@ 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-cloudfront-privesc/README.md#cloudfrontupdatedistribution--cloudfrontgetdistributionconfig +- 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: - src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudfront-privesc/README.md#cloudfrontcreatefunction-cloudfrontdescribefunction-cloudfrontpublishfunction-cloudfrontgetdistributionconfig--cloudfrontupdatedistribution + reason: UpdateDistribution can reroute viewer requests to an attacker origin. Credential gain requires a visitor + to send a usable authorization header, cookie or body and an application that accepts it; traffic content is + not in inventory. +- 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 --- + reason: Edge-function injection can redirect users or capture request data. Session takeover requires a usable + session cookie/token in later browser traffic and acceptance by the application; CloudFront configuration does + not prove it. - 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 diff --git a/src/privilege-escalation-paths/aws/_excluded_audit_6fb9.yaml b/src/privilege-escalation-paths/aws/_excluded_audit_6fb9.yaml index f74c2494db..bbee89d8da 100644 --- a/src/privilege-escalation-paths/aws/_excluded_audit_6fb9.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_audit_6fb9.yaml @@ -194,18 +194,20 @@ 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-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` — mint a SCEP enrollment secret (rogue-device + certificate backdoor)' + reason: Add a SCEP device-certificate target and selector joining general-purpose connector, CA profile, relying-party + trust and challenge access. + source_revision: 0b36331 +- 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: The page documents three separate ways to obtain a GitHub, Bitbucket or GHES source token. In-build GetBuildInfo + starts with running-build code and needs no attacker CreateProject/UpdateProject/StartBuild permission; image/proxy + and GHES insecureSsl variants need project control and a build. The token is distinct from the CodeBuild role, + but source-auth configuration, actual token return or interception, validity and external scopes are uncollected + runtime/provider facts. insecureSsl is GHES-only. + source_revision: 0b36331 - 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" @@ -218,12 +220,12 @@ 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-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: AddUserPoolClientSecret returns a new M2M app-client secret; configured custom scopes can authenticate + to downstream resource servers, but not an AWS identity-pool role. An exact app-client authority needs flow, + secret-slot, scope and resource-server facts. + source_revision: 0b36331 - 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" @@ -245,3 +247,34 @@ 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. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-data-access-post-exploitation/README.md#knowledge-bases--retrieve-indexed-private-documents-without-source-storage-access + source_revision: 0b36331 + technique: bedrock:Retrieve returns indexed source text that may contain a credential + reason: Indexed text must actually contain a valid, usable credential and its holder must be identified from returned + content; neither fact is present in the configuration snapshot. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-data-access-post-exploitation/README.md#read-bedrock-plaintext-directly-from-an-s3-vectors-backing-index + source_revision: 0b36331 + technique: S3 Vectors GetVectors returns AMAZON_BEDROCK_TEXT from Bedrock index + reason: A returned vector chunk must contain a usable credential and identify its holder; index configuration + alone cannot establish that content or identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-post-exploitation/README.md#aws---bedrock-agents-memory-poisoning-indirect-prompt-injection + source_revision: 0b36331 + technique: Persistent agent-memory injection induces later privileged tool calls and exfiltration + reason: Requires poisoned memory content to be retained, replayed and obeyed by a later model/user session before + a privileged tool is called; none is determined by static agent configuration. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-bedrock-post-exploitation/README.md#aws---bedrock-agents-multi-agent-prompt-injection-chains + source_revision: 0b36331 + technique: Multi-agent prompt injection coaxes collaborator action-group misuse + reason: Requires the supervisor to forward the attacker text and a collaborator model to obey it and invoke a + privileged action group; routing and tool behavior are runtime facts. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudformation-registry-post-exploitation/README.md#read-stored-extension-configuration + source_revision: 0b36331 + technique: BatchDescribeTypeConfigurations returns literal Hook/extension credentials + reason: The stored extension configuration must contain a literal, usable credential and its holder must be identified + from the API response; dynamic references do not expose the secret and inventory metadata does not contain its + value. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudwatch-omni-post-exploitation/README.md#query-unified-logs-and-traces-through-the-default-dataset + source_revision: 0b36331 + technique: Omni SQL default Dataset query retrieves credential-bearing logs/traces + reason: The queried log or trace rows must contain a usable credential and identify its holder; telemetry content + and query results are absent from the configuration snapshot. diff --git a/src/privilege-escalation-paths/aws/_excluded_b.yaml b/src/privilege-escalation-paths/aws/_excluded_b.yaml index f37794bb4b..14bb5923ee 100644 --- a/src/privilege-escalation-paths/aws/_excluded_b.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_b.yaml @@ -172,11 +172,13 @@ 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-privilege-escalation/route53-createhostedzone-route53-changeresourcerecordsets-acm-pca-issuecertificate-acm-pca-getcer/README.md#route53createhostedzone-route53changeresourcerecordsets-acm-pcaissuecertificate-acm-pcagetcertificate-ec2describevpcs - source_revision: a53b46392c +- 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: 0b36331 technique: route53:CreateHostedZone + ChangeResourceRecordSets + acm-pca:IssueCertificate + GetCertificate - reason: Traffic interception (MitM) of in-VPC clients; no IAM principal is obtained directly. + reason: Private DNS and a trusted Private CA can intercept a vulnerable client, but a privilege edge requires + host trust-store and TLS behavior, attacker endpoint/routing control, a victim request carrying reusable credentials, + and proof of the credential target. These runtime and host facts are not established by the IAM configuration + snapshot. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-emr-privesc/README.md#elasticmapreducecreateeditor-iamlistroles-elasticmapreducelistclusters-iampassrole-elasticmapreducedescribeeditor-elasticmapreduceopeneditorinconsole source_revision: a53b46392c @@ -264,25 +266,28 @@ source_revision: a53b46392c technique: ssm:StartAssociationsOnce reason: Runs fixed associations on fixed targets; no control of code or role. -- source: - src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmdescribeparameters-ssmgetparameter--ssmgetparameters--ssmgetparametersbypath - source_revision: a53b46392c +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmdescribeparameters-ssmgetparameter--ssmgetparameters--ssmgetparametersbypath + source_revision: 0b36331 technique: ssm:GetParameter(s) - reason: Data read. -- source: - src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmgetparameterhistory--recover-current-and-previous-parameter-values - source_revision: a53b46392c + reason: Parameter contents may contain keys, but a snapshot cannot infer credential type, validity or target identity + from GetParameter permission alone. Requires exact content inspection and validation against the external or + IAM identity before an identity edge is justified. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmgetparameterhistory--recover-current-and-previous-parameter-values + source_revision: 0b36331 technique: ssm:GetParameterHistory - reason: Data read. + reason: History may expose old secrets, but an old password or token is not necessarily still valid. Requires + exact content inspection and validation against the external or IAM identity before an identity edge is justified. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmlistcommands - source_revision: a53b46392c + source_revision: 0b36331 technique: ssm:ListCommands - reason: Data read. -- source: - src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmgetcommandinvocation-ssmlistcommandinvocations--ssmlistcommands - source_revision: a53b46392c + reason: ListCommands can reveal inline secrets only when retained command parameters contain a usable credential. + Requires exact content inspection and validation against the external or IAM identity before an identity edge + is justified. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmgetcommandinvocation-ssmlistcommandinvocations--ssmlistcommands + source_revision: 0b36331 technique: ssm:GetCommandInvocation - reason: Data read. + reason: Command output may contain credentials only when retained stdout/stderr has a still-valid secret. Requires + exact content inspection and validation against the external or IAM identity before an identity edge is justified. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#codebuild source_revision: a53b46392c technique: SSM to CodeBuild session diff --git a/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml b/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml index cc074acef3..ba2d88213e 100644 --- a/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml @@ -317,9 +317,9 @@ 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 + reason: Add an X.509 private-key target and selector for an exact exportable ACM certificate and a relying service + that trusts its key. + source_revision: 0b36331 - 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, @@ -335,27 +335,24 @@ 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 + reason: Add an API Gateway client-key target and selector joining an enabled key, usage plan, stage and key-required + method, including other authorizers. + source_revision: 0b36331 - 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 + reason: Add an API Gateway client-key target and selector joining readable key value, usage-plan association and + key-required method. + source_revision: 0b36331 - 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 + reason: A stage variable can redirect traffic, but credential gain needs future requests containing usable tokens + and an attacker endpoint that receives them. + source_revision: 0b36331 - 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 + reason: Canary routing alone does not prove escalation. Credential theft needs future authenticated traffic; bypass + needs proof the retained deployment permits an otherwise forbidden operation. + source_revision: 0b36331 - 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 @@ -376,17 +373,14 @@ 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 + reason: CORS abuse needs an authenticated victim visiting the attacker origin with suitable cookies and a credentialed + endpoint; those browser/session facts are absent from configuration. + source_revision: 0b36331 - 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 + reason: Rollback is exploitable only if the selected historical deployment has weaker authorization or a removed + privileged route; deployment metadata does not prove this. + source_revision: 0b36331 - 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, @@ -401,59 +395,51 @@ 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 + reason: A route change gains credentials only when future matched requests contain reusable authentication material + and a controlled backend receives it. + source_revision: 0b36331 - 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 + reason: The returned content grants another identity only when it contains a usable credential; exact content + and authority must be verified. + source_revision: 0b36331 - 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 + reason: Creating a hosted version does not deploy it; a later actor must deploy it and consumer code must treat + its bytes as a privileged command. + source_revision: 0b36331 - 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 + reason: A deployment grants no fixed privilege without knowing the selected version bytes and security-sensitive + behavior of a live consumer. + source_revision: 0b36331 - 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 + reason: Add an AppFlow stored-connector authority target and selector joining flow, SaaS scope, field mapping + and attacker-readable destination. + source_revision: 0b36331 - 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 + reason: The returned content grants another identity only when it contains a usable credential; exact content + and authority must be verified. + source_revision: 0b36331 - 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 + reason: The returned content grants another identity only when it contains a usable credential; exact content + and authority must be verified. + source_revision: 0b36331 - 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 + reason: Image sharing yields credentials only if usable secrets were baked into the filesystem; recipient-side + image-builder inspection is required. + source_revision: 0b36331 - 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 + reason: AMI export yields credentials only if usable secrets are present in the image filesystem and the caller + has separate EC2 inspection access. + source_revision: 0b36331 - 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 @@ -480,35 +466,29 @@ 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 + reason: Add a DSQL database-role target and selector joining IAM mapping, cluster DbConnect allow and PostgreSQL + role grants. + source_revision: 0b36331 - 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 + reason: Add a bounded restore-authority target and selector joining recovery point, passable role, valid metadata, + target resource and source read/KMS rights. + source_revision: 0b36331 - 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 + reason: Add a recovery-point permission target and proposed-policy selector that evaluates the explicit vault-policy + self grant on an exact recovery point. + source_revision: 0b36331 - 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 + reason: The returned content grants another identity only when it contains a usable credential; exact content + and authority must be verified. + source_revision: 0b36331 - 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 + reason: The returned content grants another identity only when it contains a usable credential; exact content + and authority must be verified. + source_revision: 0b36331 - 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 @@ -518,9 +498,9 @@ - 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.' + reason: PutModelInvocationLoggingConfiguration can redirect future model input/output to an attacker-readable + S3 bucket; credential gain depends on a future prompt or completion containing a usable secret. Delete and disable + variants only blind logging; CloudWatch destination additionally needs a passable delivery role. 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' @@ -535,9 +515,9 @@ 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. + reason: RegisterInstance can replace a backend and receive client requests. Credential or backend-identity gain + requires clients to send usable tokens or protocol credentials and accept the replacement endpoint; those runtime + protocol facts are absent from inventory. 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' @@ -547,36 +527,36 @@ 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. + reason: DescribeStacks may expose literal parameters/outputs, GetTemplate hard-coded values, and GetTemplateSummary + defaults; NoEcho masks described parameters. A principal edge requires a usable credential and holder in returned + content. 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. + reason: ListExports returns output values; a privilege edge exists only if an export contains a usable credential + whose holder can be identified. Export metadata alone does not prove this. 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. + reason: DescribeChangeSet can return pending parameter values; a privilege edge requires an unmasked usable credential + and identified holder in the response. 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.' + reason: Origin custom headers can be shared secrets that permit direct-origin access and bypass CDN controls; + whether the origin accepts the value as an authentication credential is external application configuration/runtime + behavior. 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.' + reason: GetKey/ListKeys expose stored values that can include credentials. A privilege edge requires a usable + value and identifiable holder in the store content; keys and configuration alone cannot prove it. 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.' + reason: GetFunction can return embedded credentials in JavaScript. A privilege edge requires a usable secret and + identifiable holder in source content; function metadata cannot prove it. source_revision: a66f094ede - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-cloudfront-post-exploitation/README.md#cloudfrontdelete technique: '`cloudfront:Delete*`' @@ -597,16 +577,13 @@ 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.' + reason: GetLogEvents/FilterLogEvents can return authentication tokens in log messages. A principal edge requires + a usable token and holder in actual retained log content, which the configuration snapshot lacks. 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.' + reason: GetLogRecord/GetQueryResults can return credential-bearing rows, provided a valid pointer/query ID exists. + A principal edge requires a usable token and holder in returned content, not just the read grant. 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' @@ -616,9 +593,8 @@ 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.' + reason: CreateExportTask can copy historical logs to a readable bucket without direct log-read permission. Credential + gain requires retained messages containing a usable secret and an identifiable holder, plus successful export/read. 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' @@ -641,9 +617,9 @@ 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.' + reason: CreateLink can share source logs continuously with an allowed sink. Credential gain requires future shared + telemetry to contain a usable token and identify its holder; sink policy and Link grants alone do not prove + it. 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`**' @@ -652,14 +628,14 @@ 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.' + reason: PutMetricAlarm/PutCompositeAlarm can redirect or configure bounded alarm actions. A privilege edge requires + an enabled action, target resource policy and an action with a privileged effect; SNS notification or alarm + suppression alone does not grant target-role powers. 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.' + reason: SetAlarmState can trigger an enabled preconfigured alarm action. Its exact bounded effect depends on collected + alarm actions and target policies; do not infer arbitrary Lambda, SNS, EC2 or Auto Scaling role privileges. 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`**' @@ -702,9 +678,8 @@ 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.' + reason: UpdateLink can widen a permitted sink link to additional log groups; DeleteLink and narrowing only blind + telemetry. Credential gain requires newly shared log content to contain a usable secret and identify its holder. 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`' @@ -714,9 +689,8 @@ 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.' + reason: GetPackageVersionAsset can return an embedded credential. A principal edge requires a usable secret and + identifiable holder in the downloaded asset; package coordinates and metadata do not prove this. 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)' @@ -725,9 +699,9 @@ 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.' + reason: PUBLIC_READ exposes project history and configuration; exposing logs/artifacts also requires a passable + resource-access role. Credential gain requires published content to contain a usable secret and identify its + holder. source_revision: a66f094ede - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codebuild-post-exploitation/README.md#codebuilddeleteproject technique: '`codebuild:DeleteProject`' @@ -742,15 +716,16 @@ 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 + reason: GetFile/GetBlob return file bytes and GetCommit a commit message, any of which may hold a live credential + for another principal. The snapshot lacks content, owner, validity and scope, so the read permission alone cannot + produce an edge. + source_revision: 0b36331 - 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 + reason: GitPull exposes current and historical objects that may hold a still-live credential for another principal. + The snapshot lacks those objects and verified owner, validity and scope, so GitPull alone cannot produce an + edge. + source_revision: 0b36331 - 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 @@ -765,15 +740,14 @@ 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 + reason: GetPipeline/GetPipelineExecution can return literal credential values; secret references are not dereferenced. + The snapshot lacks returned literals and verified credential owner, validity and scope. + source_revision: 0b36331 - 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 + reason: ListActionExecutions can return literal credentials in resolved configuration or output variables. The + snapshot lacks those returned values and verified credential owner, validity and scope. + source_revision: 0b36331 - 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, @@ -827,11 +801,10 @@ 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 + reason: CreateParticipant returns a bounded chat/WebRTC participant bearer, not IAM or Connect admin credentials. + Exact contact/channel state, token exchange, role and service capabilities are needed before modeling the participant + identity. + source_revision: 0b36331 - 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 @@ -864,8 +837,8 @@ - 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.' + reason: The returned BGP key is authentication material, but a new authority requires a reachable peer accepting + that key and routing control; effective peer trust is not established by this AWS snapshot. 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 @@ -900,103 +873,91 @@ 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.' + reason: A DRS recovery boot exposes replicated disks; identity gain requires readable disk bytes containing a + still-usable credential owned by another identity. 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.' + reason: StartExport writes MGN migration inventory, not replicated disk contents. Test/cutover launch is separate + and needs launch control, disk access, and a usable credential. 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.' + reason: BatchGetItem reads known-key items; credential gain requires a returned usable credential of another identity. 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.' + reason: GetItem reads a known-key item; credential gain requires a returned usable credential of another identity. 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.' + reason: TransactGetItems reads known-key items; credential gain requires a returned usable credential of another + identity. 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.' + reason: Query reads matching-key items; credential gain requires a returned usable credential of another identity. 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.' + reason: Scan can enumerate table items; credential gain requires a returned usable credential of another identity. 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. + reason: PartiQLSelect reads items despite classic read denies; credential gain requires a returned usable credential + of another identity. The separately mentioned PartiQL write actions prove only table writes. 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.' + reason: Enabling and polling a stream can expose later item changes; credential gain requires a future record + containing a usable credential of another identity. 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.' + reason: UpdateItem with ReturnValues=ALL_OLD and the separately mentioned DeleteItem variant can return old attributes + despite read denies. Credential gain requires a known key and a returned usable credential of another identity; + item contents are runtime facts. 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.' + reason: A failed TransactWriteItems Update can return old attributes; credential gain requires a known key and + a usable credential in the cancellation response. 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.' + reason: The projection-ALL GSI can expose table items despite base-table read limits; credential gain requires + a usable credential in a projected item. 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. + reason: ExportTableToPointInTime copies records when PITR and S3 access permit it; credential gain requires a + usable credential of another identity in exported data. 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. + reason: RestoreTableFromBackup creates a separate table, but credential gain requires read access and a still-usable + credential in historical records. 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.' + reason: A replica update copies table items to another Region; credential gain requires read access to the replica + and a usable credential in copied data. 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.' + reason: Kinesis streaming copies future item changes; credential gain requires a later record with a usable credential + and stream read access. 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.' + reason: The restore APIs recreate current or historical table data; credential gain requires read access and a + still-usable credential in restored records. 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.' + reason: PutItem can replace an item and ReturnValues=ALL_OLD can return its prior attributes. Credential gain + requires a known key and a returned usable credential of another identity; item contents are unknown from configuration. source_revision: a66f094ede - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-dynamodb-post-exploitation/README.md#dynamodbupdateitem technique: '`dynamodb:UpdateItem`' @@ -1022,23 +983,19 @@ 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.' + reason: PutResourcePolicy can share a SecureString externally; credential gain requires a usable credential in + its value, external GetParameter access, and any needed KMS decrypt. 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.' + reason: ModifyDocumentPermission shares document content; credential gain requires an embedded usable credential + of another identity. 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.' + reason: VPC mirroring copies selected packet traffic; credential gain requires plaintext credentials or usable + session tokens in matching packets. 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' @@ -1105,9 +1062,8 @@ 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.' + reason: Route writes can redirect subnet traffic; credential gain requires interceptable usable credentials or + a relying service that accepts attacker responses. 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' @@ -1124,9 +1080,8 @@ 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.' + reason: DHCP option changes can redirect DNS resolution; credential gain requires victim queries and a spoofed + endpoint that receives credentials or is trusted. 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) @@ -1170,15 +1125,14 @@ 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 + reason: DescribeTaskDefinition returns literal environment values, which may contain reusable credentials; a concrete + escalation requires verifying a live value and mapping it to another principal. Secret ARNs alone are references. + source_revision: 0b36331 - 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 + reason: DescribeTasks returns runtime overrides that may include a live token or password; the snapshot must contain + the override value and identify its owner before claiming credential gain. + source_revision: 0b36331 - 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 @@ -1193,10 +1147,9 @@ - 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 + reason: Replication can expose credentials only if the replicated filesystem contains live credential files, the + destination can be read, and those files identify another principal; EFS configuration cannot prove content. + source_revision: 0b36331 - 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 @@ -1224,16 +1177,15 @@ 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 + reason: CNAME swapping yields credentials only if later authentication traffic reaches an attacker-controlled + destination and carries reusable credentials; DNS/environment configuration cannot prove those requests or their + content. + source_revision: 0b36331 - 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 + reason: A tag change grants authority only if an applicable IAM ABAC policy or tag-trusting automation evaluates + the new resource tag in the source’s favor; the tag mutation alone does not prove the policy path. + source_revision: 0b36331 - 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 @@ -1254,32 +1206,29 @@ 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 + reason: DescribeConfigurationSettings can reveal literal secrets, but the setting must contain a live reusable + credential for another principal; secret references and ordinary values do not establish that fact. + source_revision: 0b36331 - 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 + reason: A copied cache snapshot can contain sessions or credentials, but cache key/value content, credential validity, + and owner are needed to establish an identity gain. + source_revision: 0b36331 - 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 + reason: A serverless cache export can contain credentials, but cache content, credential validity, and owner are + needed to establish an identity gain. + source_revision: 0b36331 - 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 + reason: Redirecting ALB traffic yields credentials only if later authentication requests carry reusable secrets + and the attacker receives them; listener configuration cannot prove traffic content. + source_revision: 0b36331 - 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 + reason: Redirecting matching ALB traffic yields credentials only if the existing destination is attacker-readable + and later requests carry reusable secrets; rule configuration cannot prove those facts. + source_revision: 0b36331 - 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 @@ -1314,14 +1263,14 @@ 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 + reason: GetApplication may expose a literal runtime property credential; an escalation needs the actual live token/password + and its distinct owner, not just the application configuration name. + source_revision: 0b36331 - 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 + reason: GetJobRun may expose a literal argument or override credential; an escalation needs the actual live token/password + and its distinct owner, not just job metadata or a secret reference. + source_revision: 0b36331 - 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 @@ -1341,30 +1290,25 @@ 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 + reason: DescribePipe may return a static token in an InputTemplate; the actual value, validity, and distinct principal + must be verified before treating the read as escalation. + source_revision: 0b36331 - 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 + reason: A subscriber can replay events, but credential gain requires a readable delivery target and a retained + or future event carrying a live reusable credential for another principal. + source_revision: 0b36331 - 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 + reason: PutTargets can copy events, but credential gain requires a delivery-accepting attacker sink and matching + events containing a live reusable credential for another principal. + source_revision: 0b36331 - 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 + reason: An API destination can export events, but credential gain requires a working destination and matching + events containing a live reusable credential for another principal. + source_revision: 0b36331 - 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 @@ -1373,11 +1317,9 @@ 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 + reason: Removing filters can expose more events only through an already attacker-readable subscriber target; actual + future events must contain a live reusable credential for another principal. + source_revision: 0b36331 - 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, @@ -3012,3 +2954,133 @@ 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-post-exploitation/aws-api-gateway-post-exploitation/README.md#swap-route-integration-to-exfil-traffic-http-apis--apigatewayv2 + technique: Swap Route Integration To Exfil Traffic (HTTP APIs / `apigatewayv2`) + reason: Redirecting an HTTP integration can expose secrets only if future requests carry usable credentials to + a reachable attacker endpoint; those runtime facts are absent from configuration. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appconfig-post-exploitation/README.md#appconfig-experiments--overlay-attacker-controlled-feature-flag-treatments + technique: AppConfig Experiments — overlay attacker-controlled feature-flag treatments + reason: The treatment grants application privilege only if a live entity matches and consumer code interprets + the flag as an authorization control; those facts are not in AWS configuration. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appconfig-post-exploitation/README.md#appconfig-experiments--overlay-attacker-controlled-feature-flag-treatments + technique: UpdateExperimentRun treatment overrides or exposure on an existing run + reason: Updated treatment exposure grants privilege only if a live entity matches and consumer code uses the flag + for authorization; those facts are not in AWS configuration. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-datazone-post-exploitation/README.md#extract-published-asset-metadata-with-searchlistings + technique: Extract published asset metadata with `SearchListings` + reason: Published FORMS must contain a usable credential of another identity; neither the value nor its owner + or validity follows from SearchListings access. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-datazone-post-exploitation/README.md#inventory-project-members-and-private-catalog-content + technique: Inventory project members and private catalog content + reason: Private asset FORMS must contain a usable credential of another identity; membership and catalog inventory + do not establish secret content. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-datazone-post-exploitation/README.md#poison-a-trusted-asset-and-republish-its-listing + technique: Poison a trusted asset and republish its listing + reason: A downstream consumer must trust the poisoned listing, use the attacker endpoint, and disclose a credential; + publication alone grants no identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-device-farm-post-exploitation/README.md#reach-private-web-applications-through-testgrid + technique: Reach private web applications through TestGrid + reason: A reachable private application must have an authenticated session or exploitable authorization path; + TestGrid network reachability alone grants no identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-device-farm-post-exploitation/README.md#recover-plaintext-project-and-run-configuration + technique: Recover plaintext project and run configuration + reason: Project or run variables must actually contain a usable credential for another identity; the role ARN + and configuration metadata do not prove it. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-device-farm-post-exploitation/README.md#download-test-specifications-and-result-artifacts + technique: Download test specifications and result artifacts + reason: The downloaded test specification or artifact must contain a usable credential or bearer endpoint; upload + metadata does not identify its contents or owner. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-device-farm-post-exploitation/README.md#intercept-device-traffic-with-an-attacker-proxy + technique: Intercept device traffic with an attacker proxy + reason: Traffic must carry plaintext credentials or the app must trust the proxy certificate; the proxy setting + alone cannot decrypt validated TLS. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-devops-agent-post-exploitation/README.md#replace-a-private-connections-trusted-certificate-chain + technique: Replace a private connection's trusted certificate chain + reason: The attacker must separately control the routed endpoint and intercept a usable credential; replacing + the certificate chain alone changes TLS trust. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#search-sensitive-information-in-public-and-private-amis + technique: Search sensitive information in public and private AMIs + reason: The AMI filesystem must contain a usable credential of another identity and be launchable or readable; + image visibility proves neither fact. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#copy-running-instance + technique: Copy Running Instance + reason: The copied instance disk must contain a usable credential and the attacker must read the cloned volume; + CreateImage alone does not reveal one. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#restore-deleted-ebs-snapshots-from-recycle-bin + technique: Restore deleted EBS snapshots from Recycle Bin + reason: A retained snapshot must contain a usable credential and downstream EBS and KMS access must permit reading + it; restore permission alone is insufficient. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#live-data-theft-via-ebs-multi-attach + technique: Live Data Theft via EBS Multi-Attach + reason: The live volume must contain a usable credential and the attacker must mount and read it; Multi-Attach + metadata does not reveal content. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#elastic-ip-hijack-for-ingressegress-impersonation + technique: Elastic IP Hijack for Ingress/Egress Impersonation + reason: A relying party must authenticate by that public IP or intercepted traffic must contain a usable credential; + reassociation alone changes routing. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#ec2-eni-secondary-private-ip-hijack + technique: EC2 ENI Secondary Private IP Hijack + reason: A private service must accept the hijacked IP without stronger authentication or disclose a credential; + assigning the IP alone proves no identity gain. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#restore-deleted-ebs-snapshots-from-recycle-bin + technique: Restore deleted EBS volume from Recycle Bin + reason: The restored volume must be within retention, readable, and contain a usable credential; the page only + names this adjacent variant and leaves its IAM scope unverified. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#restore-deleted-ebs-snapshots-from-recycle-bin + technique: Restore deleted AMI from Recycle Bin + reason: The restored AMI must be within retention, launchable or readable, and contain a usable credential; the + page only names this adjacent variant and leaves its IAM scope unverified. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/README.md#elastic-ip-hijack-for-ingressegress-impersonation + technique: Release victim EIP for attacker reallocation + reason: ReleaseAddress does not guarantee attacker reacquisition of the same IP; a relying party must also trust + it or disclose credentials. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-ebs-multi-attach-data-theft.md#aws---live-data-theft-via-ebs-multi-attach + technique: AWS - Live Data Theft via EBS Multi-Attach + reason: The live EBS volume must contain a usable credential and the attacker must mount and read it; disk contents + are runtime facts. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-eip-hijack-impersonation.md#aws---elastic-ip-hijack-for-ingressegress-ip-impersonation + technique: AWS - Elastic IP Hijack for Ingress/Egress IP Impersonation + reason: An external relying party must trust the EIP as authentication or send usable credentials; address control + alone proves no new identity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-eni-secondary-ip-hijack.md#aws--ec2-eni-secondary-private-ip-hijack-trustallowlist-bypass + technique: AWS – EC2 ENI Secondary Private IP Hijack (Trust/Allowlist Bypass) + reason: A private application or ACL must treat the hijacked secondary IP as sufficient authority; that trust + rule and any resulting session are application facts. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ec2-ebs-ssm-and-vpc-post-exploitation/aws-malicious-vpc-mirror.md#aws---malicious-vpc-mirror + technique: AWS - Malicious VPC Mirror + reason: The dedicated mirror page describes packet capture; credential gain requires plaintext credentials or + valid session tokens in captured packets. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecr-post-exploitation/README.md#exfiltrate-upstream-registry-credentials-from-ecr-pullthrough-cache-ptc + technique: Exfiltrate upstream registry credentials from ECR Pull‑Through Cache (PTC) + reason: The named Secrets Manager value must contain an active upstream registry credential, and its username/token + and external registry scope must be verified from secret content; secret metadata and GetSecretValue permission + alone cannot identify a gained principal. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecr-post-exploitation/README.md#login-pull--push + technique: Login, Pull & Push + reason: An accessible image layer must actually contain a live reusable credential and identify its owner; image + metadata and pull permission cannot establish this from a configuration snapshot. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-post-exploitation/README.md#download-private-ecr-images-and-inspect-them-offline + technique: Download private ECR images and inspect them offline + reason: The pulled image layers must contain a live reusable credential and identify its owner; neither ECR pull + permission nor image metadata proves such content. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ecs-post-exploitation/README.md#mount-an-ebs-snapshot-in-an-ecs-task + technique: Mount an EBS snapshot in an ECS task + reason: The selected snapshot filesystem must contain live reusable credentials, the task must mount and disclose + them, and their owner must be identified; snapshot and ECS configuration alone do not prove these runtime facts. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-eks-post-exploitation/README.md#from-kubernetes-to-aws + technique: Read AWS credentials from pod environment, mounted files, or Kubernetes Secrets + reason: The pod environment, mounted file, or Kubernetes Secret must contain a valid AWS credential for a different + IAM principal; references and RBAC alone cannot identify that principal or prove the credential works. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-emr-post-exploitation/README.md#enumerate-cluster-configuration-instances-and-bootstrap-artifacts + technique: Enumerate cluster configuration, instances, and bootstrap artifacts + reason: A returned EMR configuration or Kerberos field must contain a live reusable credential for a distinct + identity; cluster metadata and describe permission alone cannot prove its value or owner. + source_revision: 0b36331 diff --git a/src/privilege-escalation-paths/aws/appconfig.yaml b/src/privilege-escalation-paths/aws/appconfig.yaml index 043d748f5d..af1e78950d 100644 --- a/src/privilege-escalation-paths/aws/appconfig.yaml +++ b/src/privilege-escalation-paths/aws/appconfig.yaml @@ -1,4 +1,39 @@ # AWS appconfig privilege escalation techniques. # Added by the HackTricks privesc completeness audit (rev 6fb9ac51fd). -[] +- id: aws-audit2-appconfig-2 + provider: aws + service: appconfig + title: AppConfig Data — read the deployed configuration + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appconfig-post-exploitation/README.md#appconfig-data--read-the-deployed-configuration + source_revision: 0b36331 + summary: Under exact prerequisites, the source obtains deployed bytes, including content fetched by AppConfig + retrieval role. + requires: + all_of: + - action: appconfig:StartConfigurationSession + resource: '*' + - action: appconfig:GetLatestConfiguration + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit2-appconfig-2 + scope: same_account + aggregate_as: Verified appconfig authority in {account} + grants: + - deployed bytes, including content fetched by AppConfig retrieval role + conditions: + - id: exact_verified_prerequisites + description: Both actions on exact configuration ARN. Deployment exists; customer KMS may require kms:Decrypt; + no cross-account AppConfig Data read. Evidence must bind exact source, target and resource; missing evidence + is unknown. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed actions and verify exact resource and downstream authority. + references: + - https://docs.aws.amazon.com/appconfig/latest/userguide/what-is-appconfig.html + notes: 'Provisional: exact verified source, target and authority evidence required; missing evidence evaluates + UNKNOWN.' diff --git a/src/privilege-escalation-paths/aws/appsync.yaml b/src/privilege-escalation-paths/aws/appsync.yaml index d1bdbcdba5..2868e9155a 100644 --- a/src/privilege-escalation-paths/aws/appsync.yaml +++ b/src/privilege-escalation-paths/aws/appsync.yaml @@ -82,3 +82,35 @@ - https://docs.aws.amazon.com/appsync/latest/APIReference/API_UpdateResolver.html - https://docs.aws.amazon.com/appsync/latest/devguide/resolver-reference-http-js.html notes: No-PassRole variant of aws-appsync-passrole-datasource-sigv4 (which reaches passable roles); this one reaches only roles already stored on data sources. AppSync data sources are not collected, so roles trusting appsync.amazonaws.com are the fallback target set (unknown). +- id: aws-audit2-appsync-2 + provider: aws + service: appsync + title: Read environment secrets and export the schema + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-appsync-post-exploitation/README.md#read-environment-secrets-and-export-the-schema + source_revision: 0b36331 + summary: Under exact prerequisites, the source obtains plaintext credential or token value. + requires: + all_of: + - action: appsync:GetGraphqlApiEnvironmentVariables + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit2-appsync-2 + scope: same_account + aggregate_as: Verified appsync authority in {account} + grants: + - plaintext credential or token value + conditions: + - id: exact_verified_prerequisites + description: Resource *. Actual environment value must contain usable secret. GetIntrospectionSchema and ListDataSources + are recon. Evidence must bind exact source, target and resource; missing evidence is unknown. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed actions and verify exact resource and downstream authority. + references: + - https://attacker.example + notes: 'Provisional: exact verified source, target and authority evidence required; missing evidence evaluates + UNKNOWN.' diff --git a/src/privilege-escalation-paths/aws/athena.yaml b/src/privilege-escalation-paths/aws/athena.yaml index 7d7f1e91aa..961320613d 100644 --- a/src/privilege-escalation-paths/aws/athena.yaml +++ b/src/privilege-escalation-paths/aws/athena.yaml @@ -144,3 +144,70 @@ references: - https://docs.aws.amazon.com/athena/latest/APIReference/API_UpdateNotebook.html notes: Authorized on the workgroup ARN, so any known notebook in the workgroup is reachable. +- id: aws-audit2-athena-query-disclosure-1 + provider: aws + service: athena-query-disclosure + title: Query-history and result disclosure + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-athena-query-disclosure-post-exploitation/README.md#query-history-and-result-disclosure + source_revision: 0b36331 + summary: Under exact prerequisites, the source obtains credential or token from another user query text. + requires: + all_of: + - action: athena:GetQueryExecution + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit2-athena-query-disclosure-1 + scope: same_account + aggregate_as: Verified athena-query-disclosure authority in {account} + grants: + - credential or token from another user query text + conditions: + - id: exact_verified_prerequisites + description: Known execution ID; ListQueryExecutions discovery only. SQL must hold usable value tied to target. + Evidence must bind exact source, target and resource; missing evidence is unknown. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed actions and verify exact resource and downstream authority. + references: + - https://docs.aws.amazon.com/AmazonS3/latest/userguide/dual-stack-endpoints.html + notes: 'Provisional: exact verified source, target and authority evidence required; missing evidence evaluates + UNKNOWN.' +- id: aws-audit2-athena-query-disclosure-2 + provider: aws + service: athena-query-disclosure + title: GetQueryResults with result-object access + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-athena-query-disclosure-post-exploitation/README.md#query-history-and-result-disclosure + source_revision: 0b36331 + summary: Under exact prerequisites, the source obtains credential value in result rows. + requires: + all_of: + - action: athena:GetQueryResults + resource: '*' + - action: s3:GetObject + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit2-athena-query-disclosure-2 + scope: same_account + aggregate_as: Verified athena-query-disclosure authority in {account} + grants: + - credential value in result rows + conditions: + - id: exact_verified_prerequisites + description: Both actions for Athena retrieval of SSE-S3 result; SSE-KMS may add kms:Decrypt. Direct S3 GetObject + is separate equivalent path. Actual rows must contain credential. Evidence must bind exact source, target + and resource; missing evidence is unknown. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed actions and verify exact resource and downstream authority. + references: + - https://docs.aws.amazon.com/AmazonS3/latest/userguide/dual-stack-endpoints.html + notes: 'Provisional: exact verified source, target and authority evidence required; missing evidence evaluates + UNKNOWN.' diff --git a/src/privilege-escalation-paths/aws/codeconnections.yaml b/src/privilege-escalation-paths/aws/codeconnections.yaml index 848f3aba43..5c39dba828 100644 --- a/src/privilege-escalation-paths/aws/codeconnections.yaml +++ b/src/privilege-escalation-paths/aws/codeconnections.yaml @@ -83,3 +83,32 @@ - https://docs.aws.amazon.com/codeconnections/latest/APIReference/API_UpdateRepositoryLink.html - https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/git-sync-prereq.html notes: No iam:PassRole is needed because the sync configuration keeps its role. Complements aws-codeconnections-gitsync-passrole (new or updated sync configuration with a passed role). +- id: aws-codeconnections-installation-consumer + provider: aws + service: codeconnections + title: Replace connection installation feeding a privileged deployment + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codeconnections-post-exploitation/README.md#complete-or-replace-a-connection-installation + source_revision: 0b36331 + summary: Replace connection installation feeding a privileged deployment when exact source-to-target authority + is verified. + requires: + all_of: + - action: codeconnections:UpdateConnectionInstallation + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-codeconnections-installation-consumer + scope: any + grants: + - consumer deployment role execution + confidence: conditional + severity: high + mitigation: Restrict the source permission and verify downstream authority. + references: + - src/pentesting-cloud/aws-security/aws-post-exploitation/aws-codeconnections-post-exploitation/README.md#complete-or-replace-a-connection-installation + notes: 'Draft: missing exact source, target, or usable-authority evidence evaluates UNKNOWN; emit no speculative + edge.' + conditions: + - A provider installation changes source access, but privileged role execution requires a controlled repository + revision consumed by an exact deployment. diff --git a/src/privilege-escalation-paths/aws/cognito.yaml b/src/privilege-escalation-paths/aws/cognito.yaml index d29b03097a..5d0112cc8e 100644 --- a/src/privilege-escalation-paths/aws/cognito.yaml +++ b/src/privilege-escalation-paths/aws/cognito.yaml @@ -458,3 +458,32 @@ - https://docs.aws.amazon.com/cognito/latest/developerguide/authentication-flow.html - https://docs.aws.amazon.com/cognito/latest/developerguide/role-trust-and-permissions.html notes: Complements aws-cognito-updateidentitypool (pool's configured roles, via attached_resource_covered_by). In the basic flow the role is not taken from the pool configuration, so no SetIdentityPoolRoles or iam:PassRole is needed; reachability is decided by the role trust's aud and amr conditions, which the evaluator should check when the trust is collected. +- id: aws-cognito-upstream-idp-client-secret + provider: aws + service: cognito-idp + title: Read upstream social or OIDC provider client secret + 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 + source_revision: 0b36331 + summary: DescribeIdentityProvider may disclose an upstream OAuth application client secret and its bounded external + authority. + requires: + all_of: + - action: cognito-idp:DescribeIdentityProvider + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-cognito-upstream-idp-client-secret + scope: any + grants: + - verified upstream OAuth application client scopes + confidence: conditional + severity: high + mitigation: Restrict DescribeIdentityProvider and rotate exposed upstream client secrets. + references: + - 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 + conditions: + - ProviderDetails must contain a cleartext client_secret; the external provider must accept it with the matching + client ID and configured flow. + notes: The existing aws-v3-25 entry is for DescribeUserPoolClient, a different Cognito secret and action. Missing + external validation must evaluate UNKNOWN. diff --git a/src/privilege-escalation-paths/aws/connect.yaml b/src/privilege-escalation-paths/aws/connect.yaml index d45cce15eb..56154b58c2 100644 --- a/src/privilege-escalation-paths/aws/connect.yaml +++ b/src/privilege-escalation-paths/aws/connect.yaml @@ -111,3 +111,152 @@ and restrict connect:GetFederationToken to the caller's own user. notes: Contact-center administration only; the Connect token is not AWS credentials. The requirement is evaluated on the source; when the source reaches it only through the federation role, that role's edge carries the chain. +- id: aws-connect-contact-credential + provider: aws + service: connect + title: Recover a credential persisted in Connect contact attributes or attached files + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#collect-contact-metadata-attributes-references-and-files + source_revision: 0b36331 + summary: Recover a credential persisted in Connect contact attributes or attached files when exact source-to-target + authority is verified. + requires: + all_of: + - action: connect:GetContactAttributes + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-connect-contact-credential + scope: any + grants: + - verified credential owner authority + confidence: conditional + severity: high + mitigation: Restrict the source permission and verify downstream authority. + references: + - src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#collect-contact-metadata-attributes-references-and-files + notes: 'Draft: missing exact source, target, or usable-authority evidence evaluates UNKNOWN; emit no speculative + edge. Alternative APIs listed in collector_request need separate OR branches before implementation; the draft + names one sufficient action and must not be used for the others until represented.' + conditions: + - The page describes possible credential capture; IAM permission alone does not prove content, owner, validity + or usable downstream scope. +- id: aws-connect-flow-credential + provider: aws + service: connect + title: Recover hard-coded credential from Connect flow/module source + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#recover-flow-source-and-integration-targets + source_revision: 0b36331 + summary: Recover hard-coded credential from Connect flow/module source when exact source-to-target authority is + verified. + requires: + all_of: + - action: connect:DescribeContactFlow + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-connect-flow-credential + scope: any + grants: + - verified credential owner authority + confidence: conditional + severity: high + mitigation: Restrict the source permission and verify downstream authority. + references: + - src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#recover-flow-source-and-integration-targets + notes: 'Draft: missing exact source, target, or usable-authority evidence evaluates UNKNOWN; emit no speculative + edge. Alternative APIs listed in collector_request need separate OR branches before implementation; the draft + names one sufficient action and must not be used for the others until represented.' + conditions: + - The page describes possible credential capture; IAM permission alone does not prove content, owner, validity + or usable downstream scope. +- id: aws-connect-conversation-credential + provider: aws + service: connect + title: Capture a credential from live voice/chat transcript or monitor session + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#read-or-monitor-live-conversations + source_revision: 0b36331 + summary: Capture a credential from live voice/chat transcript or monitor session when exact source-to-target authority + is verified. + requires: + all_of: + - action: connect:ListRealtimeContactAnalysisSegments + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-connect-conversation-credential + scope: any + grants: + - verified credential owner authority + confidence: conditional + severity: high + mitigation: Restrict the source permission and verify downstream authority. + references: + - src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#read-or-monitor-live-conversations + notes: 'Draft: missing exact source, target, or usable-authority evidence evaluates UNKNOWN; emit no speculative + edge. Alternative APIs listed in collector_request need separate OR branches before implementation; the draft + names one sufficient action and must not be used for the others until represented.' + conditions: + - The page describes possible credential capture; IAM permission alone does not prove content, owner, validity + or usable downstream scope. +- id: aws-connect-stream-credential + provider: aws + service: connect + title: Capture a credential from cross-account live chat stream + 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 + source_revision: 0b36331 + summary: Capture a credential from cross-account live chat stream when exact source-to-target authority is verified. + requires: + all_of: + - action: connect:StartContactStreaming + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-connect-stream-credential + scope: any + grants: + - verified credential owner authority + confidence: conditional + severity: high + mitigation: Restrict the source permission and verify downstream authority. + references: + - src/pentesting-cloud/aws-security/aws-post-exploitation/aws-connect-post-exploitation/README.md#stream-an-active-chat-to-a-cross-account-sns-topic + notes: 'Draft: missing exact source, target, or usable-authority evidence evaluates UNKNOWN; emit no speculative + edge. Alternative APIs listed in collector_request need separate OR branches before implementation; the draft + names one sufficient action and must not be used for the others until represented.' + conditions: + - The page describes possible credential capture; IAM permission alone does not prove content, owner, validity + or usable downstream scope. +- id: aws-connect-processor-credential + provider: aws + service: connect + title: Capture a credential through controlled Connect message processor + 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 + source_revision: 0b36331 + summary: Capture a credential through controlled Connect message processor when exact source-to-target authority + is verified. + requires: + all_of: + - action: connect:StartContactMediaProcessing + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-connect-processor-credential + scope: any + grants: + - verified credential owner authority + confidence: conditional + severity: high + mitigation: Restrict the source permission and verify downstream authority. + references: + - 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 + notes: 'Draft: missing exact source, target, or usable-authority evidence evaluates UNKNOWN; emit no speculative + edge. Alternative APIs listed in collector_request need separate OR branches before implementation; the draft + names one sufficient action and must not be used for the others until represented.' + conditions: + - The page describes possible credential capture; IAM permission alone does not prove content, owner, validity + or usable downstream scope. diff --git a/src/privilege-escalation-paths/aws/controltower.yaml b/src/privilege-escalation-paths/aws/controltower.yaml index 8846eacbd7..06f3a45d81 100644 --- a/src/privilege-escalation-paths/aws/controltower.yaml +++ b/src/privilege-escalation-paths/aws/controltower.yaml @@ -36,3 +36,32 @@ - https://docs.aws.amazon.com/controltower/latest/userguide/account-factory.html - https://docs.aws.amazon.com/controltower/latest/userguide/provision-and-manage-accounts.html notes: Provisioning a brand-new account (servicecatalog:ProvisionProduct) grants admin only over that new, empty account, which is not an existing principal in the snapshot. +- id: aws-controltower-preventive-scp-disable + provider: aws + service: controltower + title: Disable a preventive Control Tower control that enforces an SCP deny + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-control-tower-post-exploitation/README.md#enable--disable-controls + source_revision: 0b36331 + summary: Disable a preventive Control Tower control that enforces an SCP deny when exact source-to-target authority + is verified. + requires: + all_of: + - action: controltower:DisableControl + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-controltower-preventive-scp-disable + scope: same_account + grants: + - specific formerly blocked action + confidence: conditional + severity: high + mitigation: Restrict the source permission and verify downstream authority. + references: + - src/pentesting-cloud/aws-security/aws-post-exploitation/aws-control-tower-post-exploitation/README.md#enable--disable-controls + notes: 'Draft: missing exact source, target, or usable-authority evidence evaluates UNKNOWN; emit no speculative + edge.' + conditions: + - Only a preventive control that actually enforces an SCP Deny can activate a pre-existing Allow; detective controls + do not. diff --git a/src/privilege-escalation-paths/aws/ssm.yaml b/src/privilege-escalation-paths/aws/ssm.yaml index 9ce108e809..84b48d9107 100644 --- a/src/privilege-escalation-paths/aws/ssm.yaml +++ b/src/privilege-escalation-paths/aws/ssm.yaml @@ -7,33 +7,37 @@ service: ssm title: Start an Automation runbook that carries a preauthorized assume role 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 obtain the privileges of the assume role hardcoded in account-owned Automation runbooks it can start, limited to the runbook steps. + source_revision: 0b36331 + summary: Starting a stored-role runbook exercises only its authorized document version, steps and parameters; + it does not expose the full role. requires: all_of: - - action: ssm:StartAutomationExecution - resource: "{target.resource_arn}" + - action: ssm:StartAutomationExecution + resource: '{target.resource_arn}' target: - kind: aws_role + kind: aws_verified_authority selector: - trust_allows_service: ssm.amazonaws.com - via_resource_type: ssm_automation_document + aws_challenge_fact: aws-ssm-startautomationexecution-stored-role scope: same_account - aggregate_as: "Automation assume roles hardcoded in runbooks startable in {account}" + aggregate_as: Verified bounded authority in {account} + grants: + - Only the privileges of the callable Automation steps and outputs conditions: - - id: runbook_steps_useful - description: The source gains only what the runbook's fixed steps do with its parameters (e.g. a runbook that runs a script, attaches a policy or takes caller-chosen inputs); a runbook with no parameter-controlled privileged step gives no meaningful privilege. - - id: role_parameterised - description: If the assume role is a parameter rather than a literal, the source needs iam:PassRole on it and the technique becomes PassRole-style. + - id: exact_verified_prerequisites + description: A collected fact must bind the actor, exact resource, permitted inputs, target authority and useful + privileged effect. + - id: document_version_and_parameter_join + description: Resolve the exact startable document version, literal role, allowed parameters and steps; a read-only + DescribeOrganization runbook yields only that output. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Keep AutomationAssumeRole roles least-privileged, scope ssm:StartAutomationExecution to specific document ARNs, and avoid runbooks that execute caller-supplied scripts under privileged roles. + mitigation: Keep AutomationAssumeRole roles least-privileged, scope ssm:StartAutomationExecution to specific document + ARNs, and avoid runbooks that execute caller-supplied scripts under privileged roles. references: - - https://docs.aws.amazon.com/systems-manager/latest/userguide/automation-setup.html - notes: Target is the literal assumeRole of account-owned (not AWS-managed) Automation documents in Resource scope; reach is limited to the document's actions. - + - https://docs.aws.amazon.com/systems-manager/latest/userguide/automation-setup.html + notes: The stored role or service is usable only through the documented operation. Missing exact evidence is UNKNOWN. - id: aws-ssm-sendcommand provider: aws service: ssm @@ -533,3 +537,175 @@ 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. +- id: aws-audit-start-stored-state-manager-association + provider: aws + service: ssm + title: Start stored State Manager association + 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: 0b36331 + summary: The source can invoke a privileged fixed document under the node identity only when the exact target + and prerequisites are verified. + requires: + all_of: + - action: ssm:StartAssociationsOnce + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit-start-stored-state-manager-association + scope: same_account + aggregate_as: Verified Invoke a privileged fixed document under the in {account} + grants: + - Invoke a privileged fixed document under the node identity + conditions: + - id: exact_verified_prerequisites + description: 'Evidence must bind the source, exact target, and these prerequisites: Association ID is authorized; + document, parameters, targets and their role are fixed; existing steps must have an attacker-useful privileged + side effect or controllable input.' + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed permissions to approved operators and review the exact target configuration. + notes: Evidence must bind actor, exact resource, target and all prerequisites; absent evidence is UNKNOWN, with + no definite privilege edge. + references: + - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/ +- id: aws-audit-jit-shell-to-hybrid-managed-instance + provider: aws + service: ssm + title: JIT shell to hybrid managed instance + 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: 0b36331 + summary: The source can approved JIT credentials permit shell and node-role theft only when the exact target and + prerequisites are verified. + requires: + all_of: + - action: ssm:StartAccessRequest + resource: '*' + - action: ssm:GetAccessToken + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit-jit-shell-to-hybrid-managed-instance + scope: same_account + aggregate_as: Verified Approved JIT credentials permit shell and nod in {account} + grants: + - Approved JIT credentials permit shell and node-role theft + conditions: + - id: exact_verified_prerequisites + description: 'Evidence must bind the source, exact target, and these prerequisites: StartAccessRequest scoped + to arn:aws:ssm:::managed-instance/; GetAccessToken on *; JIT enabled and approved; + caller uses supported AssumeRole session; node online.' + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed permissions to approved operators and review the exact target configuration. + notes: Evidence must bind actor, exact resource, target and all prerequisites; absent evidence is UNKNOWN, with + no definite privilege edge. + references: + - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/ +- id: aws-audit-resume-disconnected-hybrid-node-session + provider: aws + service: ssm + title: Resume disconnected hybrid-node session + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#ssmresumesession + source_revision: 0b36331 + summary: The source can shell access and possible role credential theft only when the exact target and prerequisites + are verified. + requires: + all_of: + - action: ssm:ResumeSession + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit-resume-disconnected-hybrid-node-session + scope: same_account + aggregate_as: Verified Shell access and possible role credential the in {account} + grants: + - Shell access and possible role credential theft + conditions: + - id: exact_verified_prerequisites + description: 'Evidence must bind the source, exact target, and these prerequisites: Known resumable session + ID; session belongs to hybrid node; IAM session resource scope permits caller; node online.' + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed permissions to approved operators and review the exact target configuration. + notes: Evidence must bind actor, exact resource, target and all prerequisites; absent evidence is UNKNOWN, with + no definite privilege edge. + references: + - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/ +- id: aws-audit-create-association-targeting-hybrid-managed-node + provider: aws + service: ssm + title: Create association targeting hybrid managed node + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/README.md#privileged-execution-through-a-state-manager-association + source_revision: 0b36331 + summary: The source can execute supplied document as hybrid node only when the exact target and prerequisites + are verified. + requires: + all_of: + - action: ssm:CreateAssociation + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit-create-association-targeting-hybrid-managed-node + scope: same_account + aggregate_as: Verified Execute supplied document as hybrid node in {account} + grants: + - Execute supplied document as hybrid node + conditions: + - id: exact_verified_prerequisites + description: 'Evidence must bind the source, exact target, and these prerequisites: Target is an SSM online + hybrid node; caller may create association and use a shell-capable document.' + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed permissions to approved operators and review the exact target configuration. + notes: Evidence must bind actor, exact resource, target and all prerequisites; absent evidence is UNKNOWN, with + no definite privilege edge. + references: + - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/ +- 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: 0b36331 + summary: The source can execute caller-selected runbook steps as passable role only when the exact target and + prerequisites are verified. + requires: + all_of: + - action: ssm:StartAutomationExecution + resource: '*' + - action: iam:PassRole + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit-use-existing-parameterized-automation-runbook-with-runtime-passrole + scope: same_account + aggregate_as: Verified Execute caller-selected runbook steps as pass in {account} + grants: + - Execute caller-selected runbook steps as passable role + 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: Evidence must bind actor, exact resource, target and all prerequisites; absent evidence is UNKNOWN, with + no definite privilege edge. + references: + - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-ssm-privesc/ diff --git a/src/privilege-escalation-paths/aws/sso.yaml b/src/privilege-escalation-paths/aws/sso.yaml index 14dc649800..ba73443d70 100644 --- a/src/privilege-escalation-paths/aws/sso.yaml +++ b/src/privilege-escalation-paths/aws/sso.yaml @@ -230,45 +230,48 @@ service: sso title: Create an admin permission set and assign it to a controlled user in a member account 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 - summary: The source can become administrator of accounts it can assign by creating a new permission set, attaching an administrator policy, and assigning it to an Identity Center user it controls. + source_revision: 0b36331 + summary: The source can become administrator of accounts it can assign by creating a new permission set, attaching + an administrator policy, and assigning it to an Identity Center user it controls. requires: all_of: - - action: sso:CreatePermissionSet - resource: "*" - - action: sso:CreateAccountAssignment - resource: "arn:aws:sso:::account/{target.account}" - - action: sso:ProvisionPermissionSet - resource: "arn:aws:sso:::account/{target.account}" + - action: sso:CreatePermissionSet + resource: arn:aws:sso:::instance/* + - action: sso:CreateAccountAssignment + resource: arn:aws:sso:::account/{target.account} any_of: - - - action: sso:AttachManagedPolicyToPermissionSet - resource: "arn:aws:sso:::permissionSet/*" - - - action: sso:PutInlinePolicyToPermissionSet - resource: "arn:aws:sso:::permissionSet/*" + - - action: sso:AttachManagedPolicyToPermissionSet + resource: arn:aws:sso:::permissionSet/* + - - action: sso:PutInlinePolicyToPermissionSet + resource: arn:aws:sso:::permissionSet/* target: kind: aws_account_admin selector: any_principal_in_scope: true scope: org - aggregate_as: "Accounts reachable with a newly created permission set" + aggregate_as: Accounts reachable with a newly created permission set conditions: - - id: controls_identity_center_user - description: The source must control an Identity Center user or group to assign. - - id: management_account_permission_sets - description: A delegated administrator cannot create assignments in the management account. - - id: resource_scoping - description: CreatePermissionSet, policy attach and CreateAccountAssignment are authorized on instance, permission-set and account ARNs; aws:ResourceTag conditions on permission sets can limit the attach step. + - id: controls_identity_center_user + description: The source must control an Identity Center user or group to assign. + - id: management_account_permission_sets + description: A delegated administrator cannot create assignments in the management account. + - id: resource_scoping + description: CreatePermissionSet, policy attach and CreateAccountAssignment are authorized on instance, permission-set + and account ARNs; aws:ResourceTag conditions on permission sets can limit the attach step. + - id: first_assignment_provisions + description: For a new permission set, CreateAccountAssignment provisions the account role; subsequent permission-set + updates can need ProvisionPermissionSet. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: critical - mitigation: Restrict sso:CreatePermissionSet and assignment permissions to Identity Center administrators; scope assignments to specific accounts and permission-set ARNs. + mitigation: Restrict sso:CreatePermissionSet and assignment permissions to Identity Center administrators; scope + assignments to specific accounts and permission-set ARNs. references: - - https://docs.aws.amazon.com/singlesignon/latest/APIReference/API_CreatePermissionSet.html - - https://docs.aws.amazon.com/singlesignon/latest/APIReference/API_CreateAccountAssignment.html - - https://docs.aws.amazon.com/singlesignon/latest/userguide/delegated-admin.html + - https://docs.aws.amazon.com/singlesignon/latest/APIReference/API_CreatePermissionSet.html + - https://docs.aws.amazon.com/singlesignon/latest/APIReference/API_CreateAccountAssignment.html + - https://docs.aws.amazon.com/singlesignon/latest/userguide/delegated-admin.html notes: Complements aws-sso-createaccountassignment, which only reuses existing permission sets. - - id: aws-identitystore-createuser-groupmembership provider: aws service: sso @@ -384,3 +387,44 @@ - https://docs.aws.amazon.com/singlesignon/latest/IdentityStoreAPIReference/API_CreateUser.html - https://docs.aws.amazon.com/singlesignon/latest/APIReference/API_CreateAccountAssignment.html notes: Removes the controls_identity_center_user condition of aws-sso-createaccountassignment; the group-membership variant is aws-identitystore-createuser-groupmembership. +- id: aws-audit-enable-permission-sets-then-create-admin-assignment + provider: aws + service: sso + title: Enable permission sets then create admin assignment + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/README.md#aws-identity-center--aws-sso + source_revision: 0b36331 + summary: The source can turn application-only instance into account-access path and assign admin only when the + exact target and prerequisites are verified. + requires: + all_of: + - action: sso:UpdateInstance + resource: '*' + - action: sso:CreatePermissionSet + resource: '*' + - action: sso:AttachManagedPolicyToPermissionSet + resource: '*' + - action: sso:CreateAccountAssignment + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit-enable-permission-sets-then-create-admin-assignment + scope: same_account + aggregate_as: Verified Turn application-only instance into account-a in {account} + grants: + - Turn application-only instance into account-access path and assign admin + outcome: permission_grant + conditions: + - id: exact_verified_prerequisites + description: 'Evidence must bind source, exact target, and these prerequisites: Organization instance starts + with PermissionSetsEnabled=false; UpdateInstance enables it; source can create/attach/assign a new admin set + to controlled user; management/delegated-admin account restrictions apply.' + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed actions to approved operators and review the exact target configuration. + notes: Evidence must bind actor, exact resource, target and all prerequisites; absent evidence is UNKNOWN, with + no definite privilege edge. + references: + - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sso-and-identitystore-privesc/ diff --git a/src/privilege-escalation-paths/aws/stepfunctions.yaml b/src/privilege-escalation-paths/aws/stepfunctions.yaml index 57012ef882..a342eecf9e 100644 --- a/src/privilege-escalation-paths/aws/stepfunctions.yaml +++ b/src/privilege-escalation-paths/aws/stepfunctions.yaml @@ -172,3 +172,39 @@ references: - https://docs.aws.amazon.com/step-functions/latest/apireference/API_UpdateStateMachine.html notes: "" +- id: aws-audit-exfiltrate-eventbridge-connection-credential-via-teststate-http-task + provider: aws + service: states + title: Exfiltrate EventBridge Connection credential via TestState HTTP Task + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/README.md#eventbridge-connection-credentials-without-statesrevealsecrets + source_revision: 0b36331 + summary: The source can obtain reusable API key, Basic credential, or OAuth token only when the exact target and + prerequisites are verified. + requires: + all_of: + - action: states:TestState + resource: '*' + - action: iam:PassRole + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit-exfiltrate-eventbridge-connection-credential-via-teststate-http-task + scope: same_account + aggregate_as: Verified Obtain reusable API key, Basic credential, or in {account} + grants: + - Obtain reusable API key, Basic credential, or OAuth token + conditions: + - id: exact_verified_prerequisites + description: 'Evidence must bind the source, exact target, and these prerequisites: Passed Step Functions role + trusts states.amazonaws.com and permits InvokeHTTPEndpoint, RetrieveConnectionCredentials, GetSecretValue + and DescribeSecret on connection secret; known connection; attacker HTTPS endpoint; states:RevealSecrets unnecessary.' + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed permissions to approved operators and review the exact target configuration. + notes: Evidence must bind actor, exact resource, target and all prerequisites; absent evidence is UNKNOWN, with + no definite privilege edge. + references: + - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-stepfunctions-privesc/ diff --git a/src/privilege-escalation-paths/aws/sts.yaml b/src/privilege-escalation-paths/aws/sts.yaml index 756283fa53..cdd97570e6 100644 --- a/src/privilege-escalation-paths/aws/sts.yaml +++ b/src/privilege-escalation-paths/aws/sts.yaml @@ -149,41 +149,41 @@ service: sts title: Obtain a privileged root-user session in a member account with sts:AssumeRoot 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 - summary: A principal in the management account or the IAM delegated-administrator account can open short root sessions in member accounts, limited to AWS-managed task policies that can reset root credentials and unlock resource policies. + source_revision: 0b36331 + summary: AssumeRoot creates a short member-account root session restricted to the selected AWS managed root-task + policy. requires: all_of: - - action: sts:AssumeRoot - resource: "arn:aws:iam::{target.account}:root" + - action: sts:AssumeRoot + resource: arn:aws:iam::{target.account}:root target: - kind: aws_account_admin + kind: aws_verified_authority selector: - any_principal_in_scope: true - org_member_account: true + aws_challenge_fact: aws-sts-assumeroot-member-accounts scope: org - aggregate_as: "Member accounts reachable through centralized root sessions" + aggregate_as: Verified bounded authority in {account} + grants: + - One selected IAM root-task policy, never unrestricted root conditions: - - id: source_in_management_or_delegated_admin - description: The source must be in the organization management account or the account registered as IAM delegated administrator; the management account itself cannot be targeted. - - id: root_sessions_enabled - description: Centralized root access (RootSessions) must be enabled for the organization; from the management account it can be enabled with organizations:EnableAWSServiceAccess, iam:EnableOrganizationsRootCredentialsManagement and iam:EnableOrganizationsRootSessions. - - id: task_policy_scope - description: Each session is scoped to one task policy (IAMAuditRootUserCredentials, IAMCreateRootUserPassword, IAMDeleteRootUserCredentials, S3UnlockBucketPolicy, SQSUnlockQueuePolicy) and lasts at most 900 seconds; full root control needs IAMCreateRootUserPassword followed by a root sign-in. - - id: task_policy_condition_keys - description: sts:TaskPolicyArn conditions on the grant can restrict which task policies the source may request. + - id: exact_verified_prerequisites + description: A collected fact must bind the actor, exact resource, permitted inputs, target authority and useful + privileged effect. + - id: task_policy_and_feature + description: Centralized RootSessions must be enabled; bind exact member account and permitted sts:TaskPolicyArn. + Password reset is not permanent takeover unless root sign-in can complete. preconditions: - - target_in_other_account + - target_in_other_account blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: critical - mitigation: Restrict sts:AssumeRoot to break-glass roles in the management / delegated-admin account, constrain sts:TaskPolicyArn, and alert on AssumeRoot events. + mitigation: Restrict sts:AssumeRoot to break-glass roles in the management / delegated-admin account, constrain + sts:TaskPolicyArn, and alert on AssumeRoot events. references: - - https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoot.html - - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user-privileged-task.html - - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-enable-root-access.html - notes: Root password recovery for member accounts may still face root MFA when it is configured; SCPs apply to member-account root users. - + - https://docs.aws.amazon.com/STS/latest/APIReference/API_AssumeRoot.html + - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-user-privileged-task.html + - https://docs.aws.amazon.com/IAM/latest/UserGuide/id_root-enable-root-access.html + notes: The stored role or service is usable only through the documented operation. Missing exact evidence is UNKNOWN. - id: aws-rolesanywhere-createtrustanchor-createprofile-passrole provider: aws service: rolesanywhere @@ -219,3 +219,45 @@ references: - https://docs.aws.amazon.com/rolesanywhere/latest/userguide/trust-model.html notes: Only roles whose trust policy already allows rolesanywhere.amazonaws.com are reached; adding that trust is a separate trust-policy edge. The profile session policy can reduce the obtained permissions. +- id: aws-audit-enable-centralized-root-sessions-then-call-assumeroot + provider: aws + service: organizations + title: Enable centralized root sessions then call AssumeRoot + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/README.md#enabling-the-feature-yourself-management-account + source_revision: 0b36331 + summary: The source can gain one selected root task capability only when the exact target and prerequisites are + verified. + requires: + all_of: + - action: organizations:EnableAWSServiceAccess + resource: '*' + - action: iam:EnableOrganizationsRootCredentialsManagement + resource: '*' + - action: iam:EnableOrganizationsRootSessions + resource: '*' + - action: sts:AssumeRoot + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit-enable-centralized-root-sessions-then-call-assumeroot + scope: same_account + aggregate_as: Verified Gain one selected root task capability in {account} + grants: + - Gain one selected root task capability + outcome: permission_grant + conditions: + - id: exact_verified_prerequisites + description: 'Evidence must bind the source, exact target, and these prerequisites: Source in Organizations + management account; feature initially disabled; IAM trusted access enabled; root credentials management enabled; + RootSessions enabled; sts:AssumeRoot allowed for member and task policy; registration optional if delegated + to another account.' + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed permissions to approved operators and review the exact target configuration. + notes: Evidence must bind actor, exact resource, target and all prerequisites; absent evidence is UNKNOWN, with + no definite privilege edge. + references: + - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sts-privesc/ diff --git a/src/privilege-escalation-paths/aws/synthetics.yaml b/src/privilege-escalation-paths/aws/synthetics.yaml index e71da5f3e1..fc9400095c 100644 --- a/src/privilege-escalation-paths/aws/synthetics.yaml +++ b/src/privilege-escalation-paths/aws/synthetics.yaml @@ -46,3 +46,37 @@ - https://docs.aws.amazon.com/AmazonSynthetics/latest/APIReference/API_StartCanaryDryRun.html - https://docs.aws.amazon.com/service-authorization/latest/reference/list_synthetics.html notes: The source's Lambda UpdateFunctionConfiguration on the generated function is itself an edge (lambda.yaml) to the same role; this entry is the supported Synthetics path. +- id: aws-audit-trigger-privileged-existing-canary + provider: aws + service: synthetics + title: Trigger privileged existing canary + 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: 0b36331 + summary: The source can cause attacker-useful privileged effect under stored role only when the exact target and + prerequisites are verified. + requires: + all_of: + - action: synthetics:StartCanary + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit-trigger-privileged-existing-canary + scope: same_account + aggregate_as: Verified Cause attacker-useful privileged effect under in {account} + grants: + - Cause attacker-useful privileged effect under stored role + conditions: + - id: exact_verified_prerequisites + description: 'Evidence must bind the source, exact target, and these prerequisites: Stopped canary known and + StartCanary permission covers exact ARN; code is fixed; only flag if code has sensitive side effect or exposes + role-only data to caller.' + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed permissions to approved operators and review the exact target configuration. + notes: Evidence must bind actor, exact resource, target and all prerequisites; absent evidence is UNKNOWN, with + no definite privilege edge. + references: + - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-synthetics-privesc/ diff --git a/src/privilege-escalation-paths/aws/timestream.yaml b/src/privilege-escalation-paths/aws/timestream.yaml new file mode 100644 index 0000000000..0c2fdd50ed --- /dev/null +++ b/src/privilege-escalation-paths/aws/timestream.yaml @@ -0,0 +1,76 @@ +- id: aws-audit-create-scheduled-query-to-exfiltrate-role-readable-secrets + provider: aws + service: timestream + title: Create scheduled query to exfiltrate role-readable secrets + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-timestream-privesc/README.md#timestreamcreatescheduledquery--iampassrole--run-sql-and-downstream-writes-as-a-scheduled-query-role + source_revision: 0b36331 + summary: The source can read sensitive rows through role and write to readable target/error report only when the + exact target and prerequisites are verified. + requires: + all_of: + - action: timestream:CreateScheduledQuery + resource: '*' + - action: timestream:DescribeEndpoints + resource: '*' + - action: iam:PassRole + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit-create-scheduled-query-to-exfiltrate-role-readable-secrets + scope: same_account + aggregate_as: Verified Read sensitive rows through role and write to in {account} + grants: + - Read sensitive rows through role and write to readable target/error report + outcome: permission_grant + conditions: + - id: exact_verified_prerequisites + description: 'Evidence must bind the source, exact target, and these prerequisites: Execution role trusts timestream.amazonaws.com + and can Select source, WriteRecords target, Publish notification, write S3 error report; selected output readable + by source; KMS/TagResource conditional; query name satisfies trust SourceArn.' + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed permissions to approved operators and review the exact target configuration. + notes: Evidence must bind actor, exact resource, target and all prerequisites; absent evidence is UNKNOWN, with + no definite privilege edge. + references: + - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-timestream-privesc/ +- id: aws-audit-trigger-stored-query-that-delivers-restricted-secrets + provider: aws + service: timestream + title: Trigger stored query that delivers restricted secrets + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-timestream-privesc/README.md#timestreamexecutescheduledquery--trigger-an-already-stored-role-workflow + source_revision: 0b36331 + summary: The source can receive or cause exposure of data/credentials through stored role only when the exact + target and prerequisites are verified. + requires: + all_of: + - action: timestream:ExecuteScheduledQuery + resource: '*' + - action: timestream:DescribeEndpoints + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit-trigger-stored-query-that-delivers-restricted-secrets + scope: same_account + aggregate_as: Verified Receive or cause exposure of data/credentials in {account} + grants: + - Receive or cause exposure of data/credentials through stored role + outcome: permission_grant + conditions: + - id: exact_verified_prerequisites + description: 'Evidence must bind the source, exact target, and these prerequisites: Fixed SQL, role, destination + and permitted InvocationTime must already disclose useful rows to an attacker-readable target or error-report + prefix; otherwise only cost/integrity effect.' + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed permissions to approved operators and review the exact target configuration. + notes: Evidence must bind actor, exact resource, target and all prerequisites; absent evidence is UNKNOWN, with + no definite privilege edge. + references: + - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-timestream-privesc/ diff --git a/src/privilege-escalation-paths/aws/transfer.yaml b/src/privilege-escalation-paths/aws/transfer.yaml index 0a2de79e4c..896eeb41e7 100644 --- a/src/privilege-escalation-paths/aws/transfer.yaml +++ b/src/privilege-escalation-paths/aws/transfer.yaml @@ -7,188 +7,232 @@ service: transfer title: Import an SSH key for an existing service-managed Transfer user source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#transferimportsshpublickey--impersonate-a-service-managed-user - source_revision: 171e422299 - summary: The source can obtain the S3/EFS file-access privileges of the IAM role configured on a service-managed Transfer Family user. + source_revision: 0b36331 + summary: Transfer file operations as the selected service-managed user within the exact server, storage, session-policy + and home-directory limits. requires: all_of: - - action: transfer:ImportSshPublicKey - resource: "{target.resource_arn}" + - action: transfer:ImportSshPublicKey + resource: '{target.resource_arn}' target: - kind: aws_role + kind: aws_verified_authority selector: - trust_allows_service: transfer.amazonaws.com - via_resource_type: transfer_user + aws_challenge_fact: aws-transfer-importsshpublickey scope: same_account - aggregate_as: "Roles of service-managed Transfer Family users in {account}" + aggregate_as: Verified bounded authority in {account} + grants: + - Transfer file operations as the selected service-managed user conditions: - - id: service_managed_identity - description: The server must use service-managed identities (custom identity providers authenticate elsewhere) with SFTP enabled. - - id: network_reachability - description: The source needs a network path to the server's public or VPC endpoint. - - id: session_policy_and_home_directory - description: Access is limited to the file operations the role allows, further narrowed by the user's session policy and logical home directory; no AWS API credentials are obtained. + - id: exact_verified_prerequisites + description: A collected fact must bind the actor, exact resource, permitted inputs, target authority and useful + privileged effect. + - id: transfer_scope_join + description: Bind the exact server, authenticated user, selected role, session policy, home directory, and accessible + S3/EFS paths; the role is never assumed by the attacker. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: medium - mitigation: Restrict transfer:ImportSshPublicKey to Transfer administrators, scope user roles and session policies to the user's own prefix, and alert on key imports. + mitigation: Restrict transfer:ImportSshPublicKey to Transfer administrators, scope user roles and session policies + to the user's own prefix, and alert on key imports. references: - - https://docs.aws.amazon.com/transfer/latest/APIReference/API_ImportSshPublicKey.html - notes: Bounded impact - the role is used by the Transfer service for file operations only, so this is data-plane access via another principal's role rather than full role assumption. - + - https://docs.aws.amazon.com/transfer/latest/APIReference/API_ImportSshPublicKey.html + notes: The stored role or service is usable only through the documented operation. Missing exact evidence is UNKNOWN. - id: aws-transfer-passrole-createuser-access provider: aws service: transfer title: Attach a passed role to a Transfer Family user or access mapping the source can log in as 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 - source_revision: 171e422299 - summary: The source can exercise the S3/EFS file-access privileges of a passable role trusting transfer.amazonaws.com by binding it to a Transfer Family identity it can authenticate as. + source_revision: 0b36331 + summary: Transfer file operations through the selected passable role within the exact server, storage, session-policy + and home-directory limits. requires: all_of: - - action: iam:PassRole - resource: "{target.arn}" + - action: iam:PassRole + resource: '{target.arn}' any_of: - - - action: transfer:CreateUser - resource: "*" - - - action: transfer:UpdateUser - resource: "*" - - - action: transfer:CreateAccess - resource: "*" - - - action: transfer:UpdateAccess - resource: "*" + - - action: transfer:CreateUser + resource: '*' + - - action: transfer:UpdateUser + resource: '*' + - - action: transfer:CreateAccess + resource: '*' + - - action: transfer:UpdateAccess + resource: '*' target: - kind: aws_role + kind: aws_verified_authority selector: - trust_allows_service: transfer.amazonaws.com - resource_permission_covers_target: iam:PassRole + aws_challenge_fact: aws-transfer-passrole-createuser-access scope: same_account - aggregate_as: "Roles trusting transfer.amazonaws.com passable in {account}" + aggregate_as: Verified bounded authority in {account} + grants: + - Transfer file operations through the selected passable role conditions: - - id: authenticate_as_identity - description: The source must authenticate as the identity (an SSH key it supplies for a service-managed user, or membership in the mapped AD group for an access mapping). - - id: network_reachability - description: The source needs a network path to the server's public or VPC endpoint. - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict which roles can be passed. + - id: exact_verified_prerequisites + description: A collected fact must bind the actor, exact resource, permitted inputs, target authority and useful + privileged effect. + - id: transfer_scope_join + description: Bind the exact server, authenticated user, selected role, session policy, home directory, and accessible + S3/EFS paths; the role is never assumed by the attacker. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: medium - mitigation: Restrict transfer:CreateUser/UpdateUser/CreateAccess/UpdateAccess and iam:PassRole on Transfer roles, and scope Transfer roles to per-user prefixes. + mitigation: Restrict transfer:CreateUser/UpdateUser/CreateAccess/UpdateAccess and iam:PassRole on Transfer roles, + and scope Transfer roles to per-user prefixes. references: - - https://docs.aws.amazon.com/transfer/latest/APIReference/API_CreateUser.html - notes: Bounded impact - file operations through the role; no API credentials are returned. - + - https://docs.aws.amazon.com/transfer/latest/APIReference/API_CreateUser.html + notes: The stored role or service is usable only through the documented operation. Missing exact evidence is UNKNOWN. - id: aws-transfer-secret-backed-idp-record provider: aws service: transfer title: Rewrite a Secrets Manager record used by a Transfer custom identity provider source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#secretsmanagerputsecretvalue--poison-a-secrets-manager-backed-custom-idp-user - source_revision: 171e422299 - summary: The source can exercise the file-access privileges of any role trusting transfer.amazonaws.com by writing a custom-IdP user record that sets its credential and selects that role. + source_revision: 0b36331 + summary: Transfer file operations selected by the exact secret-backed IdP record within the exact server, storage, + session-policy and home-directory limits. requires: all_of: - - action: secretsmanager:PutSecretValue - resource: "{target.consumer_input_arn}" + - action: secretsmanager:PutSecretValue + resource: '{target.resource_arn}' target: - kind: aws_role + kind: aws_verified_authority selector: - trust_allows_service: transfer.amazonaws.com - consumer_input_writable_via: secretsmanager:PutSecretValue + aws_challenge_fact: aws-transfer-secret-backed-idp-record scope: same_account - aggregate_as: "Roles trusting transfer.amazonaws.com selectable by writable custom-IdP records in {account}" + aggregate_as: Verified bounded authority in {account} + grants: + - Transfer file operations selected by the exact secret-backed IdP record conditions: - - id: idp_reads_role_from_secret - description: Only the legacy Secrets Manager-backed custom IdP that reads Role/Policy/HomeDirectory from the same secret (aws/transfer//) is affected; DynamoDB-backed solutions are not. - - id: kms_key - description: A customer-managed KMS key on the secret also requires kms permissions for the source. - - id: network_reachability - description: The source needs a network path to the server endpoint. + - id: exact_verified_prerequisites + description: A collected fact must bind the actor, exact resource, permitted inputs, target authority and useful + privileged effect. + - id: transfer_scope_join + description: Bind the exact server, authenticated user, selected role, session policy, home directory, and accessible + S3/EFS paths; the role is never assumed by the attacker. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: medium - mitigation: Separate credential data from authorization attributes in custom IdPs, deny PutSecretValue on aws/transfer/* secrets except to the IdP administrators, and alert on such writes. + mitigation: Separate credential data from authorization attributes in custom IdPs, deny PutSecretValue on aws/transfer/* + secrets except to the IdP administrators, and alert on such writes. references: - - https://docs.aws.amazon.com/transfer/latest/userguide/custom-idp-intro.html - notes: No iam:PassRole is involved; the IdP response chooses the role. Bounded to file operations through the role. - + - https://docs.aws.amazon.com/transfer/latest/userguide/custom-idp-intro.html + notes: The stored role or service is usable only through the documented operation. Missing exact evidence is UNKNOWN. - id: aws-transfer-custom-idp-takeover provider: aws service: transfer title: Take over a Transfer Family custom identity provider 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 - source_revision: 171e422299 - summary: The source can exercise the file-access privileges of any role trusting transfer.amazonaws.com by controlling the custom identity provider response that selects the session role. + source_revision: 0b36331 + summary: Transfer file operations selected by the active custom IdP response within the exact server, storage, + session-policy and home-directory limits. requires: any_of: - - - action: transfer:UpdateServer - resource: "*" - - - action: lambda:UpdateFunctionCode - resource: "{target.consumer_input_arn}" - - - action: apigateway:PATCH - resource: "{target.consumer_input_arn}" - - action: apigateway:POST - resource: "*" + - - action: transfer:UpdateServer + resource: '*' + - - action: lambda:UpdateFunctionCode + resource: '{target.resource_arn}' + - - action: apigateway:PATCH + resource: '{target.resource_arn}' + - action: apigateway:POST + resource: '*' target: - kind: aws_role + kind: aws_verified_authority selector: - trust_allows_service: transfer.amazonaws.com + aws_challenge_fact: aws-transfer-custom-idp-takeover scope: same_account - aggregate_as: "Roles trusting transfer.amazonaws.com in {account} (custom IdP servers)" + aggregate_as: Verified bounded authority in {account} + grants: + - Transfer file operations selected by the active custom IdP response conditions: - - id: custom_idp_server - description: The server must use a Lambda or API Gateway custom identity provider (UpdateServer can also switch it to one). - - id: updateserver_existing_function - description: The UpdateServer path needs an existing Lambda function the source controls whose resource policy allows the server to invoke it. - - id: lambda_code_signing - description: Code signing enforced on the IdP function blocks an unsigned replacement. - - id: network_reachability - description: The source needs a network path to the server endpoint. + - id: exact_verified_prerequisites + description: A collected fact must bind the actor, exact resource, permitted inputs, target authority and useful + privileged effect. + - id: transfer_scope_join + description: Bind the exact server, authenticated user, selected role, session policy, home directory, and accessible + S3/EFS paths; the role is never assumed by the attacker. blockers: - - scp_or_boundary_deny - - lambda_code_signing_enforced + - scp_or_boundary_deny + - lambda_code_signing_enforced confidence: conditional severity: medium - mitigation: Restrict transfer:UpdateServer to deployment roles, protect IdP functions with code signing and restricted lambda:UpdateFunctionCode, restrict API Gateway PATCH/deployment on IdP APIs, and keep Transfer roles least-privileged. + mitigation: Restrict transfer:UpdateServer to deployment roles, protect IdP functions with code signing and restricted + lambda:UpdateFunctionCode, restrict API Gateway PATCH/deployment on IdP APIs, and keep Transfer roles least-privileged. references: - - https://docs.aws.amazon.com/transfer/latest/userguide/custom-lambda-idp.html - notes: The IdP response chooses any role trusting transfer.amazonaws.com without iam:PassRole. The IdP function/API (consumer input) mapping is not collected, so the Lambda/API Gateway groups resolve as unknown; apigateway:POST is required on "*" because the deployment resource differs from the integration response (false negatives only). - + - https://docs.aws.amazon.com/transfer/latest/userguide/custom-lambda-idp.html + notes: The stored role or service is usable only through the documented operation. Missing exact evidence is UNKNOWN. - id: aws-transfer-workflow-passrole-updateserver provider: aws service: transfer title: Attach a managed workflow with a passed execution role to a Transfer server source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/README.md#managed-workflow-role-abuse--execute-storage-actions-on-upload - source_revision: 171e422299 - summary: The source can have Transfer Family run workflow steps (copy, tag, delete, decrypt, custom Lambda invoke) with the privileges of a passable role trusting transfer.amazonaws.com. + source_revision: 0b36331 + summary: Only COPY, TAG, DELETE, DECRYPT or allowed Lambda invocation steps within the exact server, storage, + session-policy and home-directory limits. requires: all_of: - - action: transfer:CreateWorkflow - resource: "*" - - action: transfer:UpdateServer - resource: "*" - - action: iam:PassRole - resource: "{target.arn}" + - action: transfer:CreateWorkflow + resource: '*' + - action: transfer:UpdateServer + resource: '*' + - action: iam:PassRole + resource: '{target.arn}' target: - kind: aws_role + kind: aws_verified_authority selector: - trust_allows_service: transfer.amazonaws.com - resource_permission_covers_target: iam:PassRole + aws_challenge_fact: aws-transfer-workflow-passrole-updateserver scope: same_account - aggregate_as: "Roles trusting transfer.amazonaws.com passable in {account}" + aggregate_as: Verified bounded authority in {account} + grants: + - Only COPY, TAG, DELETE, DECRYPT or allowed Lambda invocation steps conditions: - - id: upload_trigger - description: Workflows run on a completed or partial upload to the server; the source must be able to upload or wait for legitimate uploads (AS2 messages do not trigger server workflows). - - id: step_types_bound_impact - description: The role is only exercised through workflow step types; custom steps invoke existing Lambda functions, which run with their own roles. - - id: passrole_condition_key - description: iam:PassedToService conditions may restrict which roles can be passed. + - id: exact_verified_prerequisites + description: A collected fact must bind the actor, exact resource, permitted inputs, target authority and useful + privileged effect. + - id: transfer_scope_join + description: Bind the exact server, authenticated user, selected role, session policy, home directory, and accessible + S3/EFS paths; the role is never assumed by the attacker. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: medium - mitigation: Restrict transfer:CreateWorkflow/UpdateServer and iam:PassRole on Transfer workflow roles, and scope workflow roles to the prefixes they process. + mitigation: Restrict transfer:CreateWorkflow/UpdateServer and iam:PassRole on Transfer workflow roles, and scope + workflow roles to the prefixes they process. + references: + - https://docs.aws.amazon.com/transfer/latest/userguide/workflow-execution-role.html + notes: The stored role or service is usable only through the documented operation. Missing exact evidence is UNKNOWN. +- id: aws-audit-redirect-connector-to-steal-partner-sftp-credential + provider: aws + service: transfer + title: Redirect connector to steal partner SFTP credential + 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: 0b36331 + summary: The source can authenticate as partner or access partner files only when the exact target and prerequisites + are verified. + requires: + all_of: + - action: transfer:UpdateConnector + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit-redirect-connector-to-steal-partner-sftp-credential + scope: same_account + aggregate_as: Verified Authenticate as partner or access partner fil in {account} + grants: + - Authenticate as partner or access partner files + conditions: + - id: exact_verified_prerequisites + description: Evidence must prove the connector URL update reaches an attacker endpoint accepted by host-key + validation, a later connection occurs, and a reusable password is captured and validated for the partner identity. + SSH public-key authentication alone does not disclose the private key. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed permissions to approved operators and review the exact target configuration. + notes: Evidence must bind actor, exact resource, target and all prerequisites; absent evidence is UNKNOWN, with + no definite privilege edge. references: - - https://docs.aws.amazon.com/transfer/latest/userguide/workflow-execution-role.html - notes: Bounded impact - storage operations on uploaded files through the workflow role. + - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/ diff --git a/src/privilege-escalation-paths/aws/wickr.yaml b/src/privilege-escalation-paths/aws/wickr.yaml new file mode 100644 index 0000000000..177abd6e61 --- /dev/null +++ b/src/privilege-escalation-paths/aws/wickr.yaml @@ -0,0 +1,34 @@ +- id: aws-audit-reset-wickr-retention-bot-challenge-and-operate-bot + provider: aws + service: wickr + title: Reset Wickr retention-bot challenge and operate bot + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-wickr-privesc/README.md#wickrcreatedataretentionbotchallenge--take-over-the-data-retention-bot + source_revision: 0b36331 + summary: The source can authenticate bot and receive message/attachment copies only when the exact target and + prerequisites are verified. + requires: + all_of: + - action: wickr:CreateDataRetentionBotChallenge + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit-reset-wickr-retention-bot-challenge-and-operate-bot + scope: same_account + aggregate_as: Verified Authenticate bot and receive message/attachme in {account} + grants: + - Authenticate bot and receive message/attachment copies + conditions: + - id: exact_verified_prerequisites + description: 'Evidence must bind the source, exact target, and these prerequisites: Retention enabled; exact + network ARN; attacker operates compatible bot and captures returned challenge; enrollment may disrupt prior + bot.' + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed permissions to approved operators and review the exact target configuration. + notes: Evidence must bind actor, exact resource, target and all prerequisites; absent evidence is UNKNOWN, with + no definite privilege edge. + references: + - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-wickr-privesc/ diff --git a/src/privilege-escalation-paths/aws/workdocs.yaml b/src/privilege-escalation-paths/aws/workdocs.yaml new file mode 100644 index 0000000000..3b814214a5 --- /dev/null +++ b/src/privilege-escalation-paths/aws/workdocs.yaml @@ -0,0 +1,34 @@ +- id: aws-audit-promote-controlled-workdocs-user-to-administrator + provider: aws + service: workdocs + title: Promote controlled WorkDocs user to administrator + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocsupdateuser + source_revision: 0b36331 + summary: The source can gain WorkDocs administrator control panel only when the exact target and prerequisites + are verified. + requires: + all_of: + - action: workdocs:UpdateUser + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit-promote-controlled-workdocs-user-to-administrator + scope: same_account + aggregate_as: Verified Gain WorkDocs administrator control panel in {account} + grants: + - Gain WorkDocs administrator control panel + outcome: application_admin + conditions: + - id: exact_verified_prerequisites + description: 'Evidence must bind the source, exact target, and these prerequisites: Existing active user controlled + by source; UpdateUser sets Type=ADMIN on that user; site supports WorkDocs admin.' + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed permissions to approved operators and review the exact target configuration. + notes: Evidence must bind actor, exact resource, target and all prerequisites; absent evidence is UNKNOWN, with + no definite privilege edge. + references: + - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/ diff --git a/src/privilege-escalation-paths/aws/workspaces.yaml b/src/privilege-escalation-paths/aws/workspaces.yaml index 7ff01eb776..ba2d5e398c 100644 --- a/src/privilege-escalation-paths/aws/workspaces.yaml +++ b/src/privilege-escalation-paths/aws/workspaces.yaml @@ -6,16 +6,19 @@ 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. + source_revision: 0b36331 + 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: "*" + - action: workspaces-instances:CreateWorkspaceInstance + resource: '*' + - action: iam:PassRole + resource: '{target.arn}' + - action: ec2:RunInstances + resource: '*' + - action: ec2:DescribeImages + resource: '*' target: kind: aws_role selector: @@ -23,19 +26,25 @@ has_instance_profile: true resource_permission_covers_target: iam:PassRole scope: same_account - aggregate_as: "Instance-profile roles passable in {account}" + aggregate_as: Instance-profile roles passable in {account} 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. + - 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. + - id: runinstances_launch_resources + description: Check ec2:RunInstances on the exact AMI, subnet, security group, volume, network interface and + prospective instance; include aws:CalledVia, CreateTags, KMS and service-linked-role prerequisites where applicable. blockers: - - scp_or_boundary_deny + - scp_or_boundary_deny confidence: conditional severity: critical - mitigation: Restrict iam:PassRole on instance-profile roles and treat workspaces-instances:CreateWorkspaceInstance like ec2:RunInstances. + 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. + - 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. From 4e500f0141fd03e7b08322c735a067a861cdf646 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Mon, 12 Oct 2026 20:40:36 +0200 Subject: [PATCH 03/17] Integrate verified AWS post-exploitation catalog fragments Co-Authored-By: Codex --- .../_excluded_audit_pa_aws_post_1_s07.yaml | 221 ++++++++ .../aws/_excluded_b.yaml | 9 +- .../aws/_excluded_verify_a66f.yaml | 533 ++++++++++++------ .../aws/challenge-v3.yaml | 85 +-- .../aws/iotsitewise.yaml | 30 + src/privilege-escalation-paths/aws/ivs.yaml | 89 +++ .../aws/lakeformation.yaml | 37 ++ 7 files changed, 781 insertions(+), 223 deletions(-) create mode 100644 src/privilege-escalation-paths/aws/_excluded_audit_pa_aws_post_1_s07.yaml create mode 100644 src/privilege-escalation-paths/aws/iotsitewise.yaml create mode 100644 src/privilege-escalation-paths/aws/ivs.yaml create mode 100644 src/privilege-escalation-paths/aws/lakeformation.yaml diff --git a/src/privilege-escalation-paths/aws/_excluded_audit_pa_aws_post_1_s07.yaml b/src/privilege-escalation-paths/aws/_excluded_audit_pa_aws_post_1_s07.yaml new file mode 100644 index 0000000000..28a3864874 --- /dev/null +++ b/src/privilege-escalation-paths/aws/_excluded_audit_pa_aws_post_1_s07.yaml @@ -0,0 +1,221 @@ +# AWS post-exploitation catalog additions. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#trigger-an-existing-iot-device-management-command + technique: Trigger privileged stored device command + reason: The stored command must actually implement a privileged device operation; command payload/template, target + firmware behavior, and dynamic parameter acceptance are not established by IAM inventory. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#read-and-manipulate-iot-jobs-through-the-device-data-plane + technique: Read IoT Jobs document via DescribeJobExecution + reason: A queued job document must exist for the known thing and contain a reusable bootstrap credential or private + URL; job-document content is unavailable in configuration inventory. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#read-and-manipulate-iot-jobs-through-the-device-data-plane + technique: Read IoT Jobs document via StartNextPendingJobExecution + reason: A pending job must exist and its returned document must contain a usable credential; the call also mutates + execution state, which permissions alone do not establish. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#read-and-manipulate-iot-jobs-through-the-device-data-plane + technique: Read IoT Jobs document via UpdateJobExecution + reason: The known execution must accept the requested update and return a document with a usable credential; its + content and current state are runtime facts. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#receive-mqtt-telemetry-and-messages + technique: Read credentials carried by MQTT messages + reason: Matching live MQTT traffic must actually contain a reusable secret; topic authorization alone only grants + message read. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#open-a-managed-tunnel-to-a-device + technique: Open IoT tunnel to privileged device service + reason: An active destination agent and service mapping must expose a privileged device service; the port, device + behavior, and destination token delivery are runtime facts. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#publish-commands-or-forged-telemetry + technique: Publish commands to privileged device/automation consumer + reason: The subscribed device or automation must interpret attacker-published fields as a privileged instruction; + that handler/firmware behavior is not in the snapshot. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#iotcreatetopicrule--iampassrole--durable-fleet-wide-mqtt-exfiltration + technique: Create IoT HTTP topic rule without PassRole + reason: An HTTP topic rule only gains credentials if the selected traffic contains reusable secrets and a reachable + attacker sink accepts them; message content and sink behavior are runtime facts. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-core-post-exploitation/README.md#iotcreatetopicrule--iampassrole--durable-fleet-wide-mqtt-exfiltration + technique: Create IoT Lambda topic rule for fleet tap + reason: The Lambda rule action only gains credentials if traffic contains reusable secrets and the invoked function + sends them to an attacker-readable sink; code and traffic content need review. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-twinmaker-post-exploitation/README.md#entity-component-and-graph-disclosure + technique: Recover credentials embedded in TwinMaker static values + reason: TwinMaker entity/component static values must contain an actual reusable credential; the ordinary graph + inventory does not inspect or classify property contents. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-twinmaker-post-exploitation/README.md#entity-component-and-graph-disclosure + technique: Recover credential through TwinMaker ExecuteQuery + reason: ExecuteQuery results must include a usable secret rather than ordinary graph data; the exact query result + content needs inspection. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-twinmaker-post-exploitation/README.md#stealth-property-theft-through-a-configured-connector + technique: Read secrets through TwinMaker connector + reason: The configured connector must expose a credential-bearing external property to the caller; connector code, + backing data, and returned values need inspection. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-wireless-post-exploitation/README.md#firmware-and-group-delivery-abuse + technique: Deliver attacker firmware to gateway or device group + reason: A compatible device must install/execute the delivered firmware and expose a stronger device identity + or privilege; task permissions alone do not prove this host outcome. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kendra-post-exploitation/README.md#kendracreatedatasource--updatedatasource--iampassrole--poison-or-repoint-ingestion + technique: Create Kendra source that indexes connector-reachable credentials + reason: The connector role must reach credential-bearing repository content and indexing plus Query/Retrieve ACL + context must disclose it; repository bytes and ACL behavior are not in the snapshot. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-keyspaces-post-exploitation/README.md#exfiltrate-future-changes-through-cdc-without-table-select + technique: Read credentials through Keyspaces CDC + reason: Captured CDC images must contain reusable credentials; stream permission and capture mode alone do not + establish secret content. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kinesis-data-streams-post-exploitation/README.md#steal-retained-records-with-shared-throughput-reads + technique: Steal credentials from retained Kinesis records + reason: Retained Kinesis records must contain reusable credentials; read permission alone does not establish that + content. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kinesis-data-streams-post-exploitation/README.md#abuse-enhanced-fan-out + technique: Register and subscribe to credential-bearing stream + reason: Future subscribed stream records must contain reusable credentials; consumer registration only grants + authorized record delivery. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kinesis-data-streams-post-exploitation/README.md#inject-forged-records + technique: Trigger privileged Kinesis Lambda consumer with forged record + reason: The Lambda handler must treat forged Kinesis fields as authority for a privileged operation; mapping configuration + alone proves invocation, not misuse. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kinesis-data-streams-post-exploitation/README.md#inject-forged-records + technique: Trigger privileged Kinesis consumer with PutRecords + reason: A non-Lambda consumer must treat forged PutRecords fields as authority for a privileged operation; consumer + code and record processing require review. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kinesis-video-streams-post-exploitation/README.md#remap-webrtc-cloud-storage-without-destination-stream-permission + technique: Redirect WebRTC recording to readable KVS stream + reason: Future WebRTC recordings must be written to a stream the actor can read; the destination permissions, + active peers, and recorded content are not proven by update permission. + source_revision: 0b36331 +- 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: Join KVS signaling as master peer + reason: ConnectAsMaster permits a signaling connection, but another peer must accept the master identity and expose + a privileged operation or credential; channel authorization alone does not prove escalation. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kms-post-exploitation/README.md#derive-shared-secret + technique: Derive trusted ECDH shared secret + reason: The ECDH output must be accepted by a protocol as an authentication or decryption secret; peer protocol + state and traffic content are outside inventory. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kms-post-exploitation/README.md#nitro-enclaveskms-integration-attacks + technique: Bypass enclave binding by omitting Recipient + reason: A KMS key policy must allow a non-attested request when Recipient is omitted and a protected ciphertext + must be available; those exact request and content facts are unproven. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kms-post-exploitation/README.md#encryptdecrypt-information + technique: Decrypt protected credentials with KMS key + reason: The actor needs ciphertext encrypted under the usable KMS key and that plaintext must contain a reusable + credential; decrypt permission alone is ordinary authorized decryption. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-function-access-post-exploitation/README.md#invoke-a-lambda + technique: Invoke unsafe privileged Lambda with crafted payload + reason: The invoked function must have a handler branch that turns attacker-supplied payload into a privileged + operation; InvokeFunction permission alone proves only invocation. + source_revision: 0b36331 +- 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: Read Lambda version environment secret via ListVersionsByFunction + reason: A listed Lambda version must store a reusable credential in plaintext environment variables; that content + is not in the permission snapshot. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#aws-lambda--efs-mount-injection-data-exfiltration + technique: Mount EFS to read shared credentials + reason: The summary documents EFS mount injection, but the function must pass VPC/mount/role gates and the mounted + directory must contain a currently usable credential; file content is unavailable in inventory. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#steal-others-lambda-url-requests + technique: Steal request credentials from compromised warm Lambda + reason: A warm compromised runtime must later receive another user request carrying a reusable cookie or token; + neither runtime compromise nor future request content is a configuration fact. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#aws-lambda--event-source-mapping-target-hijack + technique: Redirect event source mapping to controlled function + reason: The summary documents mapping diversion, but the controlled receiver must poll the source and incoming + records must contain usable credentials or drive a privileged consumer behavior. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#aws-lambda--log-siphon-via-loggingconfigloggroup-redirection + technique: Redirect Lambda logs containing credentials + reason: Future function logs must contain usable credentials and be written to an attacker-readable group; log + content and timing cannot be inferred from the configuration write. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#lambda-durable-callback-result-injection + technique: Inject privileged durable callback failure + reason: A live callback ID must be known and the failure branch must perform a privileged action; the existing + success-branch catalog entry does not prove that behavior. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#aws-lambda--trigger-privileged-consumers-through-writable-event-sources + technique: Trigger unsafe Lambda consumer through SQS queue + reason: The SQS consumer handler must use attacker-controlled fields to perform a privileged operation; mapping + and SendMessage authorization prove only delivery. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#aws-lambda--trigger-privileged-consumers-through-writable-event-sources + technique: Trigger unsafe Lambda consumer through Kinesis stream + reason: The Kinesis consumer handler must use attacker-controlled fields to perform a privileged operation; mapping + and PutRecord authorization prove only delivery. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#aws-lambda--trigger-privileged-consumers-through-writable-event-sources + technique: Trigger unsafe Lambda consumer through DynamoDB table insert + reason: The DynamoDB stream handler must use the inserted item to perform a privileged operation; table writes + and mapping prove only delivery. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#aws-lambda--trigger-privileged-consumers-through-writable-event-sources + technique: Trigger unsafe Lambda consumer through DynamoDB table update + reason: The DynamoDB stream handler must use the updated item to perform a privileged operation; table writes + and mapping prove only delivery. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#aws-lambda--trigger-privileged-consumers-through-writable-event-sources + technique: Trigger unsafe Lambda consumer through CloudWatch Logs stream + reason: The log subscription consumer must use an injected log event to perform a privileged operation; PutLogEvents + proves only delivery. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/README.md#aws-lambda--trigger-privileged-consumers-through-writable-event-sources + technique: Trigger unsafe Lambda consumer through CloudWatch alarm metric + reason: The alarm target must use the manipulated metric/alarm transition to perform a privileged operation; metric + write alone proves no such branch. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lambda-post-exploitation/aws-lambda-loggingconfig-redirection.md#required-permissions + technique: Redirect Lambda logs to attacker-readable group + reason: The redirected group must receive future credential-bearing log events and be readable by the actor; the + written LoggingConfig does not prove secret content. + source_revision: 0b36331 +- 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: Trigger unsafe Lambda consumer through SQS queue + reason: The SQS consumer handler must use attacker-controlled fields to perform a privileged operation; the cited + discovery section states this precondition. + source_revision: 0b36331 +- 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: Trigger unsafe Lambda consumer through Kinesis stream + reason: The Kinesis consumer handler must use attacker-controlled fields to perform a privileged operation; the + cited discovery section states this precondition. + source_revision: 0b36331 +- 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: Trigger unsafe Lambda consumer through DynamoDB table insert + reason: The DynamoDB consumer handler must use an inserted item to perform a privileged operation; the cited discovery + section states this precondition. + source_revision: 0b36331 +- 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: Trigger unsafe Lambda consumer through DynamoDB table update + reason: The DynamoDB consumer handler must use an updated item to perform a privileged operation; the cited discovery + section states this precondition. + source_revision: 0b36331 +- 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: Trigger unsafe Lambda consumer through CloudWatch Logs stream + reason: The CloudWatch Logs consumer handler must use an injected event to perform a privileged operation; the + cited discovery section states this precondition. + source_revision: 0b36331 +- 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: Trigger unsafe Lambda consumer through CloudWatch alarm metric + reason: The alarm target must use attacker-influenced metric state to perform a privileged operation; the cited + discovery section states this precondition. + source_revision: 0b36331 diff --git a/src/privilege-escalation-paths/aws/_excluded_b.yaml b/src/privilege-escalation-paths/aws/_excluded_b.yaml index 14bb5923ee..8f225728f1 100644 --- a/src/privilege-escalation-paths/aws/_excluded_b.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_b.yaml @@ -134,11 +134,12 @@ source_revision: a53b46392c technique: route53domains:RetrieveDomainAuthCode reason: Domain transfer credential theft; external asset takeover, no IAM principal. -- source: - src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-secrets-manager-privesc/README.md#secretsmanagergetsecretvalue - source_revision: a53b46392c +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-secrets-manager-privesc/README.md#secretsmanagergetsecretvalue + source_revision: 0b36331 technique: secretsmanager:GetSecretValue - reason: Data read; any IAM keys stored in secrets are not modelable from the control plane. + reason: GetSecretValue can reveal plaintext AWS or external credentials, but an exact secret must contain a still-valid + credential mapped to its owner; control-plane secret metadata cannot prove this. Keep a scoped exclusion pending + content evidence, rather than declaring all reads data-only. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-workdocs-privesc/README.md#workdocscreateuser source_revision: a53b46392c technique: workdocs:CreateUser diff --git a/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml b/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml index ba2d88213e..062593fc4a 100644 --- a/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml @@ -1433,11 +1433,6 @@ 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 @@ -1575,55 +1570,41 @@ 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 + reason: The document read can disclose a bootstrap token, but a specific readable job document must contain a + currently usable token or private bearer URL; configuration does not establish content. + source_revision: 0b36331 - 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 + reason: Rotation returns a tunnel bearer token, but privileged device access requires a live tunnel, SOURCE token + acceptance, and an actual privileged service behind its mapping. + source_revision: 0b36331 - 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 + reason: The rule can capture secrets, but a matching future MQTT message must contain a usable credential and + the configured destination must be attacker-readable; the rule write alone proves neither. + source_revision: 0b36331 - 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 + reason: Kendra ingestion may expose repository credentials, but the connector must reach such content and Query/Retrieve + with the supplied user context must reveal it; PassRole is not connector-role impersonation. + source_revision: 0b36331 - 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 + reason: The mapping changes Kendra ACL group resolution, but a controlled querying identity, matching allowed + documents, and absence of a DENY ACL are needed to prove added content privilege. + source_revision: 0b36331 - 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 + reason: A selected Keyspaces row may contain a reusable token, but table contents and token validity are not established + by cassandra:Select alone. + source_revision: 0b36331 - 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 + reason: A blind write can take over an application session only when the targeted row is security-sensitive and + the application trusts its new value; schema and handler behavior require inspection. + source_revision: 0b36331 - 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 @@ -1632,10 +1613,9 @@ 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 + reason: kms:Sign produces a valid signature, but impersonation needs a verifier that trusts this key for an authorization + assertion and accepts the attacker-chosen message and algorithm. + source_revision: 0b36331 - 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, @@ -1644,48 +1624,45 @@ 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 + reason: Adding a controlled DataLakeAdmins principal grants Lake Formation administration, but a principal the + actor controls and an accepted regional settings replacement must be established; data access needs further + IAM and engine rights. + source_revision: 0b36331 - 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 + reason: Self-grant can increase LF permissions, but the caller must have LF administrator or matching grant-option + authority and the specific Glue resource must be eligible; data reads need separate gates. + source_revision: 0b36331 - 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 + reason: GetDataAccess can vend scoped S3 credentials, but an authorized external-engine session, registered table, + matching LF grant and permission type, and usable path are required. + source_revision: 0b36331 - 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 + reason: An existing named expression must be referenced by a grant to a controlled principal and the replacement + tags must cover newly sensitive resources; LF grant-option checks also apply. + source_revision: 0b36331 - 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 + reason: A Glue catalog policy can grant an external principal new metadata authority, but the exact external identity + must be actor-controlled and its identity policy plus LF checks must permit the target APIs. + source_revision: 0b36331 - 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 + reason: ListFunctions or ListVersionsByFunction can disclose credentials only when a returned environment variable + contains a currently reusable secret; endpoints or ordinary configuration are not escalation. + source_revision: 0b36331 - 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 + reason: The token grants access to a MicroVM port, but escalation needs a live admin/debug listener that accepts + it and performs a stronger operation; port configuration and handler behavior are runtime facts. + source_revision: 0b36331 - 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 + reason: History read may expose a secret or live callback ID, but a specific execution must retain a reusable + credential or pending callback; ordinary workflow data is not escalation. + source_revision: 0b36331 - 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 @@ -1708,23 +1685,19 @@ 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 + reason: EFS injection reaches files only when VPC, mount, POSIX and execution-role gates pass and the mounted + directory contains a usable credential; file content is not inventory. + source_revision: 0b36331 - 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 + reason: A new mapping triggers an unchanged function, but escalation needs compatible source polling and a handler + whose fixed behavior performs a privileged action on the arriving record. + source_revision: 0b36331 - 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 + reason: A redirected mapping diverts source records, but escalation requires a controlled receiver able to poll + and records with usable credentials or other privileged content. + source_revision: 0b36331 - 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 @@ -1760,9 +1733,12 @@ - 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.' + reason: 'Macie reveal can expose plaintext credentials from a finding, including an S3 object the requester cannot + read directly when ASSUME_ROLE is configured. GetSensitiveDataOccurrences alone proves neither a credential + nor a new identity: the finding and detailed result must contain a still-usable secret, the reveal role must + be able to read that object, and the requester needs the reveal-key KMS permissions. Changing the reveal configuration + additionally requires UpdateRevealConfiguration and PassRole. These finding-content, role-use and credential-validity + facts are not established by the snapshot.' 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 @@ -1811,9 +1787,11 @@ 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. + reason: PutDeploymentParameter changes a seller-owned product parameter for a buyer agreement. Credential interception + or vendor impersonation is conditional on the exact Quick Launch template or product integration consuming an + attacker-controlled endpoint or credential, later buyer traffic, and a usable intercepted credential. Seller + write permission alone proves parameter tampering, not a new buyer identity; these integration and runtime facts + are not in the snapshot. 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' @@ -1840,33 +1818,40 @@ 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.' + reason: memorydb:Connect directly authorizes IAM authentication as a named IAM-enabled MemoryDB ACL user, with + authorization required on both the cluster and user ARN. It does not by itself yield another AWS principal or + a reusable secret; effective data-plane access also needs the user attached to the cluster ACL, an allowed network + route and commands permitted by the access string. Any downstream credential gain depends on exact key contents + and credential validity, which the snapshot cannot establish. 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.' + reason: CopySnapshot can export the MemoryDB dataset to S3 without a cluster route or ACL password. Exported keys + may contain session tokens or application credentials, but no target identity follows from CopySnapshot permission + alone. The exact RDB contents, a usable credential and downstream acceptance are needed; snapshot existence + or CreateSnapshot permission and an export-compatible bucket are separate prerequisites. 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.' + reason: Changing a MemoryDB cluster to the open-access ACL can remove its data-plane authentication boundary, + but UpdateCluster permission alone does not prove a reachable cluster or a newly gained identity. The service-linked + role must exist, the ACL change must be accepted, and the attacker needs a VPC route and admitted security group. + Security-group-only replacement does not bypass the ACL. Any downstream credential gain also depends on cluster + data contents and validity; these reachability and content facts are absent from the snapshot. 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.' + reason: ReadDataViaQuery is direct IAM-authorized Neptune data reading when DB IAM authentication and network + reachability permit it. A separate identity is gained only if an exact returned graph property contains a still-usable + credential accepted by that identity. Graph content, credential validity and endpoint reachability are not established + by the configuration snapshot. 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.' + reason: GetStreamRecords can read retained Neptune graph changes when Streams is enabled and the endpoint is reachable. + A separate identity is gained only if a retained record contains a credential that is still usable after the + change. Record contents, retention, credential validity and endpoint reachability are not established by the + configuration snapshot. 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` @@ -1935,8 +1920,10 @@ 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.' + reason: CreateAutonomousDatabaseWallet returns fresh mTLS client material, but the wallet alone does not authenticate + as an Oracle database user. A separate valid Oracle username/password or other authentication path, database + reachability, and successful wallet generation are needed; customer-managed-secret mode can also require PassRole. + These held-credential and network facts are absent from the snapshot. 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' @@ -1964,11 +1951,6 @@ 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 @@ -1989,32 +1971,38 @@ 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. + reason: Session messages or spans might contain a live reusable secret, but the snapshot has no message/span contents, + secret validity, or target identity binding. A ListMessages/ListSpans allow alone proves only conversation read; + an exact credential-content collector would be needed and must leave missing content UNKNOWN. 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. + reason: RDS Proxy backend Secrets Manager auth secrets contain a database username/password, so a DB identity + can be gained. Current schema has no database-user target or proxy-auth secret binding. Add aws_database_user + and bind DescribeDBProxies Auth.SecretArn to the exact backend user; collect DescribeDBProxies and DescribeDBProxyTargets + (IAM rds:DescribeDBProxies, rds:DescribeDBProxyTargets), snapshot key rds_proxy_auth {proxy_arn,secret_arn,db_user,target_db_arn}; + UNKNOWN until collected and GetSecretValue/KMS rights are resolved. 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.' + reason: Downloaded engine logs may contain live reusable credentials, but this requires actual runtime log content, + secret validity, and the mapped target identity. Without content evidence, DownloadDBLogFilePortion is only + log read; evaluate UNKNOWN if a credential-content collector is later added. 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.' + reason: Blue/green plus ModifyDBInstance can reset the green master password, creating access as a database user; + current graph has no aws_database_user target or clone-to-master binding. Add that target and collect DescribeBlueGreenDeployments + plus DescribeDBInstances (IAM rds:DescribeBlueGreenDeployments, rds:DescribeDBInstances), snapshot key rds_blue_green + {deployment_arn,source_db_arn,green_db_arn,master_user,managed_password}; UNKNOWN without eligible deployment + and resettable green instance. 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.' + reason: Snapshot restore plus ModifyDBInstance can set the restored instance master password and obtain its DB + identity. Add aws_database_user target and snapshot-restored-DB binding; collect DescribeDBSnapshots and DescribeDBInstances + (IAM rds:DescribeDBSnapshots, rds:DescribeDBInstances), snapshot key rds_restorable_snapshots {snapshot_arn,source_db_arn,engine,restorable} + and rds_db_instances {db_arn,master_user,managed_password}. Missing backup or reachability is UNKNOWN. source_revision: a66f094ede - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsrestore technique: '`rds:Restore*`' @@ -2047,15 +2035,18 @@ 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.' + reason: Cross-Region backup replication and point-in-time restore can yield a new DB master identity only with + a subsequent ModifyDBInstance password reset. Add aws_database_user target and replicated-backup-to-restored-instance + binding; collect DescribeDBInstanceAutomatedBackups in destination Region and DescribeDBInstances (IAM rds:DescribeDBInstanceAutomatedBackups, + rds:DescribeDBInstances), snapshot key rds_replicated_backups {source_db_arn,destination_region,backup_arn,restorable,master_user}. + Missing destination inventory is UNKNOWN. 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.' + reason: Read-replica creation plus ModifyDBInstance can give access as the replica master DB user if engine/version + permits credential reset. Add aws_database_user target and source-to-replica binding; collect DescribeDBInstances + (IAM rds:DescribeDBInstances), snapshot key rds_replica_candidates {source_db_arn,engine,replica_supported,master_user,managed_password}. + Missing eligibility or network path is UNKNOWN. 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) @@ -2081,9 +2072,9 @@ 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.' + reason: Most auxiliary rds:Modify* calls only change configuration; ModifyDBInstance or ModifyDBCluster with a + resettable master password can confer the database master identity. Model these two concrete actions under aws_database_user + with a database/master binding and viable login path; do not infer a generic Modify* privilege edge. 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' @@ -2110,9 +2101,11 @@ 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. + reason: Route creation can forward HTTP headers and bodies to an attacker endpoint. It becomes credential escalation + only if intercepted runtime traffic contains a live reusable bearer token mapped to another application principal. + Existing environment/application ownership, healthy endpoint, and exact path/method match are also required; + the configuration snapshot alone cannot prove token content, so keep this excluded until content evidence is + collected. 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' @@ -2157,9 +2150,10 @@ 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 + reason: The API returns a reusable DNS bearer token. Its exact view and validity must be joined to a target Global + Resolver service identity; no DNS-view token target kind or token-to-view binding is currently evaluated. A + different IAM principal is not required for the disclosed credential to matter. + source_revision: 0b36331 - 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 @@ -2226,16 +2220,10 @@ 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 + reason: RestoreObject only makes an archived object temporarily readable. A separate GetObject grant (and KMS + decrypt when applicable), a live credential in that object, and its owner are required; restoration alone gains + no identity. + source_revision: 0b36331 - 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 @@ -2244,10 +2232,10 @@ 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 + reason: PutBucketWebsite affects only traffic through the S3 website endpoint or a website-origin distribution. + Credential gain further requires a later visitor to put a usable token in a redirected URL and an exact account + binding; REST/OAC origins ignore this configuration. + source_revision: 0b36331 - 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 @@ -2257,21 +2245,20 @@ - 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 + reason: DescribeAppImageConfig or ListAppImageConfigs can return plaintext container environment variables. Identity + gain requires a live credential in an exact config and a mapped owner; endpoints and ordinary settings alone + are not credentials. + source_revision: 0b36331 - 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 + reason: DescribeModel returns plaintext container Environment values, which can contain a live application credential. + It does not disclose the model execution-role credential; an exact value-to-identity and validity check is needed. + source_revision: 0b36331 - 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 + reason: DescribeTrainingJob returns plaintext Environment and HyperParameters values. Only a live credential bound + to a specific identity would be an escalation; job metadata alone is not. + source_revision: 0b36331 - 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 @@ -2307,16 +2294,16 @@ 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 + reason: ListActorMessages can reveal a live OTP or verification link, but the attacker must also possess the primary + credential or session and redeem the token within the 24-hour retention and application validity window. Message + metadata cannot prove takeover. + source_revision: 0b36331 - 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 + reason: GetArtifact or BatchGetFindings can return authentication environment values or a usable script URL. Only + exact still-valid values mapped to an application or repository identity would escalate; architecture and exploit + notes alone do not. + source_revision: 0b36331 - 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 @@ -2331,9 +2318,10 @@ 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 + reason: CreateSubscriber can create an assumable S3 subscriber role for another account, while UpdateSubscriber + can reassign an existing subscriber; this is delegated data access. The exact generated role/share, prerequisites, + external-ID trust, source scope and consuming account must be resolved before emitting a principal edge. + source_revision: 0b36331 - 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 @@ -2386,11 +2374,10 @@ 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 + reason: A policy on a verified SES identity can delegate SendEmail/SendRawEmail to an attacker account. This gains + the identity-specific sending privilege, although it does not grant IAM identity impersonation. The catalog + needs an SES sending-identity target and verified-identity/policy join. + source_revision: 0b36331 - 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 @@ -3084,3 +3071,183 @@ reason: A returned EMR configuration or Kerberos field must contain a live reusable credential for a distinct identity; cluster metadata and describe permission alone cannot prove its value or owner. source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-gamelift-streams-post-exploitation/README.md#export-all-modified-session-files + technique: Export session files containing credentials + reason: The exported ZIP may contain credentials, but file contents, credential validity and readable S3 output + are runtime facts; configuration alone cannot identify a gained account. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-gamelift-streams-post-exploitation/README.md#recover-bearer-stream-urls-and-frozen-session-configuration + technique: Recover an active bearer stream URL + reason: A stream URL gives access to an application session, but the page does not establish a stronger logged-in + identity; remaining uses, expiry and application login are runtime facts. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-gamelift-streams-post-exploitation/README.md#recover-bearer-stream-urls-and-frozen-session-configuration + technique: Recover credential in stream URL environment or arguments + reason: Environment variables or arguments may contain secrets; the exact value and successful external authentication + require content inspection and live validation. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-gamelift-streams-post-exploitation/README.md#recover-stream-session-arguments-signaling-data-and-destinations + technique: Recover session environment or argument secret + reason: Session parameters may expose a secret, but neither a credential nor its acceptance by a destination is + established by configuration. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-glue-post-exploitation/README.md#read-secrets-accidentally-placed-in-jobs-and-workflows + technique: Read embedded job or workflow secrets + reason: Job and workflow arguments only sometimes contain secrets; identifying a target account and whether the + value works requires content inspection and destination authentication. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-glue-post-exploitation/README.md#read-stored-connection-credentials + technique: Read a Glue connection password + reason: GetConnection can expose a stored password, but whether it is present, current and accepted by a reachable + JDBC or SaaS endpoint is a runtime fact. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-greengrass-post-exploitation/README.md#related-iot-device-fleet-primitives-same-archetype + technique: IoT Managed Integrations OTA task + reason: CreateOtaTask schedules firmware; code execution depends on image content, device download, verification + and installation, and no specific stronger device identity is established. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-greengrass-post-exploitation/README.md#related-iot-device-fleet-primitives-same-archetype + technique: IoT Wireless firmware task on gateways + reason: Gateway task creation is not proof that attacker firmware is accepted and executed on a particular gateway; + firmware content and device state are required. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-healthomics-post-exploitation/README.md#export-private-workflow-source-and-run-secrets + technique: Recover run parameter or task-log secret + reason: A GetRun response or task log may contain a secret; the actual content, target identity and current validity + are runtime facts. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-healthomics-post-exploitation/README.md#export-private-workflow-source-and-run-secrets + technique: Recover secret embedded in private workflow export + reason: A workflow export is source disclosure; an embedded usable credential is contingent on source content + and external acceptance. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-healthomics-post-exploitation/README.md#poison-or-destroy-genomic-and-workflow-state + technique: Plant a workflow version executed later with a stronger role + reason: Creating a version only plants content. Escalation depends on later selection by another operator, executable + content and execution under a stronger run role. + source_revision: 0b36331 +- 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: Redirect procurement connection to attacker endpoint + reason: PutProcurementPortalPreference changes configuration, but portal verification, connection testing and + receipt of an accepted integration identity depend on external runtime workflow; no credential transfer follows + from the write alone. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lex-v2-post-exploitation/README.md#read-or-poison-another-runtime-session + technique: Poison another Lex runtime session to impersonate application workflow authority + reason: PutSession can impersonate victim workflow authority only if a victim session ID is known or predictable + and application code trusts attacker-set session attributes as authorization. Those runtime and code facts are + absent from an AWS configuration snapshot; GetSession alone reads data and DeleteSession disrupts availability. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-managed-flink-post-exploitation/README.md#read-current-and-historical-runtime-secrets + technique: Read Flink current or historical runtime secrets + reason: DescribeApplication and DescribeApplicationVersion can reveal current or historical property values, but + the snapshot cannot establish that a particular value is a still-usable credential for an identity the reader + does not already hold. This requires the returned property content and downstream credential validation; application + read permission alone proves disclosure, not a privilege edge. + source_revision: 0b36331174 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-managed-flink-post-exploitation/README.md#retrieve-and-inspect-application-code-and-dependencies + technique: Recover credentials embedded in Flink artifact + reason: Reading a Flink code artifact with s3:GetObject exposes bytes, not necessarily another identity. A privilege + edge requires the exact retained JAR or dependency to contain a credential and proof that the credential still + authenticates; these are artifact-content and downstream runtime facts absent from the configuration snapshot. + source_revision: 0b36331174 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-marketplace-post-exploitation/README.md#marketplace + technique: Redeem SaaS registration token from Marketplace agreement + reason: GetAgreementEntitlements may return a SaaS registration token, but a privilege edge requires a current + unredeemed token for the exact agreement and proof that the seller onboarding endpoint accepts it as a separate + buyer identity. Token issuance, 30-minute validity and seller-side redemption state are runtime facts absent + from the snapshot. + source_revision: 0b36331174 +- 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: Harvest collector non-AWS administration credentials + reason: The section begins with local root, Docker or equivalent access to the configured collector, rather than + a Strategy Recommendations IAM permission. A separate vCenter, OS or repository identity is gained only if local + files contain a still-valid credential; host access, file contents and downstream acceptance are not in the + AWS configuration snapshot. The distinct collector AWS-key case is aws-v3-11-harvest-the-strategy-recommendations-collector-aws-keys. + source_revision: 0b36331174 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-migration-hub-strategy-recommendations-post-exploitation/README.md#abuse-captured-collector-aws-credentials + technique: Read database credentials from collector-reachable secrets + reason: The migrationhub-strategy-* secret prefix and secretsmanager:GetSecretValue allow a read, but do not establish + that a specific secret holds a usable database credential or which database identity it represents. The secret + payload, any KMS grant and database acceptance are exact content/runtime facts; aws-v3-11-harvest-the-strategy-recommendations-collector-aws-keys + covers only the earlier collector-key theft. + source_revision: 0b36331174 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mwaa-post-exploitation/README.md#mwaa-serverless-sensitive-workflow-reads + technique: Recover secret from MWAA Serverless workflow definition + reason: GetWorkflow returns a workflow definition and code locations; it does not guarantee an embedded credential + or role-derived authorization. The exact definition content, credential validity and target identity would be + needed to infer a privilege edge. + source_revision: 0b36331174 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mwaa-post-exploitation/README.md#mwaa-serverless-sensitive-workflow-reads + technique: Recover secret from MWAA Serverless run override parameters + reason: GetWorkflowRun returns run override parameters, but a run may have no credential-bearing override. The + exact run response, a still-usable credential and its target identity are content/runtime facts absent from + the configuration snapshot. + source_revision: 0b36331174 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-mwaa-post-exploitation/README.md#mwaa-serverless-sensitive-workflow-reads + technique: Recover secret from MWAA Serverless task XCom + reason: GetTaskInstance can expose task XCom values, but XCom may contain ordinary results or unusable tokens. + The exact task response, credential validity and identity that accepts it are content/runtime facts absent from + the configuration snapshot. + source_revision: 0b36331174 +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#enable-full-sql-logging-via-db-parameter-groups-and-exfiltrate-via-rds-log-apis + technique: Enable full SQL logging via DB parameter groups and exfiltrate via RDS log APIs + reason: SQL-log theft would become credential escalation only if future engine log contents actually contain a + live reusable credential for a distinct database, application, or cloud identity. The configuration snapshot + cannot establish that runtime log content, validity, or principal mapping; ModifyDBParameterGroup plus DownloadDBLogFilePortion + alone proves data access. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-route53-dns-takeover-post-exploitation/README.md#cross-service-interception-of-a-fixed-privileged-http-consumer + source_revision: 0b36331 + technique: Cross-service interception of a fixed privileged HTTP consumer + reason: DNS control can expose a credential only if a particular privileged HTTP client later resolves the changed + name and sends reusable authentication material without independently validated TLS. The page names no client, + credential, or authenticated channel; DNS records alone cannot establish this path. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#sensitive-information + source_revision: 0b36331 + technique: Sensitive Information + reason: The page gives Terraform state secrets only as an example. A specific readable object must contain a still-valid + credential and its owner must be identified from content; S3 object metadata and s3:GetObject permission cannot + establish that binding. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-s3-post-exploitation/README.md#pivoting + source_revision: 0b36331 + technique: Pivoting + reason: The Airflow/MWAA DAG branch is covered by aws-mwaa-s3-putobject-dag, with other exact S3 code consumers + covered by aws-sagemaker-s3-putobject-job-code, aws-glue-s3-putobject-job-script, aws-codebuild-s3-source-poisoning + and aws-s3-putobject-ec2-userdata-object. The remaining browser-session branch needs the exact script-to-site + binding, a later authenticated browser load, and a usable session; a generic writable bucket does not identify + a target user. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-secrets-manager-post-exploitation/README.md#read-secrets + source_revision: 0b36331 + technique: Read Secrets + reason: GetSecretValue reveals an identity only when the exact secret contains a live credential and the credential + owner is known. Secret metadata does not prove content or validity; a customer-managed KMS key may also require + kms:Decrypt. The page does not identify a fixed target. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-secrets-manager-post-exploitation/README.md#mass-secret-exfiltration-via-batchgetsecretvalue-up-to-20-per-call + source_revision: 0b36331 + technique: Mass Secret Exfiltration via BatchGetSecretValue (up to 20 per call) + reason: BatchGetSecretValue expands secret reads but does not identify a credential holder. Each returned secret + must contain a live credential mapped to a target; filters additionally require ListSecrets, and customer-managed + keys can require kms:Decrypt. Secret metadata alone is insufficient. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-security-incident-response-post-exploitation/README.md#download-or-poison-forensic-attachments-without-direct-s3-permission + source_revision: 0b36331 + technique: Download or poison forensic attachments without direct S3 permission + reason: The attachment download URL grants evidence access, not an identity by itself. A specific forensic attachment + would need to contain a still-valid credential and identify its holder; upload only poisons evidence. Attachment + metadata does not prove this. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#bulk-exfiltration-of-a-mail-manager-archive + source_revision: 0b36331 + technique: Bulk exfiltration of a Mail Manager archive + reason: Archive search/content reads expose mail, but account takeover requires an actual retained message with + a still-valid credential or recovery token and its associated application account. An archive inventory does + not establish either fact; export also needs an attacker-readable destination. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#inbound-email-interception-with-receipt-rules + source_revision: 0b36331 + technique: Inbound email interception with receipt rules + reason: Receipt-rule interception can yield an account only if the targeted SES receiving path is active, a later + message contains a usable recovery token, and that token redeems for a named account. A rule and bucket policy + alone do not establish the future message or token validity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ses-post-exploitation/README.md#inbound-email-interception-with-mail-manager-rule-sets + source_revision: 0b36331 + technique: Inbound email interception with Mail Manager rule sets + reason: A Mail Manager rule-set change can yield an account only if a target ingress point uses that rule set, + the exfiltration destination receives a later message with a usable token, and that token redeems for a named + account. Configuration alone cannot prove the future content or redemption. diff --git a/src/privilege-escalation-paths/aws/challenge-v3.yaml b/src/privilege-escalation-paths/aws/challenge-v3.yaml index aa62f518dc..135116b1c5 100644 --- a/src/privilege-escalation-paths/aws/challenge-v3.yaml +++ b/src/privilege-escalation-paths/aws/challenge-v3.yaml @@ -404,33 +404,42 @@ provider: aws service: lex title: Trigger privileged business actions through a Lex fulfillment hook - source: - src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lex-v2-post-exploitation/README.md#abuse-an-existing-code-hook-through-runtime-access - summary: Lex runtime call -> exact configured hook role, conditional on a verified privileged intent/slot behavior. - Exact source, target and prerequisite proof are required. + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lex-v2-post-exploitation/README.md#abuse-an-existing-code-hook-through-runtime-access + summary: A Lex runtime request can reach a verified privileged business action exposed by an existing fulfillment + hook; it does not grant arbitrary Lambda role access. requires: - all_of: - - action: lex:RecognizeText - resource: '*' + any_of: + - - action: lex:RecognizeText + resource: '{target.resource_arn}' + - - action: lex:RecognizeUtterance + resource: '{target.resource_arn}' + - - action: lex:PutSession + resource: '{target.resource_arn}' + - - action: lex:StartConversation + resource: '{target.resource_arn}' target: kind: aws_verified_authority selector: aws_challenge_fact: aws-v3-14-trigger-privileged-business-actions-through-a-lex-fulfi scope: same_account - aggregate_as: Verified Trigger privileged business actions through a Lex fulfillment hook targets in {account} + aggregate_as: Verified privileged Lex hook actions in {account} grants: - - exact configured hook role, conditional on a verified privileged intent/slot behavior. + - Only the business action verified for the exact bot alias, intent, and slot path conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; A - hook invocation without application authorization analysis is no principal edge. + description: Evidence must bind the acting IAM principal, exact bot-alias ARN, reachable intent and slot values, + configured fulfillment hook, and missing or bypassable application authorization. The hook execution role + is not directly controlled. blockers: - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is - UNKNOWN/unresolved; verified evidence never creates a definite path. + mitigation: Restrict Lex runtime actions to the required bot aliases and authorize each privileged fulfillment + action in the application. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence + is UNKNOWN/unresolved; verified evidence never creates a definite path. + references: + - https://docs.aws.amazon.com/lexv2/latest/APIReference/welcome.html - id: aws-v3-15-replay-a-victim-application-session-recovered-from-waf provider: aws service: logs @@ -1993,14 +2002,12 @@ provider: aws service: evs title: EVS connector secret - source: - src/pentesting-cloud/aws-security/aws-post-exploitation/aws-evs-post-exploitation/README.md#recover-connector-credentials-for-an-existing-vcf-appliance - summary: 'Add `service_plane: evs-vmware-appliance` and exact environment/appliance account selector; require `evs:GetEnvironment` - or service credential-read action plus `secretsmanager:GetSecretValue` on exact linked secret. Exact source, target and - prerequisite proof are required.' + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-evs-post-exploitation/README.md#recover-connector-credentials-for-an-existing-vcf-appliance + summary: Read the exact connector secret ARN returned for an EVS environment and recover the connector appliance + account. requires: all_of: - - action: evs:GetEnvironment + - action: evs:ListEnvironmentConnectors resource: '*' - action: secretsmanager:GetSecretValue resource: '*' @@ -2011,18 +2018,18 @@ scope: same_account aggregate_as: Verified EVS connector secret targets in {account} grants: - - 'Add `service_plane: evs-vmware-appliance` and exact environment/appliance account selector' + - Exact VCF connector account privileges, never assumed VMware administrator conditions: - - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - Same exact connector account/secret join, without inferring VMware admin from connector credentials. + - id: connector_secret + description: Join environment, connector, FQDN and secret ARN; require kms:Decrypt for a customer key, a valid + secret and appliance network access. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is - UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence + is UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-68-firewall-manager-admin-action provider: aws service: fms @@ -2090,15 +2097,20 @@ provider: aws service: inspector2 title: Inspector delegated administrator - source: - src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2disabledelegatedadminaccount-inspector2enabledelegatedadminaccount--organizationslistdelegatedadministrators--organizationsenableawsserviceaccess--iamcreateservicelinkedrole - summary: Add exact organization-delegate service-plane target (`fms`, `network-security-manager`, `inspector2`) scoped - to a **controlled member account**; require row-specific delegate action. Exact source, target and prerequisite + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-inspector-post-exploitation/README.md#inspector2disabledelegatedadminaccount-inspector2enabledelegatedadminaccount--organizationslistdelegatedadministrators--organizationsenableawsserviceaccess--iamcreateservicelinkedrole + summary: Add exact organization-delegate service-plane target (`fms`, `network-security-manager`, `inspector2`) + scoped to a **controlled member account**; require row-specific delegate action. Exact source, target and prerequisite proof are required. requires: all_of: - action: inspector2:EnableDelegatedAdminAccount resource: '*' + - action: organizations:ListDelegatedAdministrators + resource: '*' + - action: organizations:EnableAWSServiceAccess + resource: '*' + - action: iam:CreateServiceLinkedRole + resource: '*' target: kind: aws_verified_authority selector: @@ -2106,18 +2118,19 @@ scope: same_account aggregate_as: Verified Inspector delegated administrator targets in {account} grants: - - Add exact organization-delegate service-plane target (`fms`, `network-security-manager`, ` + - Inspector delegated administration from the controlled member account conditions: - - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - Controlled member account, trusted access and actual Inspector delegate state. + - id: exact_delegate + description: Caller is in the Organizations management account; target is a controlled eligible member. If another + delegate exists, organizations:DeregisterDelegatedAdministrator is additionally required. Trusted access and + service-linked role state must be checked. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is - UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence + is UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-71-workmail-resetpassword provider: aws service: workmail diff --git a/src/privilege-escalation-paths/aws/iotsitewise.yaml b/src/privilege-escalation-paths/aws/iotsitewise.yaml new file mode 100644 index 0000000000..83404d0eb8 --- /dev/null +++ b/src/privilege-escalation-paths/aws/iotsitewise.yaml @@ -0,0 +1,30 @@ +# AWS post-exploitation catalog additions. +- id: aws-audit-site-grant-yourself-access-to-a-legacy-sitewi-ec31fb70 + provider: aws + service: iotsitewise + title: Widen existing SiteWise Monitor policy + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-sitewise-post-exploitation/README.md#grant-yourself-access-to-a-legacy-sitewise-monitor-portal + summary: SiteWise Monitor portal or project ADMINISTRATOR access + requires: + all_of: + - action: iotsitewise:UpdateAccessPolicy + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit-site-grant-yourself-access-to-a-legacy-sitewi-ec31fb70 + scope: same_account + aggregate_as: Verified Widen existing SiteWise Monitor policy in {account} + grants: + - SiteWise Monitor portal or project ADMINISTRATOR access + conditions: + - id: exact_verified_prerequisites + description: Legacy enrolled account, existing portal/project policy, controlled identity, administrator grant. + confidence: conditional + severity: high + mitigation: Restrict the stated action to approved principals and exact resources. + source_revision: 0b36331 + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-iot-sitewise-post-exploitation/README.md + notes: 'Draft only: exact evidence must bind the UpdateAccessPolicy action, acting principal, target policy, and + controlled identity. Missing fact must evaluate UNKNOWN.' diff --git a/src/privilege-escalation-paths/aws/ivs.yaml b/src/privilege-escalation-paths/aws/ivs.yaml new file mode 100644 index 0000000000..1fedc6db47 --- /dev/null +++ b/src/privilege-escalation-paths/aws/ivs.yaml @@ -0,0 +1,89 @@ +# AWS post-exploitation catalog additions. +- id: aws-audit-ivs-recover-publishing-and-playback-capabilit-997dd8c9 + provider: aws + service: ivs + title: Recover IVS low-latency stream publishing key + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#recover-publishing-and-playback-capabilities + summary: IVS channel publishing bearer identity + requires: + all_of: + - action: ivs:GetStreamKey + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit-ivs-recover-publishing-and-playback-capabilit-997dd8c9 + scope: same_account + aggregate_as: Verified Recover IVS low-latency stream publishing key in {account} + grants: + - IVS channel publishing bearer identity + conditions: + - id: exact_verified_prerequisites + description: Exact key ARN; live key and associated channel endpoint; GetChannel can disclose SRT passphrase + separately. + confidence: conditional + severity: high + mitigation: Restrict the stated action to approved principals and exact resources. + source_revision: 0b36331 + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md + notes: 'Draft only: exact evidence must bind actor, target and prerequisite facts. Missing fact must evaluate + UNKNOWN; no definite edge follows from IAM permissions alone.' +- id: aws-audit-ivs-recover-publishing-and-playback-capabilit-fd578249 + provider: aws + service: ivs + title: Recover IVS secure SRT passphrase + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#recover-publishing-and-playback-capabilities + summary: IVS channel secure-publishing capability + requires: + all_of: + - action: ivs:GetChannel + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit-ivs-recover-publishing-and-playback-capabilit-fd578249 + scope: same_account + aggregate_as: Verified Recover IVS secure SRT passphrase in {account} + grants: + - IVS channel secure-publishing capability + conditions: + - id: exact_verified_prerequisites + description: Channel configured for secure SRT and returned usable passphrase. + confidence: conditional + severity: high + mitigation: Restrict the stated action to approved principals and exact resources. + source_revision: 0b36331 + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md + notes: 'Draft only: exact evidence must bind actor, target and prerequisite facts. Missing fact must evaluate + UNKNOWN; no definite edge follows from IAM permissions alone.' +- id: aws-audit-ivs-recover-publishing-and-playback-capabilit-7128f3c7 + provider: aws + service: ivs + title: Recover IVS real-time ingest credentials + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md#recover-publishing-and-playback-capabilities + summary: IVS real-time stage ingest identity + requires: + all_of: + - action: ivs:GetIngestConfiguration + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit-ivs-recover-publishing-and-playback-capabilit-7128f3c7 + scope: same_account + aggregate_as: Verified Recover IVS real-time ingest credentials in {account} + grants: + - IVS real-time stage ingest identity + conditions: + - id: exact_verified_prerequisites + description: Exact ingest configuration with active RTMP(S) key and stage endpoint. + confidence: conditional + severity: high + mitigation: Restrict the stated action to approved principals and exact resources. + source_revision: 0b36331 + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ivs-post-exploitation/README.md + notes: 'Draft only: exact evidence must bind actor, target and prerequisite facts. Missing fact must evaluate + UNKNOWN; no definite edge follows from IAM permissions alone.' diff --git a/src/privilege-escalation-paths/aws/lakeformation.yaml b/src/privilege-escalation-paths/aws/lakeformation.yaml new file mode 100644 index 0000000000..d817ba691d --- /dev/null +++ b/src/privilege-escalation-paths/aws/lakeformation.yaml @@ -0,0 +1,37 @@ +# AWS post-exploitation catalog additions. +- id: aws-audit-lf-register-an-s3-location-under-a-privileged-384933ea + provider: aws + service: lakeformation + title: Register S3 location under passed privileged role + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lakeformation-post-exploitation/README.md#register-an-s3-location-under-a-privileged-role + summary: LF data-location grant and scoped access to data reachable by registration role + requires: + all_of: + - action: lakeformation:RegisterResource + resource: '*' + - action: lakeformation:RegisterResourceWithPrivilegedAccess + resource: '*' + - action: iam:PassRole + resource: '*' + - action: iam:GetRole + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit-lf-register-an-s3-location-under-a-privileged-384933ea + scope: same_account + aggregate_as: Verified Register S3 location under passed privileged role in {account} + grants: + - LF data-location grant and scoped access to data reachable by registration role + conditions: + - id: exact_verified_prerequisites + description: Unregistered S3 prefix; role trusts lakeformation.amazonaws.com and reaches S3/KMS; catalog/table + control and GetDataAccess plus engine rights for bytes. + confidence: conditional + severity: high + mitigation: Restrict the stated action to approved principals and exact resources. + source_revision: 0b36331 + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-lakeformation-post-exploitation/README.md + notes: 'Draft only: exact evidence must bind actor, target and prerequisite facts. Missing fact must evaluate + UNKNOWN; no definite edge follows from IAM permissions alone.' From 229191ba336f2b762ee0750cf4520bc888a05a84 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Mon, 12 Oct 2026 20:45:19 +0200 Subject: [PATCH 04/17] Integrate verified AWS post-exploitation and persistence paths Co-Authored-By: Codex --- .../aws/_excluded_a.yaml | 19 +- .../aws/_excluded_audit_6fb9.yaml | 12 + .../aws/_excluded_pa_aws_persist_s03.yaml | 12 + .../aws/_excluded_refresh_g5.yaml | 6 +- .../aws/_excluded_verify_a66f.yaml | 227 ++++-------------- .../aws/challenge-v3.yaml | 117 +++++---- .../aws/cloudformation.yaml | 27 +++ .../aws/datazone.yaml | 28 +++ src/privilege-escalation-paths/aws/ec2.yaml | 192 +++++++++++++++ src/privilege-escalation-paths/aws/ecs.yaml | 32 +++ src/privilege-escalation-paths/aws/iam.yaml | 43 ++++ .../aws/lambda.yaml | 42 ++++ .../aws/ssm-sap.yaml | 33 +++ .../aws/thinclient.yaml | 36 +++ .../aws/timestream.yaml | 72 ++++++ .../aws/transfer.yaml | 68 ++++++ .../aws/verifiedpermissions.yaml | 35 +++ .../aws/vpc-lattice.yaml | 31 +++ src/privilege-escalation-paths/aws/waf.yaml | 33 +++ src/privilege-escalation-paths/aws/wickr.yaml | 93 +++++++ .../aws/workmail.yaml | 66 +++++ .../aws/workspaces-web.yaml | 38 +++ .../aws/workspaces.yaml | 64 +++++ 23 files changed, 1090 insertions(+), 236 deletions(-) create mode 100644 src/privilege-escalation-paths/aws/_excluded_pa_aws_persist_s03.yaml create mode 100644 src/privilege-escalation-paths/aws/ssm-sap.yaml create mode 100644 src/privilege-escalation-paths/aws/thinclient.yaml create mode 100644 src/privilege-escalation-paths/aws/verifiedpermissions.yaml create mode 100644 src/privilege-escalation-paths/aws/vpc-lattice.yaml create mode 100644 src/privilege-escalation-paths/aws/waf.yaml create mode 100644 src/privilege-escalation-paths/aws/workmail.yaml create mode 100644 src/privilege-escalation-paths/aws/workspaces-web.yaml diff --git a/src/privilege-escalation-paths/aws/_excluded_a.yaml b/src/privilege-escalation-paths/aws/_excluded_a.yaml index 280a06e7b4..830166ad28 100644 --- a/src/privilege-escalation-paths/aws/_excluded_a.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_a.yaml @@ -97,22 +97,19 @@ # --- API Gateway --- - 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. + reason: A new API key can be a bearer credential for a key-gated usage-plan method, without granting IAM authority. - 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-privilege-escalation/aws-apigateway-privesc/README.md#apigatewayupdaterestapipolicy--apigatewaypatch + reason: A value-including API key read can disclose a reusable bearer credential, without granting IAM authority. +- 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 + reason: A resource-policy grant can confer route invocation to an external principal after redeployment, subject to method/backend authorization. +- 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 + reason: Changing/removing an authorizer, apiKeyRequired or AWS_IAM authorization can grant previously denied API route invocation after deployment, subject to remaining authorization gates; these are scoped API privileges, not IAM role credentials. +- 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. + reason: Changing or removing an authorizer can grant previously denied route invocation after deployment, without granting an IAM role. - 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 diff --git a/src/privilege-escalation-paths/aws/_excluded_audit_6fb9.yaml b/src/privilege-escalation-paths/aws/_excluded_audit_6fb9.yaml index bbee89d8da..7de6acac78 100644 --- a/src/privilege-escalation-paths/aws/_excluded_audit_6fb9.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_audit_6fb9.yaml @@ -278,3 +278,15 @@ technique: Omni SQL default Dataset query retrieves credential-bearing logs/traces reason: The queried log or trace rows must contain a usable credential and identify its holder; telemetry content and query results are absent from the configuration snapshot. +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-device-farm-persistence/README.md#preserve-an-app-and-trusted-state-on-a-private-device + technique: Retain authenticated state on a private Device Farm instance + reason: A profile setting and package installation do not establish a gained account. The physical device must retain a logged-in app or test-account session, and a later attacker-accessible remote session must reach that state; these are device/app runtime facts, including OS cleanup and session invalidation. +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-devops-agent-persistence/README.md#deferred-long-lived-devops-agent-access-tokens + technique: aidevops:CreateAccessToken or RotateAccessToken + reason: 'The page explicitly defers execution: access tokens are disabled by default and no stable create-request shape is documented. Whether the exact agent space enables tokens, accepts an operate token request and returns a usable token is an API/runtime fact, so action permission alone cannot establish a credential.' +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-devops-agent-persistence/README.md#create-a-persistent-webhook-ingress-through-an-association + technique: aidevops:AssociateService or UpdateAssociation webhook credential + reason: Only a successful association for a registered webhook-capable service may return a one-time GenericWebhook webhookSecret or apiKey. The registered service type, submitted configuration, response issuance and later webhook acceptance are runtime facts; the AWS actions alone do not prove possession of a usable webhook credential. +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-directory-service-persistence/README.md#using-an-ad-user + technique: AD user creation/change and IAM console role assignment + reason: The paragraph describes an authorized operator, not a specific AWS API permission path. Gaining a mapped role requires AD/LDAP user-write or password rights, group-membership or console role-assignment rights, an effective user/group-to-role mapping, and a working directory sign-in; those host/directory facts are not present in the IAM snapshot. The password-reset subpath is already aws-ds-resetuserpassword. diff --git a/src/privilege-escalation-paths/aws/_excluded_pa_aws_persist_s03.yaml b/src/privilege-escalation-paths/aws/_excluded_pa_aws_persist_s03.yaml new file mode 100644 index 0000000000..d9ea707b4b --- /dev/null +++ b/src/privilege-escalation-paths/aws/_excluded_pa_aws_persist_s03.yaml @@ -0,0 +1,12 @@ +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-elastic-beanstalk-persistence/README.md#backdoor-an-instance + technique: Steal instance-profile credentials after host compromise + reason: The instance-profile credentials are reachable only after host compromise and successful IMDS access. A configuration snapshot does not establish that host foothold, IMDS reachability or the attacker’s control of a process on the instance. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-elastic-beanstalk-persistence/README.md#backdoor-in-version + technique: Alter S3 source bundle before later deployment + reason: S3 bundle write alone reaches the instance-profile role only if an independent deployment later selects that exact version and executes the tampered code. The future deployment and bundle contents are runtime/content facts unavailable from a configuration snapshot. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-eventbridge-persistence/README.md#archive-as-a-passive-event-recorder + technique: Create archive retaining bus events for later disclosure + reason: CreateArchive only stores bus events. Gaining a target role would require later StartReplay access plus a rule/target whose handling of replayed event content executes attacker-controlled code or reveals credentials; these runtime automation and event-content facts are not established by the snapshot or this section. + source_revision: 0b36331 diff --git a/src/privilege-escalation-paths/aws/_excluded_refresh_g5.yaml b/src/privilege-escalation-paths/aws/_excluded_refresh_g5.yaml index 1642902921..d10a24fd10 100644 --- a/src/privilege-escalation-paths/aws/_excluded_refresh_g5.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_refresh_g5.yaml @@ -13,11 +13,9 @@ 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: 171e422299 -- source: - src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#appsyncupdategraphqlapi--appsynccreateapikey +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-appsync-privesc/README.md#appsyncupdategraphqlapi--appsynccreateapikey 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.' + reason: Creating an API key, with API_KEY already enabled or enabled by UpdateGraphqlApi, grants a bearer credential for authorized GraphQL fields until expiry; it does not confer an IAM role. source_revision: 171e422299 - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-cloudwatch-omni-privesc/README.md#cloudwatch-omni diff --git a/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml b/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml index 062593fc4a..52bd0a9d04 100644 --- a/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml @@ -15,13 +15,11 @@ 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. + reason: A valid attacker-controlled JWT client can gain registry discovery access after being allowlisted, without gaining AWS IAM authority. 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. + reason: A retained webhook can start a poisoned Amplify build after IAM revocation, yielding execution as its app role. Existing StartJob edges do not cover CreateWebHook as the trigger; a webhook alone has no role access. 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`' @@ -31,9 +29,7 @@ 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. + reason: EnableUser restores service access if the attacker knows a valid password and a usable stack assignment remains; no IAM role is created. 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' @@ -56,29 +52,20 @@ 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.' + technique: '`observabilityadmin:CreateS3TableIntegration` + `logs:AssociateSourceToS3TableIntegration` + `iam:PassRole` — copy future logs into S3 Tables' + reason: 'Potential credential-bearing rows are insufficient: integration setup only establishes log export, not a usable credential.' 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.' + reason: 'Potential credential-bearing events are insufficient: policy setup only establishes log export.' 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. + reason: A scheduled query can expose credentials only when returned rows contain a usable secret readable at the S3 destination. 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. + reason: A subscription can expose credentials only when matching future events contain a usable secret readable at the destination. 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' @@ -89,14 +76,11 @@ 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.' + reason: An external IAM principal can gain repository read or publish authorization, but whether it can exercise the grant also depends on its own identity policy and, for package-manager access, the domain token policy. These cross-account policy facts and a service-resource grant target are required for a configuration-only finding. 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. + reason: PutPermission grants a named same-account user/role ConfigureAgent and PostAgentProfile on a group. A finding requires proof that the grantee is attacker-controlled and a target model for permission grants to another principal; neither follows from PutPermission permission 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' @@ -111,9 +95,7 @@ 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.' + reason: The update may send a stored X-Amz-Firehose-Access-Key to a new endpoint, but credential reuse against the original vendor depends on the vendor and requires a successful later delivery to an attacker-controlled HTTP endpoint. Stream configuration and UpdateDestination permission alone cannot establish a usable new identity or privilege. 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' @@ -129,9 +111,8 @@ 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 + reason: PutFeedPolicy can grant an external authenticated principal new GetMetadata access to the exact feed. The catalog currently draws principal-to-principal edges and has no feed-level data-plane authority target; modeling this requires a feed ARN/principal/action grant target plus the recipient identity-policy allow. No IAM role or whole-account access follows from the policy. + source_revision: 0b36331 - 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, @@ -335,14 +316,12 @@ 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: Add an API Gateway client-key target and selector joining an enabled key, usage plan, stage and key-required - method, including other authorizers. - source_revision: 0b36331 + reason: A new API key can be a bearer credential for a key-gated usage-plan method, without granting IAM authority. + 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: Add an API Gateway client-key target and selector joining readable key value, usage-plan association and - key-required method. - source_revision: 0b36331 + reason: A value-including API key read can disclose a reusable bearer credential, without granting IAM authority. + 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: A stage variable can redirect traffic, but credential gain needs future requests containing usable tokens @@ -2391,9 +2370,7 @@ 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.' + reason: The manifest and unlock code are credentials for the matching Snowball Edge device, so device-local access is possible. A configuration snapshot cannot establish an active WithCustomer job with unexpired credentials, possession or network reach of that exact appliance, or its local service authentication; those facts are required before drawing a device-identity edge. The reads alone yield no AWS IAM session. 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' @@ -2468,9 +2445,7 @@ 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.' + reason: ReceiveMessage can disclose a stronger identity only when a returned message actually contains a valid, usable credential or token for that identity. Queue permissions and metadata cannot establish message contents, credential validity or the target identity; DeleteMessage and ChangeMessageVisibility only alter delivery. source_revision: a66f094ede - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sqs-post-exploitation/README.md#sqsdeletequeue technique: '`sqs:DeleteQueue`' @@ -2500,9 +2475,7 @@ 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.' + reason: A DLQ redrive can expose credentials when the moved message bodies contain valid tokens or secrets for a stronger identity and the attacker can read the destination queue. Queue permissions and redrive configuration cannot establish payload contents, credential validity or target identity. source_revision: a66f094ede - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sso-and-identitystore-post-exploitation/README.md#ssodeletepermissionset technique: '`sso:DeletePermissionSet`' @@ -2523,20 +2496,15 @@ 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.' + reason: TestState with revealSecrets=true and TRACE can disclose EventBridge Connection credentials attached to an HTTP Task. The remote-service identity and its authority require the actual connection, revealed secret and service-side validity; the catalog has no external-service principal target, so the permission pair alone must not create an AWS principal edge. 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. + reason: DescribeStateMachine may return a hardcoded credential in the ASL definition. An escalation edge requires inspection of the actual definition and proof that the value is a valid credential for a stronger identity; IAM permission and state-machine metadata do not establish either fact. 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.' + reason: DescribeExecution or GetExecutionHistory may expose a credential in execution input, output or history. The actual execution content, credential validity and stronger target identity must be verified; read permissions and execution metadata alone do not establish an identity edge. 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` @@ -2544,11 +2512,6 @@ 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 @@ -2576,15 +2539,11 @@ 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. + reason: DescribeChapCredentials returns iSCSI CHAP authentication secrets, which can confer an approved initiator or mutual-CHAP target identity. An edge requires an existing CHAP record for the exact target, host/network reach and compatible initiator settings; AWS IAM configuration does not prove local access or model those iSCSI identities. 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.' + technique: '`storagegateway:CreateNFSFileShare` / `CreateSMBFileShare` (+ `iam:PassRole`) — expose an S3 bucket through a file share and mount it' + reason: Creating a file share with a passed role can exercise that role’s bounded S3 read/write authority through the gateway. A valid edge requires an existing File Gateway, exact role-to-bucket authorization, a mountable NFS/SMB share and attacker network/client access; these gateway and host facts are not established by IAM permission alone. It does not grant general role credentials. source_revision: a66f094ede - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sts-post-exploitation/README.md#stsgetfederationtoken technique: '**`sts:GetFederationToken`**' @@ -2597,30 +2556,12 @@ 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 @@ -2650,63 +2591,12 @@ 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 @@ -2739,47 +2629,6 @@ 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 @@ -3251,3 +3100,27 @@ reason: A Mail Manager rule-set change can yield an account only if a target ingress point uses that rule set, the exfiltration destination receives a later message with a usable token, and that token redeems for a named account. Configuration alone cannot prove the future content or redemption. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/aws-sns-data-protection-bypass.md#security-control-bypass + technique: Remove outbound masking and read secret-bearing future notifications + reason: A policy downgrade can expose future notifications, but the snapshot cannot establish that a later publication contains a usable credential for a stronger identity or that the attacker can read its delivery. Requires the actual message body, credential validity and endpoint access; policy configuration alone proves only loss of masking. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/aws-sns-fifo-replay-exfil.md#attack-replay-archived-messages-to-an-attacker-queue + technique: Replay archive containing credentials to controlled SQS queue + reason: Replay copies archived messages to a subscription; an escalation requires an archived message containing a still-usable credential for a stronger identity and an attacker-readable confirmed endpoint. Archive and subscription configuration do not establish message contents or credential validity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/aws-sns-firehose-exfil.md#traffic-interception--redirection + technique: Attach Firehose sink to copy future messages, including possible secrets + reason: A Firehose subscription copies future SNS messages. It reaches a stronger identity only if a later delivered record contains a usable credential and the attacker can read the sink; subscription, delivery role and bucket configuration cannot establish that future content. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sns-post-exploitation/aws-sns-firehose-exfil.md#related-bucket-name-hijack-variant + technique: Recreate deleted Firehose destination bucket and capture future records + reason: Recreating a deleted bucket can redirect future Firehose objects, but bucket-name availability, continued producer delivery and the actual presence of a usable stronger-identity credential in delivered records are external/runtime facts. IAM and bucket configuration alone establish data redirection, not identity gain. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-ssm-gui-connect-post-exploitation/README.md#redirect-or-break-the-future-recording-sink + technique: Redirect RDP recordings that may show credentials + reason: Changing the RDP recording destination gives access to future video only if a session occurs and the recording visibly exposes a usable credential of another identity. Account recording preferences and KMS grants cannot establish future screen content or credential validity. +- source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-sts-post-exploitation/README.md#from-web-console-to-iam-creds + technique: Intercept victim console session credentials in browser + reason: The page describes theft of a victim session from the victim browser, which is a real identity gain. It requires browser or extension compromise and a live victim credential response; neither fact exists in an AWS configuration snapshot. +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudformation-persistence/README.md#malicious-registry-hook-or-default-extension-version + technique: Set malicious module default version for later stacks + reason: Requires a later stack template referencing the unversioned module, the deployment caller or stack role, and module content that actually grants access; default-version state alone proves no escalation. +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-data-firehose-persistence/README.md#firehoseupdatedestination--persistently-redirect-future-records + technique: firehose:UpdateDestination retained HTTP access key + reason: The update may send a stored X-Amz-Firehose-Access-Key to a new endpoint, but credential reuse against the original vendor depends on the vendor and requires a successful later delivery to an attacker-controlled HTTP endpoint. Stream configuration and UpdateDestination permission alone cannot establish a usable new identity or privilege. diff --git a/src/privilege-escalation-paths/aws/challenge-v3.yaml b/src/privilege-escalation-paths/aws/challenge-v3.yaml index 135116b1c5..af4843c012 100644 --- a/src/privilege-escalation-paths/aws/challenge-v3.yaml +++ b/src/privilege-escalation-paths/aws/challenge-v3.yaml @@ -132,14 +132,14 @@ provider: aws service: workspaces-web title: Add or replace a WorkSpaces Web portal SAML/OIDC identity provider - source: - src/pentesting-cloud/aws-security/aws-persistence/aws-workspaces-web-persistence/README.md#persist-an-attacker-controlled-portal-identity-provider - summary: Controlled IdP trusted by an exact standard-federation portal -> portal access plane. Exact source, target - and prerequisite proof are required. + source: src/pentesting-cloud/aws-security/aws-persistence/aws-workspaces-web-persistence/README.md#persist-an-attacker-controlled-portal-identity-provider + summary: Controlled IdP trusted by an exact standard-federation portal -> portal access plane. Exact source, target and prerequisite proof are required. requires: - all_of: - - action: workspaces-web:CreateIdentityProvider - resource: '*' + any_of: + - - action: workspaces-web:CreateIdentityProvider + resource: '*' + - - action: workspaces-web:UpdateIdentityProvider + resource: '*' target: kind: aws_verified_authority selector: @@ -150,15 +150,13 @@ - portal access plane. conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; IdP - write alone is insufficient; only that portal and its federated session are targets. + description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; IdP write alone is insufficient; only that portal and its federated session are targets. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is - UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-06-use-independent-cognito-replica-lockout-counters-to-gue provider: aws service: challenge-evidence @@ -444,14 +442,18 @@ provider: aws service: logs title: Replay a victim application session recovered from WAF records - source: - src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#aws-waf-log-credential-harvesting-and-request-replay - summary: Readable WAF log destination -> exact application session identified by a captured replayable header, - conditional only. Exact source, target and prerequisite proof are required. + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#aws-waf-log-credential-harvesting-and-request-replay + summary: Readable WAF log destination -> exact application session identified by a captured replayable header, conditional only. Exact source, target and prerequisite proof are required. requires: - all_of: - - action: logs:FilterLogEvents - resource: '*' + any_of: + - - action: logs:FilterLogEvents + resource: '*' + - - action: logs:GetLogEvents + resource: '*' + - - action: wafv2:GetSampledRequests + resource: '*' + - - action: s3:GetObject + resource: '*' target: kind: aws_verified_authority selector: @@ -462,16 +464,13 @@ - exact application session identified by a captured replayable header, conditional only. conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - Readable logging is only a necessary proxy; no victim principal is constructed until the external evidence - identifies that exact session. + description: The exact WAF record must contain an unredacted, unexpired replayable credential for the named victim; logging access alone is insufficient. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is - UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-16-redeem-a-device-farm-session-endpoint-and-control-a-log provider: aws service: devicefarm @@ -539,14 +538,14 @@ provider: aws service: workspaces-web title: Attach an attacker IdP to a WorkSpaces Secure Browser portal - source: - src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-web-post-exploitation/README.md#add-or-replace-an-attacker-controlled-identity-provider - summary: WorkSpaces Web IdP replacement -> exact portal federation access plane. Exact source, target and prerequisite - proof are required. + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-web-post-exploitation/README.md#add-or-replace-an-attacker-controlled-identity-provider + summary: WorkSpaces Web IdP replacement -> exact portal federation access plane. Exact source, target and prerequisite proof are required. requires: - all_of: - - action: workspaces-web:CreateIdentityProvider - resource: '*' + any_of: + - - action: workspaces-web:CreateIdentityProvider + resource: '*' + - - action: workspaces-web:UpdateIdentityProvider + resource: '*' target: kind: aws_verified_authority selector: @@ -557,15 +556,13 @@ - exact portal federation access plane. conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; Do - not imply IAM access or Identity Center access from portal login. + description: The exact standard-federation portal must trust the newly created or updated attacker-controlled IdP; source and target must match reviewed evidence. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is - UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-19-grant-a-controlled-identity-sitewise-monitor-administra provider: aws service: iotsitewise @@ -1220,16 +1217,19 @@ provider: aws service: elasticache title: ElastiCache full-access user group - source: - src/pentesting-cloud/aws-security/aws-persistence/aws-elasticache-persistence/README.md#elasticachecreateuser-elasticachecreateusergroup--elasticachemodifyusergroup--plant-a-full-access-rbac-user - summary: 'Add `service_plane: elasticache` and exact replication-group selector; require row-specific ModifyUser/CreateUser/ModifyUserGroup - or ModifyReplicationGroup. Exact source, target and prerequisite proof are required.' + source: src/pentesting-cloud/aws-security/aws-persistence/aws-elasticache-persistence/README.md#elasticachecreateuser-elasticachecreateusergroup--elasticachemodifyusergroup--plant-a-full-access-rbac-user + summary: 'Add `service_plane: elasticache` and exact replication-group selector; require row-specific ModifyUser/CreateUser/ModifyUserGroup or ModifyReplicationGroup. Exact source, target and prerequisite proof are required.' requires: all_of: - action: elasticache:CreateUser resource: '*' - - action: elasticache:CreateUserGroup - resource: '*' + any_of: + - - action: elasticache:ModifyUserGroup + resource: '*' + - - action: elasticache:CreateUserGroup + resource: '*' + - action: elasticache:ModifyReplicationGroup + resource: '*' target: kind: aws_verified_authority selector: @@ -1240,15 +1240,13 @@ - 'Add `service_plane: elasticache` and exact replication-group selector; require row-specifi' conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - Same group-to-replication-group join; create/modify actions on exact resources. + description: Exact verified evidence must bind the source, new user, affected user-group and replication group. ModifyUserGroup needs authorization on the existing group and every added/removed user; CreateUserGroup needs authorization on the new group and every initial user, plus ModifyReplicationGroup to attach it to an existing replication group. The user must be active with attacker-known password, full access string, and network reach. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is - UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: Missing aws_privesc_challenge_evidence remains UNKNOWN. The current target has no exact user/group ARN placeholders, so scoped resource checks remain an evaluator/collector limitation; the challenge fact must prove them rather than report a definite path. - id: aws-v3-43-memorydb-full-access-acl-user provider: aws service: memorydb @@ -2230,3 +2228,34 @@ mitigation: Restrict the listed mutation or read permission and review its exact resource scope. notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is UNKNOWN/unresolved; verified evidence never creates a definite path. +- id: aws-pa-persist-s01-01 + provider: aws + service: acm + title: Create EAB for an existing issuance role, recover binding, register ACME account + source: src/pentesting-cloud/aws-security/aws-persistence/aws-acm-persistence/README.md#register-an-attacker-controlled-acme-certificate-account + summary: Issue certificates for prevalidated names without retaining original IAM principal + requires: + all_of: + - action: acm:CreateAcmeExternalAccountBinding + resource: '*' + - action: acm:GetAcmeExternalAccountBindingCredentials + resource: '*' + - action: iam:PassRole + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-pa-persist-s01-01 + scope: same_account + grants: + - Issue certificates for prevalidated names without retaining original IAM principal + conditions: + - id: exact_prerequisites + description: Exact endpoint and EAB; iam:PassedToService=acm-acme.amazonaws.com; Role trusts acm-acme.amazonaws.com for AssumeRole, TagSession and SetSourceIdentity; Active endpoint and validated domain; registered external account key; role can acm:RequestCertificate + confidence: conditional + severity: high + mitigation: Restrict these permissions on the exact resource and review the resulting service access. + references: + - https://docs.aws.amazon.com/acm/latest/APIReference/API_GetAcmeExternalAccountBindingCredentials.html + - https://docs.aws.amazon.com/acm/latest/userguide/security-iam-acme.html + notes: 'Draft only: exact source and target evidence is required; absent evidence evaluates UNKNOWN.' diff --git a/src/privilege-escalation-paths/aws/cloudformation.yaml b/src/privilege-escalation-paths/aws/cloudformation.yaml index 9f4ad52e30..05d0934473 100644 --- a/src/privilege-escalation-paths/aws/cloudformation.yaml +++ b/src/privilege-escalation-paths/aws/cloudformation.yaml @@ -467,3 +467,30 @@ self-managed StackSets only (their service_managed_stacksets / stackset_permission_model conditions). No iam:PassRole is involved. StackSet permission model, trusted-access state and delegated administrators are not collected, so the edge stays conditional. +- id: aws-pa-persist-s01-30 + provider: aws + service: cloudformation + title: Change CDKToolkit TrustedAccounts to attacker account and deploy role trust + source: src/pentesting-cloud/aws-security/aws-persistence/aws-cloudformation-persistence/README.md#cdk-bootstrap-stack + summary: Assume victim CDK bootstrap role from attacker account after trust update + requires: + all_of: + - action: cloudformation:UpdateStack + resource: '*' + target: + kind: aws_role + selector: + aws_challenge_fact: aws-pa-persist-s01-30 + scope: same_account + grants: + - Assume victim CDK bootstrap role from attacker account after trust update + conditions: + - id: exact_prerequisites + description: Exact existing CDKToolkit stack and mutable TrustedAccounts parameter; Attacker controls listed external account; update changes bootstrap role trust; Execution policy and external account sts:AssumeRole determine gained permissions + confidence: conditional + severity: high + mitigation: Restrict these permissions on the exact resource and review the resulting service access. + references: + - https://docs.aws.amazon.com/cdk/v2/guide/ref-cli-cmd-bootstrap.html + - https://docs.aws.amazon.com/cli/latest/reference/cloudformation/update-stack.html + notes: 'Draft only: exact source and target evidence is required; absent evidence evaluates UNKNOWN.' diff --git a/src/privilege-escalation-paths/aws/datazone.yaml b/src/privilege-escalation-paths/aws/datazone.yaml index b5bde3cf81..e985a31920 100644 --- a/src/privilege-escalation-paths/aws/datazone.yaml +++ b/src/privilege-escalation-paths/aws/datazone.yaml @@ -73,3 +73,31 @@ references: - https://docs.aws.amazon.com/datazone/latest/APIReference/API_AssociateEnvironmentRole.html notes: DataZone authorization is evaluated in addition to IAM and is not collected. +- id: aws-datazone-createprojectmembership-owner + provider: aws + service: datazone + title: Grant a controlled DataZone profile project ownership + source: src/pentesting-cloud/aws-security/aws-persistence/aws-datazone-persistence/README.md#add-an-attacker-profile-as-a-project-owner + summary: An existing project owner or domain-authorized caller can add a controlled profile as PROJECT_OWNER. + requires: + all_of: + - action: datazone:CreateProjectMembership + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-datazone-createprojectmembership-owner + scope: same_account + grants: + - PROJECT_OWNER on the exact DataZone project + conditions: + - id: datazone_authorization + description: Caller must already be a project owner or have domain-level authorization, beyond the IAM action. + - id: controlled_profile + description: The existing active user/group profile must be controlled by the attacker; later DataZone API calls still need IAM authorization. + confidence: conditional + severity: high + mitigation: Restrict the listed write action to approved administrators and review grants to controlled or external principals. + references: + - https://docs.aws.amazon.com/datazone/latest/APIReference/API_CreateProjectMembership.html + notes: Draft only. The generic verified-authority target is a schema-valid placeholder. Do not activate this entry until the stated evaluator/collector feature binds the exact source, resource and grantee; absent facts must remain UNKNOWN. diff --git a/src/privilege-escalation-paths/aws/ec2.yaml b/src/privilege-escalation-paths/aws/ec2.yaml index 29a44b6dd4..1a3c9a6ffa 100644 --- a/src/privilege-escalation-paths/aws/ec2.yaml +++ b/src/privilege-escalation-paths/aws/ec2.yaml @@ -479,3 +479,195 @@ mitigation: Restrict access to sensitive resources and remove secrets from the artifact. references: [] notes: Required collector evidence is absent from current snapshots; missing evidence remains UNKNOWN/unresolved. +- id: aws-s05-ec2getvpnconnectiondevicesampleconfiguration-disclose-site-to-site-vpn + provider: aws + service: ec2 + title: '`ec2:GetVpnConnectionDeviceSampleConfiguration` — disclose Site-to-Site VPN pre-shared keys' + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2getvpnconnectiondevicesampleconfiguration--disclose-site-to-site-vpn-pre-shared-keys + source_revision: 0b36331 + summary: The source may obtain Site-to-Site VPN peer PSK credential when the exact documented prerequisite is verified. + requires: + all_of: + - action: ec2:GetVpnConnectionDeviceSampleConfiguration + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-ec2getvpnconnectiondevicesampleconfiguration-disclose-site-to-site-vpn + scope: same_account + aggregate_as: Verified Site-to-Site VPN peer PSK credential in {account} + grants: + - Site-to-Site VPN peer PSK credential + conditions: + - id: exact_verified_prerequisites + description: Exact connection uses Standard PSK storage; usable tunnel additionally needs configured gateway IP/control and routing. Secrets Manager-backed PSKs require independent GetSecretValue. Existing exclusion denies credential gain by limiting itself to AWS principal. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/vpn/latest/s2svpn/SetUpVPNConnections.html + - https://docs.aws.amazon.com/vpn/latest/s2svpn/customer-gateway-device-windows.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. +- id: aws-s05-ec2modifyvpnconnection-ec2modifyvpntunneloptions-take-over-an-existing + provider: aws + service: ec2 + title: '`ec2:ModifyVpnConnection` + `ec2:ModifyVpnTunnelOptions` — take over an existing Site-to-Site VPN peer' + 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 + source_revision: 0b36331 + summary: The source may obtain Site-to-Site VPN customer peer identity when the exact documented prerequisite is verified. + requires: + any_of: + - - action: ec2:ModifyVpnConnection + resource: '*' + - - action: ec2:ModifyVpnConnection + resource: '*' + - action: ec2:ModifyVpnTunnelOptions + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-ec2modifyvpnconnection-ec2modifyvpntunneloptions-take-over-an-existing + scope: same_account + aggregate_as: Verified Site-to-Site VPN customer peer identity in {account} + grants: + - Site-to-Site VPN customer peer identity + conditions: + - id: exact_verified_prerequisites + description: Existing same-account customer gateway points to attacker-controlled public IP; tunnel PSKs known or rotated, compatible IKE and routes. Gateway-only change with known PSKs is a valid alternative. Existing exclusion ignores VPN peer takeover. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/vpn/latest/s2svpn/SetUpVPNConnections.html + - https://docs.aws.amazon.com/vpn/latest/s2svpn/customer-gateway-device-windows.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. +- id: aws-s05-ec2authorizeclientvpningress-broaden-an-authenticated-vpn-clients-netw + provider: aws + service: ec2 + title: '`ec2:AuthorizeClientVpnIngress` — broaden an authenticated VPN client''s network access' + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2authorizeclientvpningress--broaden-an-authenticated-vpn-clients-network-access + source_revision: 0b36331 + summary: The source may obtain Private CIDR reachability for existing VPN client when the exact documented prerequisite is verified. + requires: + all_of: + - action: ec2:AuthorizeClientVpnIngress + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-ec2authorizeclientvpningress-broaden-an-authenticated-vpn-clients-netw + scope: same_account + aggregate_as: Verified Private CIDR reachability for existing VPN client in {account} + grants: + - Private CIDR reachability for existing VPN client + conditions: + - id: exact_verified_prerequisites + description: Existing accepted VPN client identity plus matching endpoint association, authorization rule, route, security path and application access. This mutation expands network authorization but does not grant AWS IAM; existing exclusion wrongly uses only AWS-principal criterion. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/vpn/latest/s2svpn/SetUpVPNConnections.html + - https://docs.aws.amazon.com/vpn/latest/s2svpn/customer-gateway-device-windows.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. +- id: aws-s05-ec2associateclientvpntargetnetwork-ec2createclientvpnroute-attach-clie + provider: aws + service: ec2 + title: '`ec2:AssociateClientVpnTargetNetwork` + `ec2:CreateClientVpnRoute` — attach Client VPN to a VPC and extend reachable networks' + 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 + source_revision: 0b36331 + summary: The source may obtain VPC or routed-CIDR reachability for existing VPN client when the exact documented prerequisite is verified. + requires: + any_of: + - - action: ec2:AssociateClientVpnTargetNetwork + resource: '*' + - - action: ec2:CreateClientVpnRoute + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-ec2associateclientvpntargetnetwork-ec2createclientvpnroute-attach-clie + scope: same_account + aggregate_as: Verified VPC or routed-CIDR reachability for existing VPN client in {account} + grants: + - VPC or routed-CIDR reachability for existing VPN client + conditions: + - id: exact_verified_prerequisites + description: Existing accepted VPN client identity plus matching endpoint association, authorization rule, route, security path and application access. This mutation expands network authorization but does not grant AWS IAM; existing exclusion wrongly uses only AWS-principal criterion. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/vpn/latest/s2svpn/SetUpVPNConnections.html + - https://docs.aws.amazon.com/vpn/latest/s2svpn/customer-gateway-device-windows.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. +- id: aws-s05-ec2applysecuritygroupstoclientvpntargetnetwork-rebind-client-vpn-to-a + provider: aws + service: ec2 + title: '`ec2:ApplySecurityGroupsToClientVpnTargetNetwork` — rebind Client VPN to a trusted security group' + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2applysecuritygroupstoclientvpntargetnetwork--rebind-client-vpn-to-a-trusted-security-group + source_revision: 0b36331 + summary: The source may obtain Trusted network path through selected Client VPN security group when the exact documented prerequisite is verified. + requires: + all_of: + - action: ec2:ApplySecurityGroupsToClientVpnTargetNetwork + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-ec2applysecuritygroupstoclientvpntargetnetwork-rebind-client-vpn-to-a + scope: same_account + aggregate_as: Verified Trusted network path through selected Client VPN security group in {account} + grants: + - Trusted network path through selected Client VPN security group + conditions: + - id: exact_verified_prerequisites + description: Existing accepted VPN client identity plus matching endpoint association, authorization rule, route, security path and application access. This mutation expands network authorization but does not grant AWS IAM; existing exclusion wrongly uses only AWS-principal criterion. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/vpn/latest/s2svpn/SetUpVPNConnections.html + - https://docs.aws.amazon.com/vpn/latest/s2svpn/customer-gateway-device-windows.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. +- id: aws-s05-ec2modifyclientvpnendpoint-hijack-client-dnsrouting-and-suppress-conne + provider: aws + service: ec2 + title: '`ec2:ModifyClientVpnEndpoint` — hijack client DNS/routing and suppress connection logs' + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-vpn-post-exploitation/README.md#ec2modifyclientvpnendpoint--hijack-client-dnsrouting-and-suppress-connection-logs + source_revision: 0b36331 + summary: The source may obtain Victim application credential submitted after DNS redirection when the exact documented prerequisite is verified. + requires: + all_of: + - action: ec2:ModifyClientVpnEndpoint + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-ec2modifyclientvpnendpoint-hijack-client-dnsrouting-and-suppress-conne + scope: same_account + aggregate_as: Verified Victim application credential submitted after DNS redirection in {account} + grants: + - Victim application credential submitted after DNS redirection + conditions: + - id: exact_verified_prerequisites + description: Exact endpoint accepts attacker-selected DNS server and victim clients reconnect; victim DNS queries are redirected to attacker-controlled destination and user submits reusable credentials. DNS change alone does not bypass TLS or application auth. Existing exclusion correctly rejects IAM escalation but overlooks conditional credential theft via phishing described on the page. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/vpn/latest/s2svpn/SetUpVPNConnections.html + - https://docs.aws.amazon.com/vpn/latest/s2svpn/customer-gateway-device-windows.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. diff --git a/src/privilege-escalation-paths/aws/ecs.yaml b/src/privilege-escalation-paths/aws/ecs.yaml index 255a6a008c..b164d99da4 100644 --- a/src/privilege-escalation-paths/aws/ecs.yaml +++ b/src/privilege-escalation-paths/aws/ecs.yaml @@ -431,3 +431,35 @@ - https://docs.aws.amazon.com/AmazonECS/latest/developerguide/container-instance-draining.html - https://docs.aws.amazon.com/AmazonECS/latest/APIReference/API_UpdateContainerInstancesState.html notes: Unlike aws-ecs-registercontainerinstance-starttask this path needs no ecs:StartTask or iam:PassRole; it reaches the task roles of existing services. ecs:DeregisterContainerInstance is authorized on the cluster ARN. +- id: aws-ecs-eventbridge-scheduled-task-role + provider: aws + service: ecs + title: Schedule attacker-controlled ECS code under a task role + source: src/pentesting-cloud/aws-security/aws-persistence/aws-ecs-persistence/README.md#periodic-ecs-task-through-eventbridge + source_revision: 0b36331 + summary: The source can arrange recurring execution of attacker-controlled ECS code with a task role through an EventBridge scheduled rule. + requires: + all_of: + - action: events:PutRule + resource: '*' + - action: events:PutTargets + resource: '*' + - action: iam:PassRole + resource: '*' + target: + kind: aws_role + selector: + aws_challenge_fact: aws-ecs-eventbridge-scheduled-task-role + scope: same_account + aggregate_as: Verified ECS task roles reachable through scheduled EventBridge targets in {account} + conditions: + - id: invocation_role_and_task + description: The EventBridge invocation role must trust events.amazonaws.com and authorize ecs:RunTask plus any required iam:PassRole; the selected task definition must have attacker-controlled code and the stronger taskRoleArn. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict scheduled ECS targets, invocation-role passing, and task-definition roles to approved deployment principals. + references: + - https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-run-ecs-schedule.html + notes: Provisional exact-evidence selector keeps the path UNKNOWN until the requested ECS/EventBridge joins are collected. RegisterTaskDefinition and PassRole on task/execution roles are additional requirements when creating a task definition; the existing-definition variant needs proof of attacker code control. diff --git a/src/privilege-escalation-paths/aws/iam.yaml b/src/privilege-escalation-paths/aws/iam.yaml index 4a3ef51c13..0a84239868 100644 --- a/src/privilege-escalation-paths/aws/iam.yaml +++ b/src/privilege-escalation-paths/aws/iam.yaml @@ -1102,3 +1102,46 @@ 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-persistence/aws-iam-persistence/README.md#common-iam-persistence + source_revision: 0b36331 + 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:aws:iam::{source.account}:user/* + bind: new_user + - action: iam:CreateAccessKey + resource: arn:aws:iam::{source.account}:user/* + bind: new_user + any_of: + - - action: iam:PutUserPolicy + resource: arn:aws:iam::{source.account}:user/* + bind: new_user + - - action: iam:AttachUserPolicy + resource: arn:aws:iam::{source.account}:user/* + bind: new_user + 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/aws/lambda.yaml b/src/privilege-escalation-paths/aws/lambda.yaml index eddfe947b8..3e97be97f7 100644 --- a/src/privilege-escalation-paths/aws/lambda.yaml +++ b/src/privilege-escalation-paths/aws/lambda.yaml @@ -772,3 +772,45 @@ notes: Draft only. Missing exact evidence remains UNKNOWN; replace placeholder with the typed selector or collector fact described alongside this draft. Required collector evidence is absent from current snapshots; missing evidence remains UNKNOWN/unresolved. +- 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-persistence/aws-lambda-persistence/README.md#cronevent-actuator + source_revision: 0b36331 + 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:aws:lambda:*:{source.account}:function:* + bind: new_function + - action: events:PutRule + resource: arn:aws:events:*:{source.account}:rule/* + bind: scheduled_rule + - action: events:PutTargets + resource: arn:aws:events:*:{source.account}:rule/* + bind: scheduled_rule + - action: lambda:AddPermission + resource: arn:aws: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: Passable Lambda roles reachable via EventBridge in {account} + 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. diff --git a/src/privilege-escalation-paths/aws/ssm-sap.yaml b/src/privilege-escalation-paths/aws/ssm-sap.yaml new file mode 100644 index 0000000000..0293a0b0d9 --- /dev/null +++ b/src/privilege-escalation-paths/aws/ssm-sap.yaml @@ -0,0 +1,33 @@ +- id: aws-s05-recover-configured-sap-hana-administrator-credentials + provider: aws + service: ssm-sap + title: Recover configured SAP HANA administrator credentials + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-systems-manager-for-sap-post-exploitation/README.md#recover-configured-sap-hana-administrator-credentials + source_revision: 0b36331 + summary: The source may obtain SAP HANA ADMIN database identity when the exact documented prerequisite is verified. + requires: + all_of: + - action: ssm-sap:GetDatabase + resource: '*' + - action: secretsmanager:GetSecretValue + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-recover-configured-sap-hana-administrator-credentials + scope: same_account + aggregate_as: Verified SAP HANA ADMIN database identity in {account} + grants: + - SAP HANA ADMIN database identity + conditions: + - id: exact_verified_prerequisites + description: Registered HANA database exposes the ADMIN SecretId; caller can read that exact secret, use kms:Decrypt if needed, and reach/authenticate to HANA. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/ssmsap/latest/APIReference/API_GetDatabase.html + - https://docs.aws.amazon.com/ssm-sap/latest/userguide/register-database.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. diff --git a/src/privilege-escalation-paths/aws/thinclient.yaml b/src/privilege-escalation-paths/aws/thinclient.yaml new file mode 100644 index 0000000000..4fbb6544f3 --- /dev/null +++ b/src/privilege-escalation-paths/aws/thinclient.yaml @@ -0,0 +1,36 @@ +- id: aws-s05-thinclientupdateenvironment-redirect-devices-to-another-desktop-provid + provider: aws + service: thinclient + title: '`thinclient:UpdateEnvironment` - Redirect devices to another desktop provider or IdP endpoint' + 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 + source_revision: 0b36331 + summary: The source may obtain Victim IdP credential submitted to redirected endpoint when the exact documented prerequisite is verified. + requires: + all_of: + - action: thinclient:UpdateEnvironment + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-thinclientupdateenvironment-redirect-devices-to-another-desktop-provid + scope: same_account + aggregate_as: Verified Victim IdP credential submitted to redirected endpoint in {account} + grants: + - Victim IdP credential submitted to redirected endpoint + conditions: + - id: exact_verified_prerequisites + description: Exact WorkSpaces Applications environment accepts changed desktopEndpoint; registered user follows attacker-controlled IdP login URL and submits a credential. Compatible same-Region provider and victim interaction are required. Existing exclusion omits the documented credential-phishing consequence. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - "https://attacker.example/idp/login' \\\n --region \n```\n\nDo not assume that changing `desktopArn` grants control over the destination. If the attacker does not already operate the IdP or destination provider, this may cause only denial of service. End-user impact requires a registered device and a user session; control-plane success alone does not prove that credentials were captured.\n\n
\nLogs generated, detection, and stealth\n\n| Signal | Detail |\n| --- | --- |\n| CloudTrail | `UpdateEnvironment` under `thinclient.amazonaws.com`, `managementEvent:true`, `readOnly:false`, with the environment ID in `requestParameters` |\n| Request detail | CloudTrail records the environment ID and changed fields, but treats `desktopEndpoint` as sensitive and redacts its value |\n| Configuration | `GetEnvironment` and configuration inventory expose the changed `desktopArn`, endpoint and `updatedAt` value |\n| Endpoint/device | Devices start using the changed\ + \ destination; authentication failures and a new domain/certificate are independent indicators |\n| Stealth | **Medium**: one management event is generated and the destination is enumerable, but the endpoint value is redacted in the CloudTrail request |\n\n
\n\n## Security control bypass\n\n### Software-set writes - Pin or force a less secure device release\n\n**Minimum permissions:**\n\n- `thinclient:UpdateSoftwareSet` on the exact software-set ARN to change its validation state; and\n- `thinclient:UpdateEnvironment` on the exact environment ARN to target every device in the environment, or `thinclient:UpdateDevice` on an exact device ARN to target one device.\n\n```json\n{\n \"Version\": \"2012-10-17\",\n \"Statement\": [\n {\n \"Effect\": \"Allow\",\n \"Action\": \"thinclient:UpdateSoftwareSet\",\n \"Resource\": \"arn:aws:thinclient:::softwareset/\"\n },\n {\n \"Effect\": \"Allow\",\n \"Action\": \"\ + thinclient:UpdateEnvironment\",\n \"Resource\": \"arn:aws:thinclient:::environment/\"\n }\n ]\n}\n```\n\nReplace the second statement with `thinclient:UpdateDevice` and a `device/` ARN for a single-device change.\n\n**Prerequisites:** An existing registered environment or device and an AWS-published software set that the service still permits the target to install. The attacker cannot upload arbitrary firmware through this API. AWS automatically updates expired releases, so pinning an old version is bounded by the release's `supportedUntil` lifecycle.\n\n**Impact:** The attacker can approve a release, switch an environment or device from `USE_LATEST` to a chosen older supported release, and request immediate installation. This can interrupt active sessions and temporarily remove security fixes that only exist in newer Thin Client OS/Chromium software. Marking a needed release `NOT_VALIDATED` can also interfere with an administrator's\ + \ rollout. This is defense degradation and availability impact, not AWS IAM privilege escalation.\n\nReview component versions and support dates before selecting a target:\n\n```bash\naws workspaces-thin-client list-software-sets --region \naws workspaces-thin-client get-software-set \\\n --id \\\n --region \n```\n\nValidate and select a release for every device in an environment:\n\n```bash\naws workspaces-thin-client update-software-set \\\n --id \\\n --validation-status VALIDATED \\\n --region \n\naws workspaces-thin-client update-environment \\\n --id \\\n --software-set-update-mode USE_DESIRED \\\n --desired-software-set-id \\\n --software-set-update-schedule APPLY_IMMEDIATELY \\\n --region \n```\n\nOr target one device:\n\n```bash\naws workspaces-thin-client update-device \\\n --id \\\n --desired-software-set-id \\\n --software-set-update-schedule\ + \ APPLY_IMMEDIATELY \\\n --region \n```\n\nRestore the original validation status, update mode, desired release and schedule after a temporary change. Do not force an update on a production device with an active user session.\n\n
\nLogs generated, detection, and stealth\n\n| Signal | Detail |\n| --- | --- |\n| CloudTrail | `UpdateSoftwareSet` plus `UpdateEnvironment` or `UpdateDevice` under `thinclient.amazonaws.com`; these are management events with `readOnly:false` |\n| Configuration | Software-set `validationStatus`; environment/device desired and pending set IDs; update mode/schedule; and `updatedAt` timestamps |\n| Device | Version/compliance changes, reboot or session interruption when an immediate install is applied |\n| Lifecycle | A desired version older than the newest validated release or near `supportedUntil` is a high-signal discrepancy |\n| Stealth | **Low** for an immediate deployment because it is user-visible and produces multiple\ + \ durable changes; **medium** for a maintenance-window pin that is not reconciled regularly |\n\n
\n\n## References\n\n- [UpdateEnvironment API](https://docs.aws.amazon.com/workspaces-thin-client/latest/api/API_UpdateEnvironment.html" + - https://docs.aws.amazon.com/workspaces-thin-client/latest/api/API_UpdateSoftwareSet.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. diff --git a/src/privilege-escalation-paths/aws/timestream.yaml b/src/privilege-escalation-paths/aws/timestream.yaml index 0c2fdd50ed..aafafd4784 100644 --- a/src/privilege-escalation-paths/aws/timestream.yaml +++ b/src/privilege-escalation-paths/aws/timestream.yaml @@ -74,3 +74,75 @@ no definite privilege edge. references: - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-timestream-privesc/ +- id: aws-s05-liveanalytics-query-a-table-with-timestreamselect + provider: aws + service: timestream + title: 'LiveAnalytics: query a table with `timestream:Select`' + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#liveanalytics-query-a-table-with-timestreamselect + source_revision: 0b36331 + summary: The source may obtain Identity represented by a valid secret in Timestream rows when the exact documented prerequisite is verified. + requires: + all_of: + - action: timestream:Select + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-liveanalytics-query-a-table-with-timestreamselect + scope: same_account + aggregate_as: Verified Identity represented by a valid secret in Timestream rows in {account} + grants: + - Identity represented by a valid secret in Timestream rows + conditions: + - id: exact_verified_prerequisites + description: Exact table contains a usable secret/token as a dimension or measure, caller can read that table, and the credential remains valid. UNLOAD additionally requires same-Region writable attacker-readable S3 destination and listed S3 permissions; direct Select normally needs DescribeEndpoints for CLI/SDK. Existing exclusion overlooks the explicit secrets/tokens impact while denying AWS-principal gain. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/timestream/latest/developerguide/security_iam_service-with-iam.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_timestream.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. +- id: aws-s05-liveanalytics-export-query-results-to-s3-with-timestreamunload + provider: aws + service: timestream + title: 'LiveAnalytics: export query results to S3 with `timestream:Unload`' + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-timestream-post-exploitation/README.md#liveanalytics-export-query-results-to-s3-with-timestreamunload + source_revision: 0b36331 + summary: The source may obtain Identity represented by a valid secret in exported Timestream rows when the exact documented prerequisite is verified. + requires: + all_of: + - action: timestream:Select + resource: '*' + - action: timestream:Unload + resource: '*' + - action: s3:GetBucketAcl + resource: '*' + - action: s3:PutObject + resource: '*' + - action: s3:GetObject + resource: '*' + - action: s3:AbortMultipartUpload + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-liveanalytics-export-query-results-to-s3-with-timestreamunload + scope: same_account + aggregate_as: Verified Identity represented by a valid secret in exported Timestream rows in {account} + grants: + - Identity represented by a valid secret in exported Timestream rows + conditions: + - id: exact_verified_prerequisites + description: Exact table contains a usable secret/token as a dimension or measure, caller can read that table, and the credential remains valid. UNLOAD additionally requires same-Region writable attacker-readable S3 destination and listed S3 permissions; direct Select normally needs DescribeEndpoints for CLI/SDK. Existing exclusion overlooks the explicit secrets/tokens impact while denying AWS-principal gain. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/timestream/latest/developerguide/security_iam_service-with-iam.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_timestream.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. diff --git a/src/privilege-escalation-paths/aws/transfer.yaml b/src/privilege-escalation-paths/aws/transfer.yaml index 896eeb41e7..df5a4a4ea2 100644 --- a/src/privilege-escalation-paths/aws/transfer.yaml +++ b/src/privilege-escalation-paths/aws/transfer.yaml @@ -236,3 +236,71 @@ no definite privilege edge. references: - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-transfer-family-privesc/ +- id: aws-s05-connector-remote-directory-move-and-delete-capability-pivot + provider: aws + service: transfer + title: Connector remote-directory, move, and delete capability pivot + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#connector-remote-directory-move-and-delete-capability-pivot + source_revision: 0b36331 + summary: The source may obtain Remote SFTP connector identity and its authorized remote directory capability when the exact documented prerequisite is verified. + requires: + any_of: + - - action: transfer:StartDirectoryListing + resource: '*' + - - action: transfer:StartRemoteMove + resource: '*' + - - action: transfer:StartRemoteDelete + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-connector-remote-directory-move-and-delete-capability-pivot + scope: same_account + aggregate_as: Verified Remote SFTP connector identity and its authorized remote directory capability in {account} + grants: + - Remote SFTP connector identity and its authorized remote directory capability + conditions: + - id: exact_verified_prerequisites + description: Existing connector and stored credential, reachable remote path; listing also needs connector-role S3 output and attacker read access to result. StartRemoteMove and StartRemoteDelete are independent alternatives on the exact connector ARN. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/transfer/latest/userguide/custom-lambda-idp.html + - https://docs.aws.amazon.com/transfer/latest/userguide/authentication-api-gateway.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. +- id: aws-s05-logsfilterlogevents-logsgetlogevents-recover-custom-idp-passwords-from + provider: aws + service: transfer + title: '`logs:FilterLogEvents` / `logs:GetLogEvents` — recover custom-IdP passwords from logs' + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-transfer-family-post-exploitation/README.md#logsfilterlogevents--logsgetlogevents--recover-custom-idp-passwords-from-logs + source_revision: 0b36331 + summary: The source may obtain Transfer custom-IdP user identity when the exact documented prerequisite is verified. + requires: + any_of: + - - action: logs:FilterLogEvents + resource: '*' + - - action: logs:GetLogEvents + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-logsfilterlogevents-logsgetlogevents-recover-custom-idp-passwords-from + scope: same_account + aggregate_as: Verified Transfer custom-IdP user identity in {account} + grants: + - Transfer custom-IdP user identity + conditions: + - id: exact_verified_prerequisites + description: Known Lambda/API Gateway custom-IdP log group actually contains plaintext passwords; GetLogEvents on a known stream is an alternative. Password login still must work. Existing exclusion is false for service identity takeover. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/transfer/latest/userguide/custom-lambda-idp.html + - https://docs.aws.amazon.com/transfer/latest/userguide/authentication-api-gateway.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. diff --git a/src/privilege-escalation-paths/aws/verifiedpermissions.yaml b/src/privilege-escalation-paths/aws/verifiedpermissions.yaml new file mode 100644 index 0000000000..06b7942682 --- /dev/null +++ b/src/privilege-escalation-paths/aws/verifiedpermissions.yaml @@ -0,0 +1,35 @@ +- id: aws-s05-delete-or-corrupt-the-authorization-store + provider: aws + service: verifiedpermissions + title: Delete or corrupt the authorization store + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-verified-permissions-post-exploitation/README.md#delete-or-corrupt-the-authorization-store + source_revision: 0b36331 + summary: The source may obtain Application action authorized by a proven fail-open integration when the exact documented prerequisite is verified. + requires: + any_of: + - - action: verifiedpermissions:DeletePolicy + resource: '*' + - - action: verifiedpermissions:DeletePolicyStore + resource: '*' + - - action: verifiedpermissions:UpdatePolicy + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-delete-or-corrupt-the-authorization-store + scope: same_account + aggregate_as: Verified Application action authorized by a proven fail-open integration in {account} + grants: + - Application action authorized by a proven fail-open integration + conditions: + - id: exact_verified_prerequisites + description: Specific policy/template/schema/identity-source mutation and a confirmed application integration that treats the resulting denial/evaluation error as allow. Default Verified Permissions decision remains deny; no edge without fail-open proof. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/verifiedpermissions/latest/apireference/API_Operations.html + - https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/monitoring-cloudtrail.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. diff --git a/src/privilege-escalation-paths/aws/vpc-lattice.yaml b/src/privilege-escalation-paths/aws/vpc-lattice.yaml new file mode 100644 index 0000000000..f3d1d0f41a --- /dev/null +++ b/src/privilege-escalation-paths/aws/vpc-lattice.yaml @@ -0,0 +1,31 @@ +- id: aws-s05-vpc-latticecreateservicenetworkvpcassociation-obtain-network-reachabil + provider: aws + service: vpc-lattice + title: '`vpc-lattice:CreateServiceNetworkVpcAssociation` — obtain network reachability into a service network' + 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 + source_revision: 0b36331 + summary: The source may obtain Network reachability from associated VPC into exact Lattice service network when the exact documented prerequisite is verified. + requires: + all_of: + - action: vpc-lattice:CreateServiceNetworkVpcAssociation + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-vpc-latticecreateservicenetworkvpcassociation-obtain-network-reachabil + scope: same_account + aggregate_as: Verified Network reachability from associated VPC into exact Lattice service network in {account} + grants: + - Network reachability from associated VPC into exact Lattice service network + conditions: + - id: exact_verified_prerequisites + description: Attacker controls compute in a VPC that can be associated; service/network IAM auth policy, vpc-lattice-svcs:Invoke, and application auth still gate requests. Existing exclusion ignores the gained network-plane authorization. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/vpc-lattice/latest/ug/what-is-vpc-lattice.html + - https://docs.aws.amazon.com/vpc-lattice/latest/APIReference/API_PutAuthPolicy.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. diff --git a/src/privilege-escalation-paths/aws/waf.yaml b/src/privilege-escalation-paths/aws/waf.yaml new file mode 100644 index 0000000000..d57f6ebe80 --- /dev/null +++ b/src/privilege-escalation-paths/aws/waf.yaml @@ -0,0 +1,33 @@ +- id: aws-s05-wafv2tagresource-wafv2untagresource + provider: aws + service: waf + title: '**`wafv2:TagResource`, `wafv2:UntagResource`**' + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#wafv2tagresource-wafv2untagresource + source_revision: 0b36331 + summary: The source may obtain Additional WAF administration allowed by tag-conditioned policy when the exact documented prerequisite is verified. + requires: + any_of: + - - action: wafv2:TagResource + resource: '*' + - - action: wafv2:UntagResource + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-wafv2tagresource-wafv2untagresource + scope: same_account + aggregate_as: Verified Additional WAF administration allowed by tag-conditioned policy in {account} + grants: + - Additional WAF administration allowed by tag-conditioned policy + conditions: + - id: exact_verified_prerequisites + description: Only when a policy or automation actually gates a stronger WAF action on mutable tags. Existing exclusion treats all tagging as harmless despite page warning that tags can gate access; absent ABAC evidence there is no edge. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/waf/latest/APIReference/API_DeleteWebACL.html + - https://docs.aws.amazon.com/waf/latest/developerguide/logging-fields.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. diff --git a/src/privilege-escalation-paths/aws/wickr.yaml b/src/privilege-escalation-paths/aws/wickr.yaml index 177abd6e61..0e26d9408f 100644 --- a/src/privilege-escalation-paths/aws/wickr.yaml +++ b/src/privilege-escalation-paths/aws/wickr.yaml @@ -32,3 +32,96 @@ no definite privilege edge. references: - https://cloud.hacktricks.wiki/pentesting-cloud/aws-security/aws-privilege-escalation/aws-wickr-privesc/ +- id: aws-s05-wickrgetoidcinfo-disclose-the-sso-client-secret + provider: aws + service: wickr + title: '`wickr:GetOidcInfo` — disclose the SSO client secret' + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrgetoidcinfo--disclose-the-sso-client-secret + source_revision: 0b36331 + summary: The source may obtain Wickr integration OAuth client identity when the exact documented prerequisite is verified. + requires: + all_of: + - action: wickr:GetOidcInfo + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-wickrgetoidcinfo-disclose-the-sso-client-secret + scope: same_account + aggregate_as: Verified Wickr integration OAuth client identity in {account} + grants: + - Wickr integration OAuth client identity + conditions: + - id: exact_verified_prerequisites + description: Exact network is configured for this credential; secret/code is returned and remains usable. OIDC use still needs an allowed grant/code; invite code must be pending, unexpired and unconsumed. Existing exclusion says no AWS principal while the page explicitly documents a separate service identity. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/wickr/latest/APIReference/API_RegisterOidcConfig.html + - https://docs.aws.amazon.com/wickr/latest/APIReference/API_GetOidcInfo.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. +- id: aws-s05-wickrgetopentdfconfig-disclose-the-opentdf-client-secret + provider: aws + service: wickr + title: '`wickr:GetOpentdfConfig` — disclose the OpenTDF client secret' + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrgetopentdfconfig--disclose-the-opentdf-client-secret + source_revision: 0b36331 + summary: The source may obtain OpenTDF OAuth client identity when the exact documented prerequisite is verified. + requires: + all_of: + - action: wickr:GetOpentdfConfig + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-wickrgetopentdfconfig-disclose-the-opentdf-client-secret + scope: same_account + aggregate_as: Verified OpenTDF OAuth client identity in {account} + grants: + - OpenTDF OAuth client identity + conditions: + - id: exact_verified_prerequisites + description: Exact network is configured for this credential; secret/code is returned and remains usable. OIDC use still needs an allowed grant/code; invite code must be pending, unexpired and unconsumed. Existing exclusion says no AWS principal while the page explicitly documents a separate service identity. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/wickr/latest/APIReference/API_RegisterOidcConfig.html + - https://docs.aws.amazon.com/wickr/latest/APIReference/API_GetOidcInfo.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. +- id: aws-s05-wickrlistusers-recover-an-invited-users-enrollment-code + provider: aws + service: wickr + title: '`wickr:ListUsers` — recover an invited user''s enrollment code' + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-wickr-post-exploitation/README.md#wickrlistusers--recover-an-invited-users-enrollment-code + source_revision: 0b36331 + summary: The source may obtain Pending Wickr invited user identity when the exact documented prerequisite is verified. + requires: + all_of: + - action: wickr:ListUsers + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-wickrlistusers-recover-an-invited-users-enrollment-code + scope: same_account + aggregate_as: Verified Pending Wickr invited user identity in {account} + grants: + - Pending Wickr invited user identity + conditions: + - id: exact_verified_prerequisites + description: Exact network is configured for this credential; secret/code is returned and remains usable. OIDC use still needs an allowed grant/code; invite code must be pending, unexpired and unconsumed. Existing exclusion says no AWS principal while the page explicitly documents a separate service identity. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/wickr/latest/APIReference/API_RegisterOidcConfig.html + - https://docs.aws.amazon.com/wickr/latest/APIReference/API_GetOidcInfo.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. diff --git a/src/privilege-escalation-paths/aws/workmail.yaml b/src/privilege-escalation-paths/aws/workmail.yaml new file mode 100644 index 0000000000..f7b1d19196 --- /dev/null +++ b/src/privilege-escalation-paths/aws/workmail.yaml @@ -0,0 +1,66 @@ +- id: aws-s05-abusing-workmail-to-bypass-ses-sandbox + provider: aws + service: workmail + title: Abusing WorkMail to bypass SES sandbox + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workmail-post-exploitation/README.md#abusing-workmail-to-bypass-ses-sandbox + source_revision: 0b36331 + summary: The source may obtain New WorkMail mailbox login identity when the exact documented prerequisite is verified. + requires: + all_of: + - action: workmail:RegisterMailDomain + resource: '*' + - action: workmail:CreateUser + resource: '*' + - action: workmail:RegisterToWorkMail + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-abusing-workmail-to-bypass-ses-sandbox + scope: same_account + aggregate_as: Verified New WorkMail mailbox login identity in {account} + grants: + - New WorkMail mailbox login identity + conditions: + - id: exact_verified_prerequisites + description: Existing WorkMail organization; attacker DNS control and domain verification; chosen mailbox password; optional CreateOrganization and its directory prerequisites for new org. This is newly created application identity, not existing mailbox takeover. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/workmail/latest/adminguide/workmail_limits.html + - https://docs.aws.amazon.com/ses/latest/dg/request-production-access.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. +- id: aws-s05-workmailmessageflowgetrawmessagecontent-putrawmessagecontent-steal-or + provider: aws + service: workmail + title: '`workmailmessageflow:GetRawMessageContent` / `PutRawMessageContent` — steal or rewrite in-transit email' + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workmail-post-exploitation/README.md#workmailmessageflowgetrawmessagecontent--putrawmessagecontent--steal-or-rewrite-in-transit-email + source_revision: 0b36331 + summary: The source may obtain Identity associated with valid password-reset link or credential when the exact documented prerequisite is verified. + requires: + all_of: + - action: workmailmessageflow:GetRawMessageContent + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-workmailmessageflowgetrawmessagecontent-putrawmessagecontent-steal-or + scope: same_account + aggregate_as: Verified Identity associated with valid password-reset link or credential in {account} + grants: + - Identity associated with valid password-reset link or credential + conditions: + - id: exact_verified_prerequisites + description: Known valid message ID, matching message ARN, within 24-hour window; content actually contains usable identity material. PutRawMessageContent is an integrity path requiring synchronous flow and S3 object, not a prerequisite for theft. Existing exclusion ignores documented credentials/reset links. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/workmail/latest/adminguide/workmail_limits.html + - https://docs.aws.amazon.com/ses/latest/dg/request-production-access.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. diff --git a/src/privilege-escalation-paths/aws/workspaces-web.yaml b/src/privilege-escalation-paths/aws/workspaces-web.yaml new file mode 100644 index 0000000000..2f642fa5e9 --- /dev/null +++ b/src/privilege-escalation-paths/aws/workspaces-web.yaml @@ -0,0 +1,38 @@ +- id: aws-s05-disable-inline-redaction + provider: aws + service: workspaces-web + title: Disable inline redaction + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-web-post-exploitation/README.md#disable-inline-redaction + source_revision: 0b36331 + summary: The source may obtain Credential revealed through disabled browser redaction when the exact documented prerequisite is verified. + requires: + all_of: + - action: workspaces-web:UpdateDataProtectionSettings + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-disable-inline-redaction + scope: same_account + aggregate_as: Verified Credential revealed through disabled browser redaction in {account} + grants: + - Credential revealed through disabled browser redaction + conditions: + - id: exact_verified_prerequisites + description: Exact attached settings, later authenticated session views a page containing data that matching redaction had hidden. No direct AWS IAM credential claim without content evidence. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - "https:///metadata\n```\n\nAfter configuring the returned WorkSpaces service-provider values in the attacker's IdP, that IdP can issue assertions for identities it controls. WorkSpaces Web still validates the SAML/OIDC protocol fields; the attack is the deliberate replacement of the trust anchor, not an assertion validation bypass.\n\n**Minimum permissions and prerequisites:** For a new provider, `workspaces-web:CreateIdentityProvider` on the target portal and prospective identity-provider resource patterns; for replacement, `UpdateIdentityProvider` on both the portal and exact provider ARNs. The portal must use standard federation rather than the IAM Identity Center-only setup, and the attacker must operate a compatible IdP. Both actions pass IAM authorization.\n\n**Impact:** Establish an independent portal login path that survives rotation of the original IdP credentials and grants access to internal applications reachable from the secure-browser network.\n\n**Stealth:**\ + \ Medium. The trust change is visible in management events and provider inventory, but later authentication appears to use a configured provider.\n\n
\nLogs generated\n\n| Event/evidence | Visibility and detection |\n| --- | --- |\n| `CreateIdentityProvider` / `UpdateIdentityProvider` | Default CloudTrail management events with portal/provider ARNs, type and metadata configuration. |\n| Portal authentication | Session/User Access logs can show usernames, sessions and source IPs if logging remains attached. |\n| Current trust | Inventory `ListIdentityProviders` and `GetIdentityProvider`; verify metadata URLs, issuer/audience, provider type and approved certificate fingerprints. |\n\n
\n\n### Re-enable clipboard, download, upload and print channels\n\n`UpdateUserSettings` can turn the main host/session transfer controls back on:\n\n```bash\naws workspaces-web update-user-settings \\\n --user-settings-arn \\\n --copy-allowed Enabled\ + \ \\\n --paste-allowed Enabled \\\n --download-allowed Enabled \\\n --upload-allowed Enabled \\\n --print-allowed Enabled \\\n --deep-link-allowed Enabled\n```\n\nThis converts a locked-down “view only” portal into a practical extraction path for a malicious or compromised user. Cookie-synchronization and toolbar configuration also live on this resource and must be reviewed when it changes.\n\n**Minimum permissions and prerequisites:** `workspaces-web:UpdateUserSettings` on an attached user-settings ARN and a user/session that can already reach valuable content. Creating or attaching a different resource additionally requires `CreateUserSettings` and `AssociateUserSettings` on the portal and settings ARNs. The update action alone passes IAM authorization.\n\n**Impact:** Export of rendered data or files from applications reachable only through the isolated browser, and import of attacker-controlled content into those applications.\n\n**Stealth:** Medium. The settings write is visible,\ + \ while permitted clipboard and file use is not recorded by CloudTrail. Session Logger can record transfer metadata when it remains enabled, but not clipboard contents or file contents.\n\n
\nLogs generated\n\n| Event/evidence | Visibility and detection |\n| --- | --- |\n| `UpdateUserSettings` | Default CloudTrail management event containing the changed transfer, deep-link, toolbar and cookie-synchronization configuration. |\n| `AssociateUserSettings` | Default management event if an alternate resource is attached to the portal. |\n| File/clipboard activity | Session Logger can record selected transfer event types and filenames/sizes; it deliberately omits transferred content. |\n| Current settings | Reconcile `GetUserSettings` against an approved baseline. |\n\n
\n\n## Telemetry tampering\n\n### Redirect or disable session and URL logging\n\nWorkSpaces Web offers a broad Session Logger to S3 and a narrower User Access log to Kinesis. `UpdateSessionLogger`\ + \ can send future session metadata to another accepted bucket, while the two `Disassociate*` actions remove the logging resources from a portal:\n\n```bash\naws workspaces-web update-session-logger \\\n --session-logger-arn \\\n --log-configuration '{\n \"s3\":{\n \"bucket\":\"\",\n \"keyPrefix\":\"portal/\",\n \"bucketOwner\":\"\",\n \"logFileFormat\":\"JSONLines\",\n \"folderStructure\":\"NestedByDate\"\n }\n }'\n\naws workspaces-web disassociate-session-logger --portal-arn \naws workspaces-web disassociate-user-access-logging-settings --portal-arn \n```\n\nSession Logger records usernames, client/portal IPs, session IDs, full visited URLs and metadata about interactions, printing, clipboard direction, uploads and downloads. AWS states that it does not record clipboard content or transferred file content. User Access logging records start/end and URL visits,\ + \ but URL history can already miss incognito or deleted-history activity.\n\n**Minimum permissions and prerequisites:** For redirection, `workspaces-web:UpdateSessionLogger` on the attached logger ARN and a destination that accepts the WorkSpaces Web service's writes; satisfy the S3/KMS and expected-owner checks for that bucket. Updating the Kinesis path instead uses `UpdateUserAccessLoggingSettings` on its settings ARN and a usable stream. Blinding needs the relevant `DisassociateSessionLogger` or `DisassociateUserAccessLoggingSettings` permission on the portal ARN. Each WorkSpaces Web action independently reached the not-found boundary with only the corresponding action allowed.\n\n**Impact:** Collect future browsing/session metadata in an attacker-readable destination, or remove the defender's detailed record before other portal activity. This is metadata collection, not clipboard or file-content capture.\n\n**Stealth:** Medium. The configuration writes are high-signal management\ + \ events, but after disassociation there is no native session stream to report the browsing that follows.\n\n
\nLogs generated\n\n| Event/evidence | Visibility and detection |\n| --- | --- |\n| `UpdateSessionLogger` / `UpdateUserAccessLoggingSettings` | Default CloudTrail management events containing the destination. Alert on bucket owner, bucket/prefix, stream account and filter changes. |\n| `DisassociateSessionLogger` / `DisassociateUserAccessLoggingSettings` | Default management events; treat either as the last reliable control-plane detection point. |\n| S3 delivery | S3 object data events only when the destination is selected by a trail; bucket policy and access logs provide additional evidence. |\n| Kinesis delivery | Kinesis data-plane visibility depends on the account's selected telemetry; monitor stream policy and consumer changes separately. |\n| Delivery failures | Session Logger publishes target-not-found and access-denied CloudWatch metrics. |\n\ + \n
\n\n## References\n\n- [WorkSpaces Secure Browser service authorization](https://docs.aws.amazon.com/service-authorization/latest/reference/list_workspaces-web.html" + - https://docs.aws.amazon.com/workspaces-web/latest/adminguide/browser-policies-custom.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. diff --git a/src/privilege-escalation-paths/aws/workspaces.yaml b/src/privilege-escalation-paths/aws/workspaces.yaml index ba2d5e398c..391a7058a2 100644 --- a/src/privilege-escalation-paths/aws/workspaces.yaml +++ b/src/privilege-escalation-paths/aws/workspaces.yaml @@ -48,3 +48,67 @@ - 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. +- id: aws-s05-workspacesupdateworkspaceimagepermission-share-a-custom-image-with-an + provider: aws + service: workspaces + title: '`workspaces:UpdateWorkspaceImagePermission` — share a custom image with an attacker account' + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-post-exploitation/README.md#workspacesupdateworkspaceimagepermission--share-a-custom-image-with-an-attacker-account + source_revision: 0b36331 + summary: The source may obtain Identity associated with valid secret in copied WorkSpace image when the exact documented prerequisite is verified. + requires: + all_of: + - action: workspaces:UpdateWorkspaceImagePermission + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-workspacesupdateworkspaceimagepermission-share-a-custom-image-with-an + scope: same_account + aggregate_as: Verified Identity associated with valid secret in copied WorkSpace image in {account} + grants: + - Identity associated with valid secret in copied WorkSpace image + conditions: + - id: exact_verified_prerequisites + description: Exact custom image shared for copy to attacker account, attacker copies it, and disk actually holds still-valid secrets. Existing exclusion ignores documented secret and domain-credential theft; no definite IAM edge from share alone. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/workspaces/latest/api/API_UpdateWorkspaceImagePermission.html + - https://docs.aws.amazon.com/workspaces/latest/adminguide/share-custom-image.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. +- id: aws-s05-workspacesmodifysamlproperties-modifycertificatebasedauthproperties-we + provider: aws + service: workspaces + title: '`workspaces:ModifySamlProperties` / `ModifyCertificateBasedAuthProperties` — weaken desktop authentication' + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-workspaces-post-exploitation/README.md#workspacesmodifysamlproperties--modifycertificatebasedauthproperties--weaken-desktop-authentication + source_revision: 0b36331 + summary: The source may obtain Victim WorkSpaces desktop session when the exact documented prerequisite is verified. + requires: + any_of: + - - action: workspaces:ModifySamlProperties + resource: '*' + - - action: workspaces:ModifyCertificateBasedAuthProperties + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-s05-workspacesmodifysamlproperties-modifycertificatebasedauthproperties-we + scope: same_account + aggregate_as: Verified Victim WorkSpaces desktop session in {account} + grants: + - Victim WorkSpaces desktop session + conditions: + - id: exact_verified_prerequisites + description: Exact directory/workspace auth configuration accepts attacker-controlled IdP assertion or downgraded certificate path, and victim desktop access actually succeeds. ModifyCertificateBasedAuthProperties is an independent alternative; ModifyWorkspaceAccessProperties only changes device/network restrictions. Missing or unverified evidence is UNKNOWN and must not emit a definite edge. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict the listed action on the exact resource and remove unnecessary access. + references: + - https://docs.aws.amazon.com/workspaces/latest/api/API_UpdateWorkspaceImagePermission.html + - https://docs.aws.amazon.com/workspaces/latest/adminguide/share-custom-image.html + notes: Requires an exact source/target evidence record; absent facts remain UNKNOWN. From ceecc48edf1eea43b9897c43f8f2b9de1517cfb4 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Mon, 12 Oct 2026 20:50:46 +0200 Subject: [PATCH 05/17] Integrate verified AWS persistence and unauthenticated paths Co-Authored-By: Codex --- .../aws/_excluded_audit_6fb9.yaml | 199 ++++++- .../aws/_excluded_refresh_g6.yaml | 19 +- .../aws/_excluded_v4.yaml | 29 +- .../aws/_excluded_verify_a66f.yaml | 108 ++-- .../aws/challenge-v3.yaml | 504 +++++++++++++++--- 5 files changed, 707 insertions(+), 152 deletions(-) diff --git a/src/privilege-escalation-paths/aws/_excluded_audit_6fb9.yaml b/src/privilege-escalation-paths/aws/_excluded_audit_6fb9.yaml index 7de6acac78..ab813d77f0 100644 --- a/src/privilege-escalation-paths/aws/_excluded_audit_6fb9.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_audit_6fb9.yaml @@ -80,14 +80,13 @@ 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 +- 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. + reason: Most matrix rows grant data access, injection, or persistence rather than a new principal. AMIs, snapshots, + and golden images may contain credentials, but the snapshot does not reveal their contents or prove any embedded + key is live and belongs to a privileged identity. AWS Signer profile sharing can delegate signing authority; + model it separately when the catalog can target a trusted signing profile. Existing role-bearing routes remain + covered by their service entries. source_revision: 6fb9ac51fd - source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/resource-policy-and-shared-resource-attacks.md#messaging-and-event-injection @@ -166,10 +165,11 @@ 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 +- 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. + reason: The reachable agent proxies configuration reads without handing over its IAM role credentials. Returned + configuration may contain embedded secrets; obtaining a separate identity requires inspecting those bytes and + validating a specific credential, which the snapshot cannot infer. 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 @@ -290,3 +290,182 @@ - source: src/pentesting-cloud/aws-security/aws-persistence/aws-directory-service-persistence/README.md#using-an-ad-user technique: AD user creation/change and IAM console role assignment reason: The paragraph describes an authorized operator, not a specific AWS API permission path. Gaining a mapped role requires AD/LDAP user-write or password rights, group-membership or console role-assignment rights, an effective user/group-to-role mapping, and a working directory sign-in; those host/directory facts are not present in the IAM snapshot. The password-reset subpath is already aws-ds-resetuserpassword. +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-managed-flink-persistence/README.md#runtime-property-configuration-implant + technique: Flink runtime-property configuration implant + reason: The property change yields role or credential authority only if the deployed application code reads the + exact property and routes a privileged operation or credential to the attacker. DescribeApplication exposes + values but not the code path or runtime effect; an arbitrary property has no effect. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-api-gateway-unauthenticated-enum/README.md#api-invoke-bypass + technique: Lambda-authorizer execution-ARN wildcard accepts routes, verbs, stages, or APIs beyond intended application + grant + reason: The overbroad execute-api policy is returned by Lambda authorizer code at request time, and the attacker + must pass its other checks. Static API/Lambda configuration cannot prove the returned policy, intended route + boundaries, or a privilege gain. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-appsync-unauthenticated-enum/README.md#appsync-api-keys + technique: Leaked AppSync API key grants that GraphQL API's authorized operations + reason: A regex hit in an owned artifact does not prove a complete, unexpired AppSync key, API binding, allowed + field, or successful authentication. Requires artifact content, key validity, and resolver authorization facts + beyond the configuration snapshot. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-appsync-unauthenticated-enum/README.md#appsync-key-assignments + technique: Contextual x-api-key/appsync_apiKey assignment exposes the same scoped API capability + reason: This contextual assignment is another detector for the same AppSync API-key exposure as gap-04. The header + can belong to another service; artifact context, live key validity, and allowed operations are needed. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-connect-participant-unauthenticated-enum/README.md#connect-participantconnection-tokens + technique: Leaked live participant or connection token grants one chat participant's transcript/message/attachment + capability + reason: The page documents a bearer capability for one chat participant, but the complete token, expiry, contact + binding, and permitted operations are runtime facts. The cloud configuration snapshot cannot infer that an attacker + has a live token. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-device-farm-unauthenticated/README.md#remote-access-and-testgrid-endpoint-urls + technique: Leaked live signed Device Farm endpoint URL grants a scoped device/browser session + reason: Only a complete active signed Device Farm URL authorizes a specific session. URL leakage, expiry, and + session binding require content/runtime evidence; project or session ARNs alone confer nothing. aws-v3-16 uses + an IAM GetRemoteAccessSession path, so it is not equivalent. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-ec2-unauthenticated-enum/README.md#public-amis--ebs-snapshots + technique: Public AMI or EBS snapshot can be copied/restored and inspected for embedded credentials + reason: Public AMI/snapshot sharing permits disk-data access. Identity gain requires an embedded credential and + proof it is still valid; neither follows from the public-share configuration. This matches the content limitation + in the EBS direct-snapshot-read exclusion. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-ecr-unauthenticated-enum/README.md#public-registry-repositories-images + technique: Anonymous pull of public image may expose embedded credentials + reason: Anonymous public ECR pull grants image data only. Recovering another identity requires scanning image + layers/metadata and validating a specific embedded credential; publication alone is insufficient. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-edge-origin-bypass/README.md#aws-waf-x-forwarded-for-client-ip-spoofing + technique: Client-supplied first X-Forwarded-For IP can cross a WAF IP allowlist for protected application paths + reason: The page specifically gives an admin/staging path protected only by a WAF forwarded-IP allowlist. A spoofed + header can cross that application gate, but the exact WAF rule, proxy sanitization, path authorization, and + successful route access need application/request facts outside the principal snapshot. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-eks-unauthenticated-enum/README.md#kubeconfig-credentials + technique: Leaked kubeconfig with a static bearer token or client certificate/private key authenticates as its + K8s identity + reason: A kubeconfig yields a Kubernetes identity only when it contains a complete valid static token or client + certificate/private key accepted by the cluster. Artifact leak, authenticator binding, expiry, and RBAC grant + are not inferable from EKS configuration; an exec-plugin or server URL is insufficient. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-eks-unauthenticated-enum/README.md#bearer-identity-tokens + technique: Leaked valid bearer token authenticates only as the represented scoped Kubernetes identity + reason: A JWT-shaped match is not proof of signature, audience, expiry, or Kubernetes identity. Only a validated + leaked bearer token accepted by the exact cluster could confer the represented scoped identity; the content + and runtime facts are unavailable. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-dynamodb-unauthenticated-access/README.md#cognito-guest-identities-for-dynamodb + technique: Cognito guest role DynamoDB access + reason: The guest IAM-role acquisition is already covered by aws-v3-59-anonymous-cognito-guest-role. DynamoDB + access is a subsequent ordinary signed action limited by that role policies and Cognito session scope-down; + it creates no second identity edge. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-elb-unauthenticated-access/README.md#listener-rule-shadowing--auth-bypass + technique: Earlier broad ALB listener rule shadows authenticate-oidc/cognito rule + reason: The earlier forwarding rule can bypass ALB authentication for a route; a privilege edge needs the backend + route to grant an application identity, secret or privileged action, which requires handler and session behavior + absent from the snapshot. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-elb-unauthenticated-access/README.md#source-ip-restrictions-can-be-bypassed-through-alternate-paths + technique: Reach restricted backend through alternate listener/LB/direct IP + reason: An alternate route can bypass one listener rule’s IP filter; whether this grants privilege depends on + the backend’s authorization and the live network path, not on the listener rule alone. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-elb-unauthenticated-access/README.md#client-controlled-x-forwarded-for-trust + technique: Spoof client IP through preserved X-Forwarded-For + reason: Preserving X-Forwarded-For allows header spoofing; a privilege edge needs the application to trust that + value for authorization and expose a privileged action, which requires application logic and request behavior. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-gamelift-streams-unauthenticated-access/README.md#gamelift-streams-stream-urls + technique: Use leaked active stream URL + reason: The full active stream URL must leak and remain valid; a stream-group identifier and static IAM/configuration + facts cannot prove possession of this session bearer credential. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-invoicing-and-billing-unauthenticated-access/README.md#s3-presigned-urls + technique: Use leaked invoice S3 presigned URL + reason: The full signed URL must leak and remain valid for the specific S3 object and HTTP method; the URL grants + only document access and cannot be inferred from a configuration snapshot. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-invoicing-and-billing-unauthenticated-access/README.md#procurement-integration-shared-secrets + technique: Use leaked ProcurementPortalSharedSecret + reason: The actual ProcurementPortalSharedSecret must leak and the external portal must accept it; its protocol, + activation and network controls are external runtime facts, and it does not authenticate the AWS Invoicing API. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-ivs-unauthenticated-access/README.md#ivs-stream-keys + technique: Use leaked IVS stream key + reason: The full active IVS stream key must leak; a channel identifier or static configuration cannot prove possession + of a media-plane publishing credential or its current validity. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-ivs-unauthenticated-access/README.md#ivs-participantplayback-tokens + technique: Use leaked IVS participant token + reason: The signed participant token must leak and its stage, capability and expiry must validate; static IAM/configuration + does not establish possession of this media-plane token. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-kinesis-video-unauthenticated-enum/README.md#kinesis-playback-session-urls + technique: Use leaked HLS/DASH SessionToken URL + reason: The full URL and live SessionToken must leak; an endpoint hostname does not authorize playback, and the + token is runtime session state. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-kinesis-video-unauthenticated-enum/README.md#iceturn-credentials + technique: Use leaked ICE/TURN username and password + reason: Both temporary TURN username and password must leak and remain valid for the relay allocation; the endpoint + and configuration alone establish neither fact. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-location-service-unauthenticated-enum/README.md#amazon-location-api-keys + technique: Use leaked Location API key + reason: The actual Location API key must be disclosed and valid for the requested action, resource, region and + restrictions; client-side key exposure can be intentional and grants no IAM identity. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-managed-blockchain-unauthenticated-enum/README.md#managed-blockchain-accessor-tokens + technique: Use leaked BILLING_TOKEN accessor + reason: The active full BILLING_TOKEN must leak and remain usable; an accessor ID or configuration inventory cannot + prove possession of this blockchain API bearer credential. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-memorydb-unauthenticated-access/README.md#passwordless-access-through-the-open-access-acl + technique: Read MemoryDB through open-access ACL and recover stored credentials + reason: The open-access ACL permits unauthenticated data access only with a live private-network route and security-group + access. Credential escalation further requires a stored, valid secret mapped to a stronger principal; arbitrary + MemoryDB key contents and external credential validity are unavailable from AWS configuration APIs. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-quicksight-unauthenticated-enum/README.md#quicksight-anonymous-viewer-embed-urls + technique: Use a leaked QuickSight anonymous-viewer embed URL + reason: A private embed URL is a bearer session, but actual URL disclosure, expiry, authorized dashboard scope, + and private versus public sharing are runtime facts; a URL pattern or QuickSight policy cannot prove them. +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-quicksight-unauthenticated-enum/README.md#q-business-web-experience-session-urls + technique: Use a leaked Q Business web-experience session URL + reason: A generated URL can be a Q Business session credential, but disclosure, validity, application scope, and + whether the experience is already public require runtime URL and application evidence. +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-security-incident-response-unauthenticated-access/README.md#s3-presigned-urls + technique: Use a leaked Security IR S3 attachment presigned URL + reason: The presigned URL is a bearer capability for one S3 object and method; its disclosure, signature validity, + expiry, signer permissions, and object scope are runtime facts. +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-subdomain-takeover/README.md#elastic-beanstalk-environment-takeover + technique: Claim a dangling Elastic Beanstalk CNAME + reason: Taking the victim hostname requires a live dangling CNAME and an available matching Beanstalk environment + name; gaining sessions additionally requires victim traffic and exposed session material, none of which follows + from IAM configuration. +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-subdomain-takeover/README.md#s3-bucket--static-website-takeover + technique: Claim a dangling S3 bucket or website endpoint + reason: Taking the victim hostname requires a dangling DNS record, deleted matching bucket, and successful bucket + claim in the original region; session theft further requires victim traffic and session material. +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-subdomain-takeover/README.md#route53-ns-delegation--dangling-hosted-zone-takeover + technique: Match dangling Route 53 NS delegation + reason: Delegated DNS control requires stale parent NS records, an unclaimed or deleted hosted zone, and assignment + of the matching nameserver set; credential gain through email interception also requires delivered sensitive + messages. +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-subdomain-takeover/README.md#ec2-elastic-ip-re-allocation-takeover + technique: Reacquire an IP targeted by a dangling A record + reason: Taking the victim hostname requires a stale A record, released address, and successful reallocation of + that exact regional IP; gaining a session further requires victim traffic and exposed session material. +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-timestream-influxdb-unauthenticated-enum/README.md#endpoint-discovery-and-authenticated-database-access + technique: Guess a weak Timestream for InfluxDB native credential + reason: The public endpoint and health/version response only prove reachability and reconnaissance. Native InfluxDB + access requires an actually valid guessed, weak, or leaked token/password and successful authentication, which + are runtime facts. +- source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-timestream-influxdb-unauthenticated-enum/README.md#influxdb-token-and-password-assignments + technique: Use a leaked InfluxDB token or password + reason: The regex finds candidate InfluxDB token/password assignments; artifact content, disclosure to the attacker, + token validity, native permissions, and network reachability require runtime evidence. diff --git a/src/privilege-escalation-paths/aws/_excluded_refresh_g6.yaml b/src/privilege-escalation-paths/aws/_excluded_refresh_g6.yaml index e8e1337784..5890336e96 100644 --- a/src/privilege-escalation-paths/aws/_excluded_refresh_g6.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_refresh_g6.yaml @@ -181,19 +181,18 @@ 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 +- 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). + reason: The AWS snapshot does not contain the application-to-store binding, a controlled login principal, requested + action/resource, and complete effective Cedar decision including forbids. source_revision: 171e422299 -- source: - src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-verified-permissions-privesc/README.md#redirect-token-trust-with-updateidentitysource +- 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. + reason: Application integration and token decision facts are absent from the AWS snapshot; the store configuration + alone cannot prove a token is accepted as a privileged application principal. source_revision: 171e422299 -- source: - src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-verified-permissions-privesc/README.md#rebind-a-policy-store-alias-to-a-permissive-store +- 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. + reason: The AWS snapshot can show an alias mapping but cannot establish which application resolves the alias or + that the selected store permits a privileged action for an attacker-controlled principal. source_revision: 171e422299 diff --git a/src/privilege-escalation-paths/aws/_excluded_v4.yaml b/src/privilege-escalation-paths/aws/_excluded_v4.yaml index 43237c64e9..e572d5811c 100644 --- a/src/privilege-escalation-paths/aws/_excluded_v4.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_v4.yaml @@ -229,12 +229,12 @@ reason: StartPipelineExecution overrides parameter values. Privileged effects require a pipeline definition and step code that pass those values into a sensitive command, resource or destination without safe validation; IAM permission alone does not establish that data flow. -- source: - src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-secrets-manager-privesc/README.md#secretsmanagergetresourcepolicy-secretsmanagerputresourcepolicy-secretsmanagerlistsecrets - source_revision: a53b46392c +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-secrets-manager-privesc/README.md#secretsmanagergetresourcepolicy-secretsmanagerputresourcepolicy-secretsmanagerlistsecrets + source_revision: 0b36331 technique: secretsmanager:PutResourcePolicy - reason: PutResourcePolicy can self-grant secret read to a same-account IAM user. Another identity follows only if the - secret contains a live usable credential and KMS allows decrypt; policy metadata alone does not reveal those facts. + reason: PutResourcePolicy may grant a named external principal secret-value read when its own identity policy + and KMS policy permit it. Whether the plaintext is a usable credential for a particular principal requires secret-content + and account linkage; the policy alone does not prove identity takeover. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-service-catalog-privesc/README.md#sensitive-cloudformation-outputs-with-servicecataloggetprovisionedproductoutputs source_revision: a53b46392c @@ -252,12 +252,11 @@ technique: sns:AddPermission reason: AddPermission grants selected SNS actions to an account on this topic. The page documents topic access/manipulation, not another principal or credential beyond topic-scoped permissions. -- source: - src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sns-privesc/README.md#snssettopicattributes--grant-subscribe-access-to-a-controlled-iam-user +- 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: SetTopicAttributes can grant a same-account user Subscribe on this topic and future message delivery. This - resource-scoped grant does not itself identify a credential or another principal. - source_revision: 171e422299 + reason: SetTopicAttributes can grant Publish and Subscribe to external principals on one topic; the page’s SourceOwner-conditioned + management statement is effective only for matching owner context. Topic-scoped actions are not IAM role authority. + source_revision: 0b36331 - 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 @@ -269,9 +268,9 @@ technique: sqs:AddPermission reason: AddPermission grants selected SQS actions to an account on this queue. The page documents queue access/manipulation only; no second identity follows without credential-bearing message contents. -- source: - src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-sqs-privesc/README.md#sqssetqueueattributes--grant-queue-access-to-a-controlled-iam-user +- 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: SetQueueAttributes can grant a same-account user ReceiveMessage on this queue. This resource-scoped grant does - not identify a live credential in its messages. - source_revision: 171e422299 + reason: SetQueueAttributes can grant queue-scoped send, receive, and management actions to a named or OrgID-matching + principal when its identity policy and KMS permissions allow them. The policy alone does not prove access to + credentials in messages or unrelated IAM authority. + source_revision: 0b36331 diff --git a/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml b/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml index 52bd0a9d04..3df353cbea 100644 --- a/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml @@ -161,22 +161,6 @@ 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 @@ -186,10 +170,10 @@ - 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 + reason: The share can give an external account resource-specific network/use rights after an invitation is accepted. + Current principal graph cannot represent RAM-shared subnet/TGW authority or infer another IAM role; requires + exact share, recipient and permission-version joins. + source_revision: 0b36331 - 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 @@ -220,17 +204,16 @@ 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 + reason: PutFileSystemPolicy can give an external principal file-system and bucket-data access, but this is a resource-scoped + data-plane grant. Usable access depends on a mount/network path, effective recipient authorization, backing + bucket role and KMS; no IAM role takeover follows from the write alone. + source_revision: 0b36331 - 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 + reason: CreateAccessPoint plus PutAccessPointPolicy can grant external object access only when the bucket delegates + to the access point and recipient IAM, network and KMS checks pass. This is object-scoped authority, not a generic + IAM principal takeover. + source_revision: 0b36331 - 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); @@ -238,15 +221,16 @@ 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 + reason: PutModelPackageGroupPolicy can grant a valid external principal group-level read/write rights when its + identity policy also allows them. Artifact S3/ECR/KMS access and execution by a deployment role do not follow + from the group policy alone. + source_revision: 0b36331 - 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 + reason: The org-conditioned policy grants eligible principals group-scoped UpdateModelPackage if their identity + policy allows it. Execution under a deployment role requires an existing auto-deploy pipeline, an approved package + transition and trusted artifact; those runtime/configuration facts are not established by the policy alone. + source_revision: 0b36331 - 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 @@ -260,9 +244,10 @@ 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 + reason: CreateMembership grants an existing controlled Identity Center user MEMBER access to one Agent Space web + application. It does not grant IAM authority; current snapshots do not bind attacker control, SSO user, membership + and space. + source_revision: 0b36331 - 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; @@ -280,9 +265,9 @@ 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.' + reason: The scheduled association is the persistence aspect of aws-ssm-createassociation. The command-execution + path to a managed instance profile is already cataloged there; no separate privilege edge is introduced by the + schedule. 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' @@ -3124,3 +3109,42 @@ - source: src/pentesting-cloud/aws-security/aws-persistence/aws-data-firehose-persistence/README.md#firehoseupdatedestination--persistently-redirect-future-records technique: firehose:UpdateDestination retained HTTP access key reason: The update may send a stored X-Amz-Firehose-Access-Key to a new endpoint, but credential reuse against the original vendor depends on the vendor and requires a successful later delivery to an attacker-controlled HTTP endpoint. Stream configuration and UpdateDestination permission alone cannot establish a usable new identity or privilege. +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-secrets-manager-persistence/README.md#swap-the-rotation-lambda-to-an-attacker-controlled-function-via-rotatesecret + technique: Rebind secret rotation to controlled Lambda that reads/exfiltrates secret + reason: Rotation Lambda code and runtime behavior must actually read/exfiltrate the secret; configured Lambda + ARN and role permissions alone cannot prove code execution, exfiltration or a credential in the secret. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-secrets-manager-persistence/README.md#cross-region-replica-promotion-backdoor-replicate--promote--permissive-policy + technique: Replicate, promote and share standalone secret in second Region + reason: The replica policy can expose secret data, but identity escalation depends on the plaintext being a usable + credential and on recipient KMS/IAM permissions and successful promotion; neither secret contents nor credential + validity is in a configuration snapshot. + source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-step-functions-persistence/README.md#backdooring-aliases + technique: Repoint an alias to a backdoored version + reason: An alias update only selects an existing immutable version. The snapshot must identify an attacker-useful + privileged state in that version and a caller that later invokes this alias; IAM permission to update alias + alone does not establish either content or execution. The separate definition-edit path is aws-stepfunctions-updatestatemachine-existing-role. +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-verified-permissions-persistence/README.md#persist-an-attacker-controlled-oidc-trust-source + technique: Attacker-issued OIDC JWT impersonates application principal/group + reason: Application integration and token decision facts are absent from the AWS snapshot; the store configuration + alone cannot prove a token is accepted as a privileged application principal. +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-verified-permissions-persistence/README.md#persist-application-access-with-a-cedar-policy + technique: Permit controlled application principal to perform privileged application action + reason: The AWS snapshot does not contain the application-to-store binding, a controlled login principal, requested + action/resource, and complete effective Cedar decision including forbids. +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-verified-permissions-persistence/README.md#persist-through-a-policy-store-alias-mapping + technique: Redirect application alias to attacker-selected permissive store + reason: The AWS snapshot can show an alias mapping but cannot establish which application resolves the alias or + that the selected store permits a privileged action for an attacker-controlled principal. +- source: src/pentesting-cloud/aws-security/aws-persistence/aws-workspaces-web-persistence/README.md#persist-a-hostile-extension-in-every-secure-browser-session + technique: Create and associate hostile browser settings + reason: CreateBrowserSettings plus AssociateBrowserSettings can attach a policy, but extension code and manifest + permissions at the external update endpoint, later portal sessions, and privileged pages visited by those sessions + are not established by AWS configuration. aws-v3-04 covers the distinct UpdateBrowserSettings route with verified + evidence. +- source: src/pentesting-cloud/aws-security/aws-cross-account-attacks/resource-policy-and-shared-resource-attacks.md#shared-artifacts-and-supply-chains + technique: Recover IAM credentials from a shared AMI, snapshot, or golden image + reason: Whether an artifact contains a usable credential, which IAM principal it identifies, whether that credential + remains valid, and whether the recipient can decrypt and inspect the content are host/content and runtime facts + unavailable in the configuration snapshot. A share permission alone does not prove privilege gain. diff --git a/src/privilege-escalation-paths/aws/challenge-v3.yaml b/src/privilege-escalation-paths/aws/challenge-v3.yaml index af4843c012..b4924a1749 100644 --- a/src/privilege-escalation-paths/aws/challenge-v3.yaml +++ b/src/privilege-escalation-paths/aws/challenge-v3.yaml @@ -131,15 +131,19 @@ - id: aws-v3-05-add-or-replace-a-workspaces-web-portal-saml-oidc-identi provider: aws service: workspaces-web - title: Add or replace a WorkSpaces Web portal SAML/OIDC identity provider + title: Add a WorkSpaces Web portal SAML/OIDC identity provider source: src/pentesting-cloud/aws-security/aws-persistence/aws-workspaces-web-persistence/README.md#persist-an-attacker-controlled-portal-identity-provider - summary: Controlled IdP trusted by an exact standard-federation portal -> portal access plane. Exact source, target and prerequisite proof are required. + summary: Controlled IdP trusted by an exact standard-federation portal -> portal access plane. Exact source, target + and prerequisite proof are required. requires: any_of: - - action: workspaces-web:CreateIdentityProvider resource: '*' - - action: workspaces-web:UpdateIdentityProvider resource: '*' + all_of: + - action: workspaces-web:CreateIdentityProvider + resource: '*' target: kind: aws_verified_authority selector: @@ -150,13 +154,15 @@ - portal access plane. conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; IdP write alone is insufficient; only that portal and its federated session are targets. + description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; + IdP write alone is insufficient; only that portal and its federated session are targets. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence + is UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-06-use-independent-cognito-replica-lockout-counters-to-gue provider: aws service: challenge-evidence @@ -1251,15 +1257,14 @@ provider: aws service: memorydb title: MemoryDB full-access ACL user - source: - src/pentesting-cloud/aws-security/aws-persistence/aws-memorydb-persistence/README.md#memorydbcreateuser-memorydbcreateacl--memorydbupdateacl--plant-a-full-access-acl-user - summary: 'Add `service_plane: memorydb` and exact cluster selector; require row-specific `memorydb:CreateUser/UpdateUser/UpdateACL`. - Exact source, target and prerequisite proof are required.' + source: src/pentesting-cloud/aws-security/aws-persistence/aws-memorydb-persistence/README.md#memorydbcreateuser-memorydbcreateacl--memorydbupdateacl--plant-a-full-access-acl-user + summary: Create a full-access MemoryDB user and add it to an ACL already attached to a cluster; the exact user, + ACL and cluster must be verified. requires: all_of: - action: memorydb:CreateUser resource: '*' - - action: memorydb:CreateACL + - action: memorydb:UpdateACL resource: '*' target: kind: aws_verified_authority @@ -1268,18 +1273,19 @@ scope: same_account aggregate_as: Verified MemoryDB full-access ACL user targets in {account} grants: - - 'Add `service_plane: memorydb` and exact cluster selector; require row-specific `memorydb:C' + - MemoryDB cluster data-plane authority through a new ACL user conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - Existing cluster ACL, user membership change, and known actor-set credential. + description: Evidence must bind an attacker-known user credential to the exact ACL already attached to the target + cluster, and show network access. The separate new-ACL route needs CreateACL and UpdateCluster and is not + claimed by this entry. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is - UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence + is UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-44-memorydb-attached-user-takeover provider: aws service: memorydb @@ -1631,10 +1637,9 @@ provider: aws service: es title: OpenSearch domain policy - source: - src/pentesting-cloud/aws-security/aws-persistence/aws-opensearch-access-policy-persistence/README.md#esupdatedomainconfig--domain-access-policy-takeover - summary: 'Add `service_plane: opensearch` and domain selector; require `es:UpdateDomainConfig` for exact domain policy. - Exact source, target and prerequisite proof are required.' + source: src/pentesting-cloud/aws-security/aws-persistence/aws-opensearch-access-policy-persistence/README.md#esupdatedomainconfig--domain-access-policy-takeover + summary: 'Add `service_plane: opensearch` and domain selector; require `es:UpdateDomainConfig` for exact domain + policy. Exact source, target and prerequisite proof are required.' requires: all_of: - action: es:UpdateDomainConfig @@ -1646,18 +1651,19 @@ scope: same_account aggregate_as: Verified OpenSearch domain policy targets in {account} grants: - - 'Add `service_plane: opensearch` and domain selector; require `es:UpdateDomainConfig` for e' + - OpenSearch HTTP data access allowed by both domain policy and fine-grained access control conditions: - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - Exact domain and FGAC-disabled state; if FGAC enabled, no engine-admin edge. + description: Evidence must bind the exact domain, controlled IAM principal, allowed ESHttp action, reachable + endpoint and effective domain policy. If fine-grained access control is enabled, prove that its role mapping + also permits the requested index/action; explicit denies and KMS can still block access. blockers: - scp_or_boundary_deny confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is - UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence + is UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-56-marketplace-seller-entity-policy provider: aws service: aws-marketplace @@ -1755,10 +1761,9 @@ provider: aws service: challenge-evidence title: Anonymous Cognito guest role - source: - src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum/README.md#guest-identity-credentials - summary: Add a **source entry point** `aws_cognito_anonymous_pool_role` rather than making every IAM source anonymous; - row 83/84 then use a normal role-to-resource permission edge. Exact external source and target proof are required. + source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum/README.md#guest-identity-credentials + summary: Known identity-pool ID and enabled guest access can issue temporary credentials for the exact unauthenticated + role when its mapping and trust permit. Enhanced-flow session policies scope down the effective permissions. requires: {} source_kind: aws_challenge_foothold source_selector: @@ -1770,7 +1775,8 @@ scope: same_account aggregate_as: Verified Anonymous Cognito guest role targets in {account} grants: - - Add a **source entry point** `aws_cognito_anonymous_pool_role` rather than making every IA + - Temporary credentials for the exact mapped unauthenticated IAM role, limited by the role policies and Cognito + enhanced-flow session policies. conditions: - id: exact_external_foothold description: Pool AllowUnauthenticatedIdentities, actual unauth role mapping, role trust, and scope-down. Source @@ -1778,16 +1784,15 @@ confidence: conditional severity: high mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is - inferred from configuration. + notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal + is inferred from configuration. - id: aws-v3-60-cognito-classic-flow provider: aws service: challenge-evidence title: Cognito classic flow - source: - src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum/README.md#enhanced-and-basic-authentication-flows - summary: Add a **source entry point** `aws_cognito_anonymous_pool_role` rather than making every IAM source anonymous; - row 83/84 then use a normal role-to-resource permission edge. Exact external source and target proof are required. + source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-unauthenticated-enum/README.md#enhanced-and-basic-authentication-flows + summary: Enabled classic flow can exchange a guest identity-pool OIDC token through STS for the exact trusted + IAM role without Cognito enhanced-flow scope-down. requires: {} source_kind: aws_challenge_foothold source_selector: @@ -1799,22 +1804,22 @@ scope: same_account aggregate_as: Verified Cognito classic flow targets in {account} grants: - - Add a **source entry point** `aws_cognito_anonymous_pool_role` rather than making every IA + - STS temporary credentials for the exact trusted guest IAM role; no Cognito enhanced-flow scope-down policy, + while role and other session policies still apply. conditions: - id: exact_external_foothold - description: Basic flow enabled, exact role mapping, OIDC trust, and STS authorization. Source evidence must prove - anonymous control for the exact target. + description: Require AllowUnauthenticatedIdentities, AllowClassicFlow, an exact guest-role trust accepting the + identity-pool token, no unsupported role mapping, and verified STS exchange. Missing evidence remains UNKNOWN. confidence: conditional severity: high mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is - inferred from configuration. + notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal + is inferred from configuration. - id: aws-v3-61-public-signup-cognito-role provider: aws service: challenge-evidence title: Public SignUp Cognito role - source: - src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-user-pool-unauthenticated-access/README.md#registration + source: src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-cognito-user-pool-unauthenticated-access/README.md#registration summary: Public SignUp -> authenticated identity-pool role for exact user-pool client, conditional on completing confirmation/challenges. Exact external source and target proof are required. requires: {} @@ -1828,45 +1833,18 @@ scope: same_account aggregate_as: Verified Public SignUp Cognito role targets in {account} grants: - - authenticated identity-pool role for exact user-pool client, conditional on completing con + - Temporary credentials for the exact authenticated identity-pool IAM role mapped from the confirmed Cognito + user-pool identity; effective permissions remain limited by role and session policies. conditions: - id: exact_external_foothold - description: Public SignUp alone never yields usable tokens or IAM credentials. Source evidence must prove anonymous - control for the exact target. + description: Require self-service signup enabled, a usable public app client, writable required attributes, + completed confirmation and authentication challenges, a valid provider token, exact identity-pool provider/role + mapping, and target role trust. Public SignUp alone is insufficient; missing proof remains UNKNOWN. confidence: conditional severity: high mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is - inferred from configuration. -- id: aws-v3-62-cognito-guest-to-dynamodb - provider: aws - service: challenge-evidence - title: Cognito guest to DynamoDB - source: - src/pentesting-cloud/aws-security/aws-unauthenticated-enum-access/aws-dynamodb-unauthenticated-access/README.md#cognito-guest-identities-for-dynamodb - summary: Add a **source entry point** `aws_cognito_anonymous_pool_role` rather than making every IAM source anonymous; - row 83/84 then use a normal role-to-resource permission edge. Exact external source and target proof are required. - requires: {} - source_kind: aws_challenge_foothold - source_selector: - source_id_glob: aws_challenge_foothold:*:anonymous - target: - kind: aws_role - selector: - aws_challenge_fact: aws-v3-62-cognito-guest-to-dynamodb - scope: same_account - aggregate_as: Verified Cognito guest to DynamoDB targets in {account} - grants: - - Add a **source entry point** `aws_cognito_anonymous_pool_role` rather than making every IA - conditions: - - id: exact_external_foothold - description: Same proven guest role as row 80, then effective DynamoDB action on the exact table. Source evidence - must prove anonymous control for the exact target. - confidence: conditional - severity: high - mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is - inferred from configuration. + notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal + is inferred from configuration. - id: aws-v3-63-cognito-guest-to-lex provider: aws service: challenge-evidence @@ -2259,3 +2237,379 @@ - https://docs.aws.amazon.com/acm/latest/APIReference/API_GetAcmeExternalAccountBindingCredentials.html - https://docs.aws.amazon.com/acm/latest/userguide/security-iam-acme.html notes: 'Draft only: exact source and target evidence is required; absent evidence evaluates UNKNOWN.' +- id: aws-peaso-mint-an-accessor-bearer-credential + provider: aws + service: managedblockchain + title: Create AMB billing bearer credential + source: src/pentesting-cloud/aws-security/aws-persistence/aws-managed-blockchain-persistence/README.md#mint-an-accessor-bearer-credential + source_revision: 0b36331 + summary: independent victim-billed Ethereum/Polygon RPC bearer credential; the exact source, resource, controlled + recipient and effective prerequisites must be verified. + requires: + all_of: + - action: managedblockchain:CreateAccessor + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-peaso-mint-an-accessor-bearer-credential + scope: same_account + aggregate_as: Create AMB billing bearer credential in {account} + grants: + - independent victim-billed Ethereum/Polygon RPC bearer credential + conditions: + - id: exact_verified_prerequisites + description: CreateAccessor is authorized on * with BILLING_TOKEN and the bearer token is returned by creation; + no tags are supplied. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict managedblockchain:CreateAccessor to approved operators and review exact resource policies + and recipients. + references: + - https://docs.aws.amazon.com/managed-blockchain/latest/APIReference/API_CreateAccessor.html + notes: Missing aws_privesc_challenge_evidence is UNKNOWN; evidence must bind TechniqueId, SourceArn, TargetKind, + TargetId and TargetAccount and prove all prerequisites. +- id: aws-peaso-establish-an-attacker-owned-consortium-member + provider: aws + service: managedblockchain + title: Join Fabric consortium with controlled member + source: src/pentesting-cloud/aws-security/aws-persistence/aws-managed-blockchain-persistence/README.md#establish-an-attacker-owned-consortium-member + source_revision: 0b36331 + summary: external Fabric member and CA/peer service identity; the exact source, resource, controlled recipient + and effective prerequisites must be verified. + requires: + all_of: + - action: managedblockchain:CreateProposal + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-peaso-establish-an-attacker-owned-consortium-member + scope: same_account + aggregate_as: Join Fabric consortium with controlled member in {account} + grants: + - external Fabric member and CA/peer service identity + conditions: + - id: exact_verified_prerequisites + description: A network invitation proposal for the controlled account is approved; the external account accepts + and creates a member with attacker-known bootstrap credentials. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict managedblockchain:CreateProposal to approved operators and review exact resource policies + and recipients. + references: + - https://docs.aws.amazon.com/managed-blockchain/latest/APIReference/API_CreateAccessor.html + notes: Missing aws_privesc_challenge_evidence is UNKNOWN; evidence must bind TechniqueId, SourceArn, TargetKind, + TargetId and TargetAccount and prove all prerequisites. +- id: aws-peaso-backdoor-a-workspace-with-its-resource-policy + provider: aws + service: aps + title: Grant controlled principal AMP workspace data access + source: src/pentesting-cloud/aws-security/aws-persistence/aws-managed-prometheus-persistence/README.md#backdoor-a-workspace-with-its-resource-policy + source_revision: 0b36331 + summary: AMP workspace QueryMetrics/GetLabels/GetSeries/RemoteWrite authority; the exact source, resource, controlled + recipient and effective prerequisites must be verified. + requires: + all_of: + - action: aps:PutResourcePolicy + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-peaso-backdoor-a-workspace-with-its-resource-policy + scope: same_account + aggregate_as: Grant controlled principal AMP workspace data access in {account} + grants: + - AMP workspace QueryMetrics/GetLabels/GetSeries/RemoteWrite authority + conditions: + - id: exact_verified_prerequisites + description: Exact workspace policy is ACTIVE and grants a controlled principal supported Prometheus actions; + cross-account use also has identity allow and any required KMS/network access. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict aps:PutResourcePolicy to approved operators and review exact resource policies and recipients. + references: + - https://docs.aws.amazon.com/prometheus/latest/userguide/security_iam_resource-based-policy-examples.html + notes: Missing aws_privesc_challenge_evidence is UNKNOWN; evidence must bind TechniqueId, SourceArn, TargetKind, + TargetId and TargetAccount and prove all prerequisites. +- id: aws-peaso-grant-a-cross-account-flow-entitlement + provider: aws + service: mediaconnect + title: Grant controlled account MediaConnect flow entitlement + source: src/pentesting-cloud/aws-security/aws-persistence/aws-mediaconnect-persistence/README.md#grant-a-cross-account-flow-entitlement + source_revision: 0b36331 + summary: cross-account subscription authority to a victim transport stream; the exact source, resource, controlled + recipient and effective prerequisites must be verified. + requires: + all_of: + - action: mediaconnect:GrantFlowEntitlements + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-peaso-grant-a-cross-account-flow-entitlement + scope: same_account + aggregate_as: Grant controlled account MediaConnect flow entitlement in {account} + grants: + - cross-account subscription authority to a victim transport stream + conditions: + - id: exact_verified_prerequisites + description: GrantFlowEntitlements covers parent flow and prospective entitlement; enabled entitlement lists + a controlled account, which has its own CreateFlow authority. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict mediaconnect:GrantFlowEntitlements to approved operators and review exact resource policies + and recipients. + references: + - https://docs.aws.amazon.com/mediaconnect/latest/ug/entitlements.html + notes: Missing aws_privesc_challenge_evidence is UNKNOWN; evidence must bind TechniqueId, SourceArn, TargetKind, + TargetId and TargetAccount and prove all prerequisites. +- id: aws-peaso-share-a-core-network-with-an-external-account-through-aws-ram + provider: aws + service: ram + title: Share Cloud WAN core network with controlled account + 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 + source_revision: 0b36331 + summary: cross-account Cloud WAN attachment creation authority; the exact source, resource, controlled recipient + and effective prerequisites must be verified. + requires: + all_of: + - action: ram:CreateResourceShare + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-peaso-share-a-core-network-with-an-external-account-through-aws-ram + scope: same_account + aggregate_as: Share Cloud WAN core network with controlled account in {account} + grants: + - cross-account Cloud WAN attachment creation authority + conditions: + - id: exact_verified_prerequisites + description: Core-network share permits external principals, invitation is accepted or org-shared, and live + managed permission grants the particular attachment action. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict ram:CreateResourceShare to approved operators and review exact resource policies and recipients. + references: + - https://docs.aws.amazon.com/network-manager/latest/cloudwan/cloudwan-share-network.html + notes: Missing aws_privesc_challenge_evidence is UNKNOWN; evidence must bind TechniqueId, SourceArn, TargetKind, + TargetId and TargetAccount and prove all prerequisites. +- id: aws-peaso-add-an-external-engagement-member-for-permanent-snapshot-access + provider: aws + service: partnercentral + title: Invite controlled Partner into Engagement + source: src/pentesting-cloud/aws-security/aws-persistence/aws-partner-central-selling-persistence/README.md#add-an-external-engagement-member-for-permanent-snapshot-access + source_revision: 0b36331 + summary: external Partner membership and shared snapshot-read authority; the exact source, resource, controlled + recipient and effective prerequisites must be verified. + requires: + all_of: + - action: partnercentral:CreateEngagementInvitation + resource: '*' + - action: partnercentral:GetEngagement + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-peaso-add-an-external-engagement-member-for-permanent-snapshot-access + scope: same_account + aggregate_as: Invite controlled Partner into Engagement in {account} + grants: + - external Partner membership and shared snapshot-read authority + conditions: + - id: exact_verified_prerequisites + description: Sender is an Engagement member; connected eligible Partner accepts through documented task workflow + and gains membership and snapshot permissions. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict partnercentral:CreateEngagementInvitation to approved operators and review exact resource + policies and recipients. + references: + - https://docs.aws.amazon.com/partner-central/latest/developer-guide/working-with-multi-partner-opportunities.html + notes: Missing aws_privesc_challenge_evidence is UNKNOWN; evidence must bind TechniqueId, SourceArn, TargetKind, + TargetId and TargetAccount and prove all prerequisites. +- id: aws-peaso-persist-cross-account-key-access-with-a-resource-policy + provider: aws + service: payment-cryptography + title: Grant controlled role Payment Cryptography key use + source: src/pentesting-cloud/aws-security/aws-persistence/aws-payment-cryptography-persistence/README.md#persist-cross-account-key-access-with-a-resource-policy + source_revision: 0b36331 + summary: cross-account cryptographic operation authority on exact primary key; the exact source, resource, controlled + recipient and effective prerequisites must be verified. + requires: + all_of: + - action: payment-cryptography:PutResourcePolicy + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-peaso-persist-cross-account-key-access-with-a-resource-policy + scope: same_account + aggregate_as: Grant controlled role Payment Cryptography key use in {account} + grants: + - cross-account cryptographic operation authority on exact primary key + conditions: + - id: exact_verified_prerequisites + description: Primary key policy grants a controlled role a supported action; recipient identity policy allows + the same action and key attributes/state permit it. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict payment-cryptography:PutResourcePolicy to approved operators and review exact resource policies + and recipients. + references: + - https://docs.aws.amazon.com/payment-cryptography/latest/userguide/security_iam_resource-based-policies.html + notes: Missing aws_privesc_challenge_evidence is UNKNOWN; evidence must bind TechniqueId, SourceArn, TargetKind, + TargetId and TargetAccount and prove all prerequisites. +- id: aws-peaso-cross-account-data-accessor-persistence + provider: aws + service: qbusiness + title: Create Q Business cross-account data accessor + source: src/pentesting-cloud/aws-security/aws-persistence/aws-q-business-persistence/README.md#cross-account-data-accessor-persistence + source_revision: 0b36331 + summary: supported ISV tenant SearchRelevantContent authority; the exact source, resource, controlled recipient + and effective prerequisites must be verified. + requires: + all_of: + - action: qbusiness:CreateDataAccessor + resource: '*' + - action: qbusiness:AssociatePermission + resource: '*' + - action: qbusiness:PutResourcePolicy + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-peaso-cross-account-data-accessor-persistence + scope: same_account + aggregate_as: Create Q Business cross-account data accessor in {account} + grants: + - supported ISV tenant SearchRelevantContent authority + conditions: + - id: exact_verified_prerequisites + description: Supported registered ISV tenant is controlled; accessor, application resource policy and Identity + Center assignment are effective; end-user ACLs allow the requested documents. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict qbusiness:CreateDataAccessor to approved operators and review exact resource policies and + recipients. + references: + - https://docs.aws.amazon.com/amazonq/latest/qbusiness-ug/doc-history.html + notes: Missing aws_privesc_challenge_evidence is UNKNOWN; evidence must bind TechniqueId, SourceArn, TargetKind, + TargetId and TargetAccount and prove all prerequisites. +- id: aws-peaso-grant-external-ingest-mediapackagev2putchannelpolicy + provider: aws + service: mediapackagev2 + title: Grant anonymous MediaPackage channel ingest + source: src/pentesting-cloud/aws-security/aws-persistence/aws-mediapackage-v2-policy-persistence/README.md#grant-external-ingest--mediapackagev2putchannelpolicy + source_revision: 0b36331 + summary: unauthenticated PutObject ingest authority; the exact source, resource, controlled recipient and effective + prerequisites must be verified. + requires: + all_of: + - action: mediapackagev2:PutChannelPolicy + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-peaso-grant-external-ingest-mediapackagev2putchannelpolicy + scope: same_account + aggregate_as: Grant anonymous MediaPackage channel ingest in {account} + grants: + - unauthenticated PutObject ingest authority + conditions: + - id: exact_verified_prerequisites + description: Exact channel policy permits Principal:* PutObject under attacker-satisfiable source IP and channel + ingest endpoint accepts it. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict mediapackagev2:PutChannelPolicy to approved operators and review exact resource policies + and recipients. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_awselementalmediapackagev2.html + notes: Missing aws_privesc_challenge_evidence is UNKNOWN; evidence must bind TechniqueId, SourceArn, TargetKind, + TargetId and TargetAccount and prove all prerequisites. +- id: aws-peaso-publish-a-private-origin-endpoint-mediapackagev2putoriginendpointpolicy + provider: aws + service: mediapackagev2 + title: Grant anonymous MediaPackage origin read + source: src/pentesting-cloud/aws-security/aws-persistence/aws-mediapackage-v2-policy-persistence/README.md#publish-a-private-origin-endpoint--mediapackagev2putoriginendpointpolicy + source_revision: 0b36331 + summary: unauthenticated GetObject/GetHeadObject origin authority; the exact source, resource, controlled recipient + and effective prerequisites must be verified. + requires: + all_of: + - action: mediapackagev2:PutOriginEndpointPolicy + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-peaso-publish-a-private-origin-endpoint-mediapackagev2putoriginendpointpolicy + scope: same_account + aggregate_as: Grant anonymous MediaPackage origin read in {account} + grants: + - unauthenticated GetObject/GetHeadObject origin authority + conditions: + - id: exact_verified_prerequisites + description: Exact endpoint policy permits Principal:* reads and endpoint is reachable. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict mediapackagev2:PutOriginEndpointPolicy to approved operators and review exact resource policies + and recipients. + references: + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_awselementalmediapackagev2.html + notes: Missing aws_privesc_challenge_evidence is UNKNOWN; evidence must bind TechniqueId, SourceArn, TargetKind, + TargetId and TargetAccount and prove all prerequisites. +- id: aws-peaso-cross-account-cluster-access-with-kafkaputclusterpolicy + provider: aws + service: kafka + title: Grant controlled account MSK data access + source: src/pentesting-cloud/aws-security/aws-persistence/aws-msk-policy-persistence/README.md#cross-account-cluster-access-with-kafkaputclusterpolicy + source_revision: 0b36331 + summary: external Kafka cluster/topic/group authority; the exact source, resource, controlled recipient and effective + prerequisites must be verified. + requires: + all_of: + - action: kafka:PutClusterPolicy + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-peaso-cross-account-cluster-access-with-kafkaputclusterpolicy + scope: same_account + aggregate_as: Grant controlled account MSK data access in {account} + grants: + - external Kafka cluster/topic/group authority + conditions: + - id: exact_verified_prerequisites + description: Exact cluster policy covers cluster, topic and group ARNs; multi-VPC private connectivity and broker + authentication work; external identity policy allows matching actions. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict kafka:PutClusterPolicy to approved operators and review exact resource policies and recipients. + references: + - https://docs.aws.amazon.com/msk/latest/developerguide/what-is-msk.html + notes: Missing aws_privesc_challenge_evidence is UNKNOWN; evidence must bind TechniqueId, SourceArn, TargetKind, + TargetId and TargetAccount and prove all prerequisites. From 0692b0c64adc06238f654318a5263db1ac7a62ab Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Mon, 12 Oct 2026 20:55:50 +0200 Subject: [PATCH 06/17] Integrate verified AWS services privilege escalation fragments Co-Authored-By: Codex --- .../aws/_excluded_a.yaml | 7 +- .../aws/_excluded_verify_a66f.yaml | 249 ++++++++++++++++-- src/privilege-escalation-paths/aws/batch.yaml | 8 +- .../aws/challenge-v3.yaml | 83 +++++- .../aws/codebuild.yaml | 35 +++ .../aws/cognito.yaml | 34 +++ .../aws/connect.yaml | 36 +++ .../aws/gameliftstreams.yaml | 37 +++ .../aws/healthomics.yaml | 33 +++ .../aws/keyspaces.yaml | 65 +++++ 10 files changed, 552 insertions(+), 35 deletions(-) create mode 100644 src/privilege-escalation-paths/aws/keyspaces.yaml diff --git a/src/privilege-escalation-paths/aws/_excluded_a.yaml b/src/privilege-escalation-paths/aws/_excluded_a.yaml index 830166ad28..f8176387fa 100644 --- a/src/privilege-escalation-paths/aws/_excluded_a.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_a.yaml @@ -192,11 +192,10 @@ 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-privilege-escalation/aws-codepipeline-privesc/README.md#codepipelinepollforjobs +- 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. + reason: PollForJobs can expose temporary AWS artifact credentials for a reachable custom-action job; exact pending + job, validity and artifact scope require runtime evidence. # --- CodeStar (service discontinued) --- - source: diff --git a/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml b/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml index 3df353cbea..6a17cb7d4d 100644 --- a/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml @@ -468,8 +468,9 @@ 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.' + reason: An RTMP URL can carry a third-party publisher credential. The exclusion applies when no live connector + returns a usable key or downstream acceptance is unverified; an exact publisher identity requires live connector + and downstream validation evidence. 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` @@ -2687,39 +2688,48 @@ 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. + reason: AssociateEnvironmentRole with iam:PassRole and GetEnvironmentCredentials is modeled by aws-datazone-passrole-associateenvironmentrole. + Other role-bearing operations named here only identify PassRole boundaries; this section does not show how their + fixed provisioning or domain roles can be used as a new principal. 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. + reason: GetDocument can return literal bootstrap credentials from an accessible document version, but the returned + content must contain a currently usable credential and its issuer must be verified before any principal edge + exists. Referenced secret ARNs or variable names do not reveal secret values; the read does not execute the + document. 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. + reason: DescribeLaunchConfigurations returns base64 UserData that may contain credentials. A principal edge requires + a real, unexpired credential in a readable launch configuration and a verified issuer; IAM permission and UserData + presence alone cannot establish that fact. 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. + reason: DescribeInstanceAttribute with userData can reveal launch scripts containing passwords or tokens even + for stopped instances. An identity edge requires the actual decoded content, credential validity and issuer; + the read permission and instance metadata alone do not prove these facts. 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. + reason: GetOpsItem can disclose arbitrary OperationalData including credentials. A principal edge requires an + accessible OpsItem with a usable credential and a verified issuer; neither the permission nor OpsItem metadata + proves its content or validity. 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. + reason: GetComponent returns literal component source, which may include repository credentials or tokens in account-owned + versions. A principal edge requires an actual usable credential in component.data and a verified issuer; a reference + to a secret ARN or variable name does not disclose its value, and GetComponent does not execute commands. 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 + reason: GetComponentVersionArtifact can return a presigned download for a known public or Lambda component artifact. + The bundle may contain a credential, but its bytes, credential validity and target identity are not known from + the configuration snapshot. Ordinary private S3 components are not covered by this API, and external artifacts + may require separate S3/KMS authorization. + source_revision: 0b36331 - 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 @@ -3148,3 +3158,208 @@ reason: Whether an artifact contains a usable credential, which IAM principal it identifies, whether that credential remains valid, and whether the recipient can decrypt and inspect the content are host/content and runtime facts unavailable in the configuration snapshot. A share permission alone does not prove privilege gain. + +- source: src/pentesting-cloud/aws-security/aws-services/aws-amplify-enum.md#what-to-review + technique: UI Builder schema JavaScript injection into privileged build + reason: The cited page documents JavaScript injection into generated UI components, but code execution as a privileged + build role requires the vulnerable codegen version, an affected component in the build input, and a build process + that executes the injected JavaScript with that role. Those dependency and build-runtime facts are not established + by the snapshot; merely compiling or packaging generated UI code does not prove role execution. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-api-gateway-enum.md#iam-authorizer + technique: Bypass flawed custom Lambda authorizer that accepts any nonempty Authorization header + reason: The page makes this a hypothetical flaw in custom Lambda authorizer code. A code review or verified request/response + probe must establish that an arbitrary nonempty header is allowed on a deployed reachable route and that other + authorization checks do not deny it; API Gateway configuration alone does not establish those runtime facts + or an AWS principal gain. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-appconfig-enum.md#aws-appconfig + technique: Read AppConfig content containing credentials + reason: Hosted-version reads have an existing exclusion, but deployed configuration reads via StartConfigurationSession + and GetLatestConfiguration are a distinct path. Either path yields an identity only if the returned content + contains a current reusable credential mapped to a target principal; a referenced secret ARN or ordinary configuration + value does not establish that content or validity fact. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-appflow-enum.md#iam-boundaries-worth-auditing + technique: Use stored SaaS connector authority in new flow + reason: The page documents using a stored SaaS connector profile for a flow, but a principal-to-principal edge + requires the external tenant identity and grants, source object authorization, successful flow execution, and + a destination the attacker can read. These SaaS/runtime and flow-to-profile facts are not in the AWS principal + snapshot. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-appsync-enum.md#graphql-apis-and-authorization + technique: Recover usable AppSync API keys + reason: ListApiKeys returns a bearer value, but the value is an application client key rather than an AWS principal + credential. An application access edge would require the live unexpired key, API_KEY authorization on a reachable + field, and the absence or satisfaction of other application checks; the catalog has no GraphQL client principal + target or these joined runtime facts. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-appsync-enum.md#graphql-apis-and-authorization + technique: Read credential-bearing AppSync environment variables + reason: GetGraphqlApiEnvironmentVariables returns arbitrary application values. An identity edge requires a literal + current reusable credential, proof of the identity it authenticates, and confirmation that it is not only a + secret reference; those content and validity facts are not collected. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-cloudformation-and-codestar-enum.md#registry-and-cloud-control-attack-surface + technique: ActivateType with a supplied execution role can run an attacker-published public extension/Hook as + that role. + reason: ActivateType runs publisher-supplied public extension code, but the page does not establish that the IAM + caller controls that publisher/code or can trigger its handler. Publisher ownership, exact extension version, + and an invocation event are external/runtime facts; configuration and PassRole alone cannot prove role execution + by the caller. The RegisterType path is separately modeled as aws-cloudformation-registertype-passrole-extension. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-cloudformation-and-codestar-enum.md#enumeration + technique: BatchDescribeTypeConfigurations can disclose stored extension configuration credentials. + reason: BatchDescribeTypeConfigurations can return extension settings, but the page does not identify a credential + in a particular TypeConfiguration or prove that it is valid for another identity. Exact configuration content + and credential validity/owner are required runtime/content facts. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-cloudformation-and-codestar-enum.md#enumeration + technique: DescribeStacks/GetTemplate can disclose secrets in stack parameters, outputs or template. + reason: DescribeStacks/GetTemplate exposes stack metadata or template text. A privilege edge requires an unredacted + credential in an exact response, its current validity, and a stronger target identity; these content and runtime + facts are absent from a configuration-only snapshot. NoEcho parameters do not reveal their plaintext value. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-cloudfront-enum.md#enumeration + technique: Distribution configuration can reveal origin custom-header shared secret. + reason: Origin custom headers are configuration data. A target identity exists only if a particular header is + accepted by the origin as an authentication secret; origin-side authentication behavior and current key validity + are host/runtime facts absent from the AWS snapshot. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-cloudfront-enum.md#cloudfront + technique: Cookie logging can persist visitor session credentials in standard logs. + reason: Cookie logging records request cookies, but a privilege edge requires an exact delivered S3 log object + containing a still-valid authentication cookie for another visitor and an application that accepts replay. Log + content, delivery, session expiry, and application behavior are runtime facts. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-cloudwatch-enum.md#enumeration + technique: GetLogEvents/tail may disclose application tokens or credentials stored in log events. + reason: Log read permissions expose events, not a fixed stronger identity. A privilege edge requires an exact + event with an unredacted, still-valid credential for another identity and any required downstream access; event + content and credential validity are runtime facts. The WAF-session case is already evidence-gated by aws-v3-15-replay-a-victim-application-session-recovered-from-waf. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-cloudwatch-enum.md#cross-account-observability-oam + technique: CreateLink plus service Link action can expose source-account logs to an attacker-controlled monitoring + account. + reason: CreateLink and telemetry-service Link grant bounded cross-account telemetry access. An identity gain additionally + requires an actual linked log containing a still-valid credential for another identity, a sink policy permitting + the link, and access from the monitoring account; log content and credential validity are runtime facts. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-cloudwatch-omni-enum.md#security-relevant-permission-notes + technique: CreateView/UpdateView plus view-scoped GetRecords exposes raw default Dataset logs beyond a data-scope + grant. + reason: CreateView/UpdateView plus view-scoped GetRecords expands data access to raw Dataset rows, not an identity + by itself. An identity edge requires an exact returned row containing a valid credential for another principal; + row content and current credential validity are runtime facts. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-codeartifact-enum.md#basic-information + technique: GetPackageVersionAsset can retrieve package assets containing embedded identity credentials. + reason: GetPackageVersionAsset downloads an asset. Identity gain requires the exact asset to contain an unredacted, + still-valid credential mapped to another principal; package contents and credential validity are content/runtime + facts, not inferable from asset metadata or read permission. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-datazone-enum.md#search-published-listings-and-recover-metadata-forms + technique: DataZone published listing form credential disclosure + reason: SearchListings with FORMS or GetListing returns publisher-controlled form content. A principal edge requires + an actual unexpired credential in an accessible listing and verification of its issuer and grants; neither follows + from DataZone permissions or listing metadata alone. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-device-farm-enum.md#enumerate-account-and-projects + technique: Device Farm GetProject plaintext environment-variable disclosure + reason: GetProject returns configured variable values, but a target principal exists only if an accessible project + contains a usable credential and its issuer is verified. Configuration/IAM inventory cannot infer those arbitrary + values or their validity. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-device-farm-enum.md#enumerate-runs-jobs-tests-and-artifacts + technique: Device Farm ListArtifacts credential disclosure + reason: ListArtifacts returns expiring URLs to run, job, suite or test output. An identity edge needs a readable + artifact containing a currently usable credential or session cookie and a verified target account; neither artifact + contents nor session validity follows from IAM permissions. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-device-farm-enum.md#enumerate-testgrid-sessions-and-artifacts + technique: Device Farm TestGrid artifact credential disclosure + reason: ListTestGridSessionArtifacts returns short-lived URLs to logs or videos. A target identity requires a + readable recording containing an active credential or cookie and verification of its account; artifact bytes + and validity are runtime facts. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-dynamodb-enum.md#dax-inherit-the-cluster-roles-dynamodb-access + technique: DAX data-plane access through the cluster service role + reason: DAX data actions can read or modify tables permitted to the cluster role without matching direct DynamoDB + permission, but yield scoped table-data access, not the role session or a principal identity. Actual use also + needs a reachable cluster endpoint and matching cluster-role table permissions. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-ec2-ebs-elb-ssm-vpc-and-vpn-enum/README.md#ebs + technique: Read API keys from EBS snapshots or restored disks + reason: Snapshot and disk reads expose storage bytes, not a principal by themselves. Identity gain requires that + the selected snapshot contains a still-valid credential, that the attacker can obtain its bytes (including any + KMS or restore prerequisites), and that the issuer is verified; snapshot metadata cannot prove these facts. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-ecs-enum.md#on-host-enumeration-via-the-ecs-agent-state-db-agentdb + technique: Read credentials from ECS agent.db plaintext environment values + reason: agent.db is local host state and can contain plaintext task environment values, but a principal edge needs + host or mounted-file access, an actual usable credential in those values, and verification of its issuer. ECS + IAM configuration alone cannot prove file reachability, content, or validity. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-elastic-beanstalk-enum.md#exposure + technique: Read source bundle from the regional Elastic Beanstalk S3 bucket and recover accidentally embedded + credentials + reason: A source bundle can contain a credential, but the page says only that developers may have stored one. + A configuration snapshot cannot establish the bundle bytes, credential validity, or the identity and authority + obtained. Requires S3 object content inspection and credential-to-principal verification; s3:GetObject alone + is insufficient. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-elastic-beanstalk-enum.md#exposure + technique: Overwrite the deployed source bundle and wait for a deployment to run code as its instance profile + reason: s3:PutObject can poison a source bundle, but the page explicitly says the write does not change a running + environment. Escalation depends on a later deployment consuming that exact object and running code with a particular + instance profile; the future deployment and code execution are not configuration facts. The immediate rebuild + path is already aws-elasticbeanstalk-rebuildenvironment-s3-code and needs RebuildEnvironment. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-entity-resolution-enum.md#enumerate-id-mapping + technique: Put or add a workflow/namespace resource-policy statement to grant a chosen other account its supported + workflow rights + reason: PutPolicy or AddPolicyStatement can delegate supported workflow rights to another account, but an attack + edge requires an attacker-controlled external grantee, a matching allow in that account, and an exact supported + action/resource pairing. The local account snapshot cannot establish external identity policy or control of + the grantee; PutPolicy permission alone is insufficient. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-gamelift-streams-enum.md#enumerate-sessions-account-wide + technique: Read plaintext session environment variables or launch arguments containing another identity’s credential + reason: GetStreamSession returns plaintext environment variables and launch arguments, which could contain a credential, + but the page does not assert that any specific session does. The exact response content, credential validity, + and distinct target identity require runtime content inspection; the IAM permission alone cannot determine an + escalation. + source_revision: 0b36331 + +- source: src/pentesting-cloud/aws-security/aws-services/aws-glue-enum.md#enumerate-connections-and-connected-records + technique: Read a Glue connection with stored username/password and assume the connected service identity + reason: GetConnection without HidePassword can return a stored password, but some connections have no password + or use a Secrets Manager reference. A privilege edge requires the actual returned secret, its validity and connected-service + identity; these response/content facts are absent from the configuration snapshot. Authorization also requires + GetConnection on both catalog and exact connection ARN. + source_revision: 0b36331 diff --git a/src/privilege-escalation-paths/aws/batch.yaml b/src/privilege-escalation-paths/aws/batch.yaml index bc932dd140..9ae7c414e2 100644 --- a/src/privilege-escalation-paths/aws/batch.yaml +++ b/src/privilege-escalation-paths/aws/batch.yaml @@ -23,10 +23,12 @@ outcome: workload_execution conditions: - id: job_queue_covered - description: batch:SubmitJob must cover both the job definition and a job queue (Resource includes both ARNs). + description: A usable job queue must exist, batch:SubmitJob must authorize that queue and the selected job-definition + revision together, and the queue must have a VALID, ENABLED compute environment compatible with the definition. + These queue and definition facts are unresolved unless collected and joined. blockers: - scp_or_boundary_deny - confidence: derived + confidence: conditional severity: critical mitigation: Scope batch:SubmitJob to specific job definitions and queues; keep job roles least-privileged. references: @@ -36,8 +38,6 @@ task role (trusts ecs-tasks.amazonaws.com), so the selector resolves through the ECS task principal rather than batch.amazonaws.com; job definitions are not collected, so the attachment is unknown. EKS-backed jobs use a Kubernetes service account and are not covered. - - - id: aws-batch-registerjobdefinition-passrole-submitjob provider: aws service: batch diff --git a/src/privilege-escalation-paths/aws/challenge-v3.yaml b/src/privilege-escalation-paths/aws/challenge-v3.yaml index b4924a1749..09a260470b 100644 --- a/src/privilege-escalation-paths/aws/challenge-v3.yaml +++ b/src/privilege-escalation-paths/aws/challenge-v3.yaml @@ -976,10 +976,10 @@ - id: aws-v3-32-reuse-another-user-s-cached-sts-role-credentials-or-sta provider: aws service: challenge-evidence - title: Reuse another user's cached STS role credentials or static IAM user keys from local AWS CLI files + title: Reuse another user's cached STS role credentials from local AWS CLI files source: src/pentesting-cloud/aws-security/aws-services/aws-iam-enum.md#local-enumeration - summary: Host file read of cached STS/static key -> exact owner principal. Exact external source and target proof are - required. + summary: Reading another user's cached STS session can yield its issuing role only with verified host-file access, + live credentials and owner. requires: {} source_kind: aws_challenge_foothold source_selector: @@ -989,19 +989,18 @@ selector: aws_challenge_fact: aws-v3-32-reuse-another-user-s-cached-sts-role-credentials-or-sta scope: same_account - aggregate_as: Verified Reuse another user's cached STS role credentials or static IAM user keys from local AWS CLI - files targets in {account} + aggregate_as: Verified cached STS role sessions in {account} grants: - - exact owner principal. + - Exact issuing role of the live STS session. conditions: - id: exact_external_foothold - description: No edge from mere existence of a shared host or AWS CLI installation. Source evidence must prove local - control for the exact target. + description: Source evidence must prove local read access to another user's CLI cache, live STS credentials + and exact issuing role. confidence: conditional severity: high mitigation: Restrict access to the source primitive and revoke exposed credentials or sessions. - notes: The synthetic source is only a hypothesis until an exact verified evidence item exists; no IAM principal is - inferred from configuration. + notes: The synthetic local foothold stays UNKNOWN until an exact evidence item identifies the source and issuing + role. - id: aws-v3-33-read-aws-vpn-client-temporary-credentials-from-another provider: aws service: challenge-evidence @@ -2613,3 +2612,67 @@ - https://docs.aws.amazon.com/msk/latest/developerguide/what-is-msk.html notes: Missing aws_privesc_challenge_evidence is UNKNOWN; evidence must bind TechniqueId, SourceArn, TargetKind, TargetId and TargetAccount and prove all prerequisites. + +- id: aws-chime-attendee-jointoken-read + provider: aws + service: chime + title: Read another Chime meeting attendee JoinToken + source: src/pentesting-cloud/aws-security/aws-services/aws-chime-sdk-enum.md#meetings + summary: GetAttendee or ListAttendees returns a bearer JoinToken for an existing attendee. + requires: + any_of: + - - action: chime:GetAttendee + resource: '*' + - - action: chime:ListAttendees + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-chime-attendee-jointoken-read + scope: same_account + aggregate_as: Verified Read another Chime meeting attendee JoinToken targets in {account} + grants: + - Join the exact meeting as the represented attendee. + conditions: + - id: exact_verified_prerequisites + description: The meeting and a different active attendee must exist; a nonempty token must be returned, and + evidence must bind the source, meeting and attendee. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: medium + mitigation: Restrict the exact read permission and protect returned credentials. + references: + - https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_meeting-chime_GetAttendee.html + notes: Absent or stale evidence must evaluate UNKNOWN; do not store the credential value in the snapshot. + +- id: aws-chime-rtmp-publisher-key-read + provider: aws + service: chime + title: Read live connector RTMP publishing key + source: src/pentesting-cloud/aws-security/aws-services/aws-chime-sdk-enum.md#media-pipelines + summary: GetMediaPipeline returns the complete RTMP destination URL including its stream key. + requires: + all_of: + - action: chime:GetMediaPipeline + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-chime-rtmp-publisher-key-read + scope: same_account + aggregate_as: Verified Read live connector RTMP publishing key targets in {account} + grants: + - Publish to the exact downstream live-stream destination. + conditions: + - id: exact_verified_prerequisites + description: The selected pipeline must be a live connector with a nonempty RTMP(S) stream key; the destination + must still accept that key. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: medium + mitigation: Restrict the exact read permission and protect returned credentials. + references: + - https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_media-pipelines_GetMediaPipeline.html + notes: Absent or stale evidence must evaluate UNKNOWN; do not store the credential value in the snapshot. diff --git a/src/privilege-escalation-paths/aws/codebuild.yaml b/src/privilege-escalation-paths/aws/codebuild.yaml index 48c73e0261..395c4b8ca2 100644 --- a/src/privilege-escalation-paths/aws/codebuild.yaml +++ b/src/privilege-escalation-paths/aws/codebuild.yaml @@ -438,3 +438,38 @@ references: - https://docs.aws.amazon.com/codebuild/latest/APIReference/Welcome.html notes: Required collector evidence is absent from current snapshots; missing evidence remains UNKNOWN/unresolved. + +- id: aws-codebuild-read-plaintext-aws-credential + provider: aws + service: codebuild + title: Recover another AWS principal's credential from build variables + source: src/pentesting-cloud/aws-security/aws-services/aws-codebuild-enum.md#enumeration + source_revision: 0b36331 + summary: A readable project or build exposes a verified credential belonging to another principal in a PLAINTEXT + environment variable. + requires: + any_of: + - - action: codebuild:BatchGetProjects + resource: '*' + - - action: codebuild:BatchGetBuilds + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-codebuild-read-plaintext-aws-credential + scope: same_account + aggregate_as: Verified AWS identities exposed by readable CodeBuild environment values in {account} + grants: + - The exact AWS permissions of the verified credential owner during credential validity. + conditions: + - id: exact_credential_binding + description: Evidence must identify the exact readable project or build, source principal, credential owner + and validity interval; PARAMETER_STORE and SECRETS_MANAGER references do not qualify. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Keep credentials out of PLAINTEXT build variables and restrict CodeBuild metadata reads. + references: + - https://docs.aws.amazon.com/codebuild/latest/userguide/build-env-ref-env-vars.html + notes: The verified-authority fact is absent from current snapshots; without it the result remains UNKNOWN. diff --git a/src/privilege-escalation-paths/aws/cognito.yaml b/src/privilege-escalation-paths/aws/cognito.yaml index 5d0112cc8e..e9ee392abc 100644 --- a/src/privilege-escalation-paths/aws/cognito.yaml +++ b/src/privilege-escalation-paths/aws/cognito.yaml @@ -487,3 +487,37 @@ client ID and configured flow. notes: The existing aws-v3-25 entry is for DescribeUserPoolClient, a different Cognito secret and action. Missing external validation must evaluate UNKNOWN. + +- id: aws-cognito-describeidentityprovider-upstream-client-secret + provider: aws + service: cognito-idp + title: Recover an upstream identity provider's OAuth client credential + source: src/pentesting-cloud/aws-security/aws-services/aws-cognito-enum/cognito-user-pools.md#directory-and-client-secret-disclosure + source_revision: 0b36331 + summary: DescribeIdentityProvider exposes a verified upstream social or OIDC client secret and its bounded OAuth + application authority. + requires: + all_of: + - action: cognito-idp:DescribeIdentityProvider + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-cognito-describeidentityprovider-upstream-client-secret + scope: same_account + aggregate_as: Verified upstream OAuth clients exposed by Cognito IdP configuration in {account} + grants: + - The verified upstream OAuth client identity and its permitted application scopes. + conditions: + - id: exact_upstream_client + description: Evidence must bind the source, user pool, provider, live client secret and actual upstream OAuth + privileges; it does not imply a Cognito user or IAM role. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict DescribeIdentityProvider and rotate exposed upstream client secrets. + references: + - https://docs.aws.amazon.com/cognito-user-identity-pools/latest/APIReference/API_DescribeIdentityProvider.html + notes: The existing DescribeUserPoolClient technique covers a different secret and permission. Missing verified + evidence is UNKNOWN. diff --git a/src/privilege-escalation-paths/aws/connect.yaml b/src/privilege-escalation-paths/aws/connect.yaml index 56154b58c2..1dbe4ff491 100644 --- a/src/privilege-escalation-paths/aws/connect.yaml +++ b/src/privilege-escalation-paths/aws/connect.yaml @@ -260,3 +260,39 @@ conditions: - The page describes possible credential capture; IAM permission alone does not prove content, owner, validity or usable downstream scope. + +- id: aws-connect-createparticipant-bearer + provider: aws + service: connect + title: Mint a participant bearer for an active Connect contact + source: src/pentesting-cloud/aws-security/aws-services/aws-connect-enum.md#authorization-and-unauthenticated-boundary + source_revision: 0b36331 + summary: CreateParticipant grants an additional chat or WebRTC participant identity for a verified active contact. + requires: + all_of: + - action: connect:CreateParticipant + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-connect-createparticipant-bearer + scope: same_account + aggregate_as: Verified Connect participant identities for active contacts in {account} + grants: + - The participant role's chat or WebRTC capabilities for the exact active contact. + conditions: + - id: exact_active_contact + description: The source must know the initial contact ID, hold CreateParticipant on both required Contact and + Instance resources, and satisfy channel-specific role and state limits. + - id: short_token_lifetime + description: The participant token must be exchanged promptly; a stale contact snapshot cannot prove a successful + join. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict CreateParticipant on Contact and Instance resources and monitor unexpected participant joins. + references: + - https://docs.aws.amazon.com/connect/latest/APIReference/API_CreateParticipant.html + notes: aws_verified_authority represents the bounded Connect participant identity; no new target kind is required. + Missing evidence is UNKNOWN. diff --git a/src/privilege-escalation-paths/aws/gameliftstreams.yaml b/src/privilege-escalation-paths/aws/gameliftstreams.yaml index 27c892a4c2..9d9fc7b753 100644 --- a/src/privilege-escalation-paths/aws/gameliftstreams.yaml +++ b/src/privilege-escalation-paths/aws/gameliftstreams.yaml @@ -44,3 +44,40 @@ - 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. + +- id: aws-audit-gameliftstreams-bearer-url + provider: aws + service: gameliftstreams + title: Use a GameLift Streams bearer URL + source: src/pentesting-cloud/aws-security/aws-services/aws-gamelift-streams-enum.md#enumerate-bearer-stream-urls + summary: The source obtains a new application session without the creator’s AWS credentials. + requires: + any_of: + - - action: gameliftstreams:ListStreamUrls + resource: '*' + - - action: gameliftstreams:GetStreamUrl + resource: arn:aws:gameliftstreams:*:{account}:streamgroup/* + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-audit-gameliftstreams-bearer-url + scope: same_account + aggregate_as: Verified application sessions reachable through GameLift Streams bearer URLs + outcome: scope_control + grants: + - The source obtains a new application session without the creator’s AWS credentials. + conditions: + - id: active_bearer + description: The URL must be active, unexpired, have remaining uses, and start a distinct application session. + A role ARN shown in metadata does not by itself grant that IAM role to the browser session. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Scope the listed actions to approved resources and review linked targets and effective authorization. + notes: No definite edge from IAM permission alone. An exact active bearer URL and target application-session authority + must be verified; missing collector evidence is UNKNOWN. + source_revision: 0b36331 + references: + - https://docs.aws.amazon.com/gameliftstreams/latest/apireference/API_ListStreamUrls.html + - https://docs.aws.amazon.com/gameliftstreams/latest/apireference/API_GetStreamUrl.html diff --git a/src/privilege-escalation-paths/aws/healthomics.yaml b/src/privilege-escalation-paths/aws/healthomics.yaml index bd9a59f414..16435fbdd0 100644 --- a/src/privilege-escalation-paths/aws/healthomics.yaml +++ b/src/privilege-escalation-paths/aws/healthomics.yaml @@ -36,3 +36,36 @@ references: - https://docs.aws.amazon.com/omics/latest/dev/permissions-service.html notes: No credentials are disclosed directly; the escalation is code execution in a managed workflow with the role's access. + +- id: aws-healthomics-cloudtrail-workflow-zip-credential + provider: aws + service: omics + title: Recover another identity credential from a logged HealthOmics workflow ZIP + source: src/pentesting-cloud/aws-security/aws-services/aws-healthomics-enum.md#cloudtrail-and-stealth + source_revision: 0b36331 + summary: Credential of the exact distinct identity found in the inline workflow ZIP when exact source, object, + credential, and target evidence is verified. + requires: + any_of: + - - action: cloudtrail:LookupEvents + resource: '*' + - - action: s3:GetObject + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-healthomics-cloudtrail-workflow-zip-credential + scope: same_account + grants: + - Credential of the exact distinct identity found in the inline workflow ZIP + conditions: + - id: verified_credential + description: A readable CreateWorkflow event contains definitionZip with a valid credential for a distinct identity. + For S3 trail objects, verify log-object access and any required kms:Decrypt; bind the exact event or object + and owner. + confidence: conditional + severity: high + mitigation: Do not put reusable credentials in workflow archives; restrict CloudTrail and trail-object readers. + references: + - https://docs.aws.amazon.com/omics/latest/dev/omics-permissions.html + notes: Exact aws_privesc_challenge_evidence is required. Missing or incomplete evidence remains UNKNOWN. diff --git a/src/privilege-escalation-paths/aws/keyspaces.yaml b/src/privilege-escalation-paths/aws/keyspaces.yaml new file mode 100644 index 0000000000..fa3ae4c4ae --- /dev/null +++ b/src/privilege-escalation-paths/aws/keyspaces.yaml @@ -0,0 +1,65 @@ +- id: aws-keyspaces-select-credential-row + provider: aws + service: cassandra + title: Recover another identity credential from a Keyspaces table row + source: src/pentesting-cloud/aws-security/aws-services/aws-keyspaces-enum.md#connect-to-cql-with-sigv4 + source_revision: 0b36331 + summary: Credential of the exact distinct AWS or application identity present in a readable row when exact source, + object, credential, and target evidence is verified. + requires: + all_of: + - action: cassandra:Select + resource: '*' + - action: cassandra:Select + resource: arn:aws:cassandra:*:*:/keyspace/system* + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-keyspaces-select-credential-row + scope: same_account + grants: + - Credential of the exact distinct AWS or application identity present in a readable row + conditions: + - id: verified_credential + description: The same source can read the exact table and system keyspace; a returned row contains a valid reusable + credential with verified owner and scope. A secrets table name alone is insufficient. + confidence: conditional + severity: high + mitigation: Restrict Select on credential-bearing tables and avoid storing reusable identity credentials. + references: + - https://docs.aws.amazon.com/keyspaces/latest/devguide/security_iam_service-with-iam.html + notes: Exact aws_privesc_challenge_evidence is required. Missing or incomplete evidence remains UNKNOWN. + +- id: aws-keyspaces-cdc-credential-record + provider: aws + service: cassandra + title: Recover another identity credential from a Keyspaces CDC record + source: src/pentesting-cloud/aws-security/aws-services/aws-keyspaces-enum.md#enumerate-and-read-cdc-streams + source_revision: 0b36331 + summary: Credential of the exact distinct identity present in a readable CDC image when exact source, object, + credential, and target evidence is verified. + requires: + all_of: + - action: cassandra:GetStream + resource: '*' + - action: cassandra:GetShardIterator + resource: '*' + - action: cassandra:GetRecords + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-keyspaces-cdc-credential-record + scope: same_account + grants: + - Credential of the exact distinct identity present in a readable CDC image + conditions: + - id: verified_credential + description: A retained stream image contains a valid reusable credential; verify exact stream read, image content, + credential validity and distinct owner. CDC enablement alone is insufficient. + confidence: conditional + severity: high + mitigation: Restrict CDC reads and avoid writing reusable credentials to CDC-enabled tables. + references: + - https://docs.aws.amazon.com/keyspaces/latest/devguide/configure-cdc-permissions.html + notes: Exact aws_privesc_challenge_evidence is required. Missing or incomplete evidence remains UNKNOWN. From 3c43236b73557f85c45e5d2116fd55b8f91a634f Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Mon, 12 Oct 2026 21:02:59 +0200 Subject: [PATCH 07/17] Integrate verified AWS services privesc fragments Co-Authored-By: Codex --- .../aws/_excluded_b.yaml | 21 +- .../aws/_excluded_refresh_g4.yaml | 10 +- .../aws/_excluded_refresh_g6.yaml | 19 +- .../aws/_excluded_verify_a66f.yaml | 42 ++- .../aws/challenge-v3.yaml | 337 ++++++++++++++++-- .../aws/events.yaml | 35 +- .../aws/lambda.yaml | 172 +++++++++ src/privilege-escalation-paths/aws/lex.yaml | 34 ++ .../aws/lightsail.yaml | 33 ++ .../aws/payment-cryptography.yaml | 35 ++ .../aws/qbusiness.yaml | 42 +++ src/privilege-escalation-paths/aws/rds.yaml | 34 ++ .../aws/scheduler.yaml | 34 ++ 13 files changed, 773 insertions(+), 75 deletions(-) create mode 100644 src/privilege-escalation-paths/aws/lex.yaml create mode 100644 src/privilege-escalation-paths/aws/lightsail.yaml create mode 100644 src/privilege-escalation-paths/aws/payment-cryptography.yaml create mode 100644 src/privilege-escalation-paths/aws/qbusiness.yaml diff --git a/src/privilege-escalation-paths/aws/_excluded_b.yaml b/src/privilege-escalation-paths/aws/_excluded_b.yaml index 8f225728f1..ddaee338ad 100644 --- a/src/privilege-escalation-paths/aws/_excluded_b.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_b.yaml @@ -17,15 +17,16 @@ 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: 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. + reason: 'Pending an exact KMS-key service-authority selector: PutKeyPolicy can grant new rights on the same customer + managed key, but key policy, IAM conditions and lockout check must be evaluated; it is not IAM account administration.' - 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. + reason: 'Pending an exact KMS-key grant authority selector: CreateGrant may grant new Encrypt, Decrypt or GenerateDataKey + rights on one key, constrained by grantability and grant constraints; no IAM role is obtained.' - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-kms-privesc/README.md#kmscreatekey-kmsreplicatekey source_revision: a53b46392c @@ -213,16 +214,16 @@ source_revision: a53b46392c technique: lambda:PutProvisionedConcurrencyConfig reason: Triggers init of fixed code; no control of code or role. -- source: - src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunction--download-a-function-deployment-package +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunction--download-a-function-deployment-package source_revision: a53b46392c technique: lambda:GetFunction - reason: Data read. -- source: - src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunctionconfiguration--read-environment-variables + reason: GetFunction can return a deployment package URL; any identity gain depends on downloaded code/content + holding a usable credential for a distinct principal. +- source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunctionconfiguration--read-environment-variables source_revision: a53b46392c technique: lambda:GetFunctionConfiguration - reason: Data read. + reason: Configuration access can reveal an identity credential in Environment.Variables, but no target principal + follows from permission alone; require verified credential and distinct identity. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetlayerversion--download-layer-code source_revision: a53b46392c diff --git a/src/privilege-escalation-paths/aws/_excluded_refresh_g4.yaml b/src/privilege-escalation-paths/aws/_excluded_refresh_g4.yaml index 1a87484aec..d276daa11e 100644 --- a/src/privilege-escalation-paths/aws/_excluded_refresh_g4.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_refresh_g4.yaml @@ -117,13 +117,11 @@ 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: 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: 'Pending a Lake Formation Regional administrator target selector: PutDataLakeSettings can name an attacker + principal as data lake administrator; this grants LF governance authority, not IAM admin or automatic data SELECT.' 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" diff --git a/src/privilege-escalation-paths/aws/_excluded_refresh_g6.yaml b/src/privilege-escalation-paths/aws/_excluded_refresh_g6.yaml index 5890336e96..1cdd764d75 100644 --- a/src/privilege-escalation-paths/aws/_excluded_refresh_g6.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_refresh_g6.yaml @@ -74,12 +74,13 @@ 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 +- 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 + reason: This is a real self-permission escalation, but a sound key-operation edge needs an exact primary key ARN, + key attributes/state, the selected operation, and effective explicit-deny/SCP/boundary checks. Those facts are + not all present in current snapshots; a generic same-account service-plane target would overstate usable cryptographic + access. Keep UNKNOWN until collected. + source_revision: 0b36331 - 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 @@ -196,3 +197,11 @@ reason: The AWS snapshot can show an alias mapping but cannot establish which application resolves the alias or that the selected store permits a privileged action for an attacker-controlled principal. source_revision: 171e422299 +- source: src/pentesting-cloud/aws-security/aws-services/aws-nova-act-enum.md#basic-information + technique: Read a credential from an exported Nova Act trajectory + reason: Export configuration and S3 read permission do not establish that an exported object contains a reusable + password or token, that it is still valid, or which stronger identity it belongs to. Those facts require inspecting + the object content and validating the credential against its issuer or application; a configuration-only snapshot + cannot identify a safe privilege-escalation target. GetWorkflowDefinition only discloses the export location + and grants no S3 read permission. + source_revision: 0b36331 diff --git a/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml b/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml index 6a17cb7d4d..e14eef1daa 100644 --- a/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_verify_a66f.yaml @@ -198,9 +198,9 @@ 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.' + reason: 'Documented grant can add privilege, but this catalog cannot safely emit the edge until the evaluator + supports: Add aws_service_data_access target for recipient account and ARC readiness authorization; selector + must bind eligible known victim resource ARN and supported check type.' 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)' @@ -1942,11 +1942,8 @@ 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: RDS Proxy backend Secrets Manager auth secrets contain a database username/password, so a DB identity - can be gained. Current schema has no database-user target or proxy-auth secret binding. Add aws_database_user - and bind DescribeDBProxies Auth.SecretArn to the exact backend user; collect DescribeDBProxies and DescribeDBProxyTargets - (IAM rds:DescribeDBProxies, rds:DescribeDBProxyTargets), snapshot key rds_proxy_auth {proxy_arn,secret_arn,db_user,target_db_arn}; - UNKNOWN until collected and GetSecretValue/KMS rights are resolved. + reason: Documented proxy auth secret yields a reusable DB username/password. Pending proxy-to-secret collector + and exact GetSecretValue/KMS evaluation; do not infer credentials from DescribeDBProxies alone. source_revision: a66f094ede - source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md#rdsdownloaddblogfileportion technique: '`rds:DownloadDBLogFilePortion`' @@ -2752,18 +2749,21 @@ 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. + reason: sdb:GetAttributes can return token-bearing attributes from a known domain and item. Whether the item exists + and contains a valid reusable token, and which identity owns that token, require item-content and owner evidence + unavailable from IAM configuration; no deterministic identity edge follows from the permission alone. 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. + reason: sdb:Select can enumerate items and attributes in a known domain, including possible reusable tokens. Actual + token contents, validity and owning identity are unavailable from IAM configuration; no deterministic identity + edge exists without verified content and owner mapping. 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. + reason: This enumeration table indexes existing Transfer escalation paths aws-transfer-importsshpublickey, aws-transfer-passrole-createuser-access, + aws-transfer-secret-backed-idp-record, aws-transfer-custom-idp-takeover, and aws-transfer-workflow-passrole-updateserver + in transfer.yaml. The table adds no separate technique. 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' @@ -2777,8 +2777,8 @@ 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. + reason: Target.Input may hold a usable credential for a distinct identity; RoleArn and other ARNs are locators. + UNKNOWN until literal content and authentication are verified. source_revision: a66f094ede - source: src/pentesting-cloud/aws-security/aws-services/eventbridgescheduler-enum.md#pipesupdatepipe-revalidates-iampassrole technique: '`pipes:UpdatePipe` revalidates `iam:PassRole`' @@ -3363,3 +3363,13 @@ identity; these response/content facts are absent from the configuration snapshot. Authorization also requires GetConnection on both catalog and exact connection ARN. source_revision: 0b36331 +- source: src/pentesting-cloud/aws-security/aws-services/aws-managed-flink-enum.md#enumerate-applications-and-complete-configuration + technique: Read current cleartext runtime properties containing reusable credentials + reason: Current runtime property values must actually contain an active reusable credential and its owner/authority + must be verified; the configuration snapshot exposes only arbitrary strings, not credential validity or target + identity. +- source: src/pentesting-cloud/aws-security/aws-services/aws-managed-flink-enum.md#enumerate-historical-versions-and-operations + technique: Read historical cleartext runtime properties containing reusable credentials + reason: Historical runtime property values must actually contain an active reusable credential and its owner/authority + must be verified; the configuration snapshot exposes only arbitrary strings, not credential validity or target + identity. diff --git a/src/privilege-escalation-paths/aws/challenge-v3.yaml b/src/privilege-escalation-paths/aws/challenge-v3.yaml index 09a260470b..e64c5c3384 100644 --- a/src/privilege-escalation-paths/aws/challenge-v3.yaml +++ b/src/privilege-escalation-paths/aws/challenge-v3.yaml @@ -821,14 +821,15 @@ provider: aws service: kinesisvideo title: Join Kinesis Video signaling as a master or viewer peer - source: - src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kinesis-video-streams-post-exploitation/README.md#recover-turn-credentials-and-impersonate-webrtc-peers - summary: Kinesis Video ConnectAsMaster/Viewer -> exact signaling-channel peer role. Exact source, target and - prerequisite proof are required. + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-kinesis-video-streams-post-exploitation/README.md#recover-turn-credentials-and-impersonate-webrtc-peers + summary: Kinesis Video ConnectAsMaster/Viewer -> exact signaling-channel peer role. Exact source, target and prerequisite + proof are required. requires: - all_of: - - action: kinesisvideo:ConnectAsViewer - resource: '*' + any_of: + - - action: kinesisvideo:ConnectAsViewer + resource: '*' + - - action: kinesisvideo:ConnectAsMaster + resource: '*' target: kind: aws_verified_authority selector: @@ -846,8 +847,8 @@ confidence: conditional severity: high mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is - UNKNOWN/unresolved; verified evidence never creates a definite path. + notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence + is UNKNOWN/unresolved; verified evidence never creates a definite path. - id: aws-v3-28-reach-a-lambda-execution-role-through-unsafe-workflow-i provider: aws service: states @@ -1541,35 +1542,41 @@ - id: aws-v3-52-network-security-manager-delegate provider: aws service: network-security-manager - title: Network Security Manager delegate - source: - src/pentesting-cloud/aws-security/aws-persistence/aws-network-security-manager-persistence/README.md#network-security-managerputadminaccount--retain-delegated-network-security-administration - summary: Add exact organization-delegate service-plane target (`fms`, `network-security-manager`, `inspector2`) scoped - to a **controlled member account**; require row-specific delegate action. Exact source, target and prerequisite - proof are required. + title: Delegate regional Network Security Manager administration to a controlled member account + source: src/pentesting-cloud/aws-security/aws-persistence/aws-network-security-manager-persistence/README.md#network-security-managerputadminaccount--retain-delegated-network-security-administration + source_revision: 0b36331 + summary: A management-account principal can designate a controlled member account to administer WAF and Shield + protections within its delegated Region and administrator scope. requires: all_of: - action: network-security-manager:PutAdminAccount resource: '*' + preconditions: + - source_in_org_management_account target: kind: aws_verified_authority selector: aws_challenge_fact: aws-v3-52-network-security-manager-delegate - scope: same_account - aggregate_as: Verified Network Security Manager delegate targets in {account} + scope: org + outcome: application_admin grants: - - Add exact organization-delegate service-plane target (`fms`, `network-security-manager`, ` + - Network Security Manager WAF/Shield administration for the verified Region, account/OU and firewall-type scope + aggregate_as: Verified Network Security Manager delegated authority conditions: - - id: exact_verified_prerequisites - description: A reviewed evidence record must bind this technique, the acting IAM principal and the exact target; - Controlled member account and exact NSM delegation state. + - id: verified_delegation + description: Evidence must bind the controlled member account and identity, Region, exact scope, administrator + priority, all-features organization and trusted-access/delegated-administrator state. + - id: first_time_setup + description: If setup is absent, organizations:EnableAWSServiceAccess, organizations:RegisterDelegatedAdministrator + and iam:CreateServiceLinkedRole may also be needed. blockers: - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence is - UNKNOWN/unresolved; verified evidence never creates a definite path. + mitigation: Restrict PutAdminAccount in the management account and audit regional administrator accounts, priorities + and scopes. + references: + - https://docs.aws.amazon.com/network-security-manager/latest/APIReference/API_PutAdminAccount.html - id: aws-v3-53-influxdb-admin-credentials provider: aws service: secretsmanager @@ -1635,34 +1642,35 @@ - id: aws-v3-55-opensearch-domain-policy provider: aws service: es - title: OpenSearch domain policy + title: Grant signed OpenSearch HTTP operations through a domain access policy source: src/pentesting-cloud/aws-security/aws-persistence/aws-opensearch-access-policy-persistence/README.md#esupdatedomainconfig--domain-access-policy-takeover - summary: 'Add `service_plane: opensearch` and domain selector; require `es:UpdateDomainConfig` for exact domain - policy. Exact source, target and prerequisite proof are required.' + source_revision: 0b36331 + summary: A domain configuration editor can add its own IAM principal to the exact domain policy and gain signed + HTTP read or write operations permitted by the domain. requires: all_of: - action: es:UpdateDomainConfig - resource: '*' + resource: '{target.resource_arn}' target: kind: aws_verified_authority selector: aws_challenge_fact: aws-v3-55-opensearch-domain-policy scope: same_account - aggregate_as: Verified OpenSearch domain policy targets in {account} + outcome: permission_grant grants: - - OpenSearch HTTP data access allowed by both domain policy and fine-grained access control + - es:ESHttpGet or other explicitly verified es:ESHttp* operations on the exact domain + aggregate_as: Verified OpenSearch domain data-plane authority conditions: - - id: exact_verified_prerequisites - description: Evidence must bind the exact domain, controlled IAM principal, allowed ESHttp action, reachable - endpoint and effective domain policy. If fine-grained access control is enabled, prove that its role mapping - also permits the requested index/action; explicit denies and KMS can still block access. + - id: effective_domain_access + description: Evidence must bind the exact domain ARN and HTTP action, policy processing completion, endpoint + reachability, FGAC authorization and absence of effective denies. blockers: - scp_or_boundary_deny confidence: conditional severity: high - mitigation: Restrict the listed mutation or read permission and review its exact resource scope. - notes: The required aws_privesc_challenge_evidence collection is absent from current snapshots. Missing evidence - is UNKNOWN/unresolved; verified evidence never creates a definite path. + mitigation: Restrict es:UpdateDomainConfig on exact domains and alert on domain access-policy changes. + references: + - https://docs.aws.amazon.com/opensearch-service/latest/APIReference/API_UpdateDomainConfig.html - id: aws-v3-56-marketplace-seller-entity-policy provider: aws service: aws-marketplace @@ -2676,3 +2684,258 @@ references: - https://docs.aws.amazon.com/chime-sdk/latest/APIReference/API_media-pipelines_GetMediaPipeline.html notes: Absent or stale evidence must evaluate UNKNOWN; do not store the credential value in the snapshot. +- id: aws-payment-cryptography-sameaccount-key-policy + provider: aws + service: payment-cryptography + title: Grant the source new operations on a primary payment key + source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-payment-cryptography-privesc/README.md#payment-cryptographyputresourcepolicy + source_revision: 0b36331 + summary: A policy editor can grant its own same-account IAM identity compatible operations on an exact primary + payment key. + requires: + all_of: + - action: payment-cryptography:PutResourcePolicy + resource: '{target.resource_arn}' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-payment-cryptography-sameaccount-key-policy + scope: same_account + outcome: permission_grant + grants: + - Verified compatible payment-key operation on the exact primary key + aggregate_as: Verified same-account payment-key authority + conditions: + - id: exact_key_and_operation + description: Evidence must bind source identity, primary key ARN, chosen compatible operation and absence of + effective explicit denies; export also requires exportability and wrapping setup. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict PutResourcePolicy on primary keys and review new same-account principal grants. + references: + - https://docs.aws.amazon.com/payment-cryptography/latest/userguide/security_iam_resource-based-policies.html +- id: aws-ssm-sap-hana-admin-secret + provider: aws + service: ssm-sap + title: Read a registered SAP HANA ADMIN secret + source: src/pentesting-cloud/aws-security/aws-services/aws-systems-manager-for-sap-enum.md#applications-components-and-databases + summary: GetDatabase identifies an ADMIN SecretId; reading that exact secret may yield the HANA administrator + credential. + requires: + all_of: + - action: secretsmanager:GetSecretValue + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-ssm-sap-hana-admin-secret + scope: same_account + aggregate_as: Verified affected identities in {account} + grants: + - Native SAP HANA ADMIN login + conditions: + - id: exact_verified_prerequisites + description: ssm-sap:GetDatabase (Resource *) and secretsmanager:GetSecretValue on the returned SecretId; kms:Decrypt + on its KMS key if needed. Evidence must bind this IAM source, exact target and usable privilege; absent evidence + remains UNKNOWN. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict secretsmanager:GetSecretValue to trusted administrators at the exact resource scope. + references: + - https://docs.aws.amazon.com/ssmsap/latest/APIReference/API_GetDatabase.html + - https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html + notes: Requires an exact aws_privesc_challenge_evidence record proving IAM authorization on the specific source + resource and all external prerequisites. Missing or incomplete evidence is UNKNOWN; a verified record yields + only a conditional edge. +- id: aws-transfer-connector-remote-credential + provider: aws + service: transfer + title: Read a Transfer connector remote SFTP credential + source: src/pentesting-cloud/aws-security/aws-services/aws-transfer-family-enum.md#main-resource-relationships + summary: DescribeConnector identifies UserSecretId; reading the exact secret may yield the configured remote SFTP + credential. + requires: + all_of: + - action: secretsmanager:GetSecretValue + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-transfer-connector-remote-credential + scope: any + aggregate_as: Verified affected identities in {account} + grants: + - Remote SFTP user identity + conditions: + - id: exact_verified_prerequisites + description: transfer:DescribeConnector for discovery and secretsmanager:GetSecretValue on UserSecretId; kms:Decrypt + where needed. Evidence must bind this IAM source, exact target and usable privilege; absent evidence remains + UNKNOWN. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict secretsmanager:GetSecretValue to trusted administrators at the exact resource scope. + references: + - https://docs.aws.amazon.com/transfer/latest/APIReference/API_DescribeConnector.html + - https://docs.aws.amazon.com/secretsmanager/latest/apireference/API_GetSecretValue.html + notes: Requires an exact aws_privesc_challenge_evidence record proving IAM authorization on the specific source + resource and all external prerequisites. Missing or incomplete evidence is UNKNOWN; a verified record yields + only a conditional edge. +- id: aws-verifiedpermissions-policy-app-admin + provider: aws + service: verifiedpermissions + title: Grant application privileges through a Cedar policy + source: src/pentesting-cloud/aws-security/aws-services/aws-verified-permissions-enum.md#exact-iam-boundaries + summary: A policy or template writer can add a Cedar permit for an attacker-controlled application principal where + a consuming application honors that decision. + requires: + any_of: + - - action: verifiedpermissions:CreatePolicy + resource: '*' + - - action: verifiedpermissions:UpdatePolicy + resource: '*' + - - action: verifiedpermissions:UpdatePolicyTemplate + resource: '*' + - - action: verifiedpermissions:CreatePolicyTemplate + resource: '*' + - action: verifiedpermissions:CreatePolicy + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-verifiedpermissions-policy-app-admin + scope: same_account + aggregate_as: Verified affected identities in {account} + grants: + - Exact application administrator privilege represented by Cedar action/resource + conditions: + - id: exact_verified_prerequisites + description: CreatePolicy or UpdatePolicy on exact store; UpdatePolicyTemplate for existing linked policies; + CreatePolicyTemplate plus CreatePolicy for a new linked policy. Evidence must bind this IAM source, exact + target and usable privilege; absent evidence remains UNKNOWN. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict verifiedpermissions:CreatePolicy to trusted administrators at the exact resource scope. + references: + - https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/policies-create.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_verifiedpermissions.html + notes: Requires an exact aws_privesc_challenge_evidence record proving IAM authorization on the specific source + resource and all external prerequisites. Missing or incomplete evidence is UNKNOWN; a verified record yields + only a conditional edge. +- id: aws-verifiedpermissions-identity-source-impersonation + provider: aws + service: verifiedpermissions + title: Redirect application token trust to an attacker-controlled identity + source: src/pentesting-cloud/aws-security/aws-services/aws-verified-permissions-enum.md#identity-source-and-cross-account-boundaries + summary: Changing the identity source can map a valid attacker token into a privileged Cedar principal or group + used by an application. + requires: + any_of: + - - action: verifiedpermissions:UpdateIdentitySource + resource: '*' + - - action: verifiedpermissions:CreateIdentitySource + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-verifiedpermissions-identity-source-impersonation + scope: same_account + aggregate_as: Verified affected identities in {account} + grants: + - Privileged application principal or group + conditions: + - id: exact_verified_prerequisites + description: UpdateIdentitySource or CreateIdentitySource on exact store. Evidence must bind this IAM source, + exact target and usable privilege; absent evidence remains UNKNOWN. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict verifiedpermissions:UpdateIdentitySource to trusted administrators at the exact resource + scope. + references: + - https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/identity-sources.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_verifiedpermissions.html + notes: Requires an exact aws_privesc_challenge_evidence record proving IAM authorization on the specific source + resource and all external prerequisites. Missing or incomplete evidence is UNKNOWN; a verified record yields + only a conditional edge. +- id: aws-verifiedpermissions-alias-rebind + provider: aws + service: verifiedpermissions + title: Rebind a production alias to a permissive policy store + source: src/pentesting-cloud/aws-security/aws-services/aws-verified-permissions-enum.md#enumerate-stores-and-aliases + summary: Deleting and recreating a policy-store alias can cause an application to use a different store that permits + attacker actions. + requires: + all_of: + - action: verifiedpermissions:DeletePolicyStoreAlias + resource: '*' + - action: verifiedpermissions:CreatePolicyStoreAlias + resource: '*' + - action: verifiedpermissions:CreatePolicyStoreAlias + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-verifiedpermissions-alias-rebind + scope: same_account + aggregate_as: Verified affected identities in {account} + grants: + - Application action/resource denied by original store + conditions: + - id: exact_verified_prerequisites + description: DeletePolicyStoreAlias on alias and CreatePolicyStoreAlias on alias and destination store; optional + CreatePolicyStore/policy writes if destination must be built. Evidence must bind this IAM source, exact target + and usable privilege; absent evidence remains UNKNOWN. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict verifiedpermissions:DeletePolicyStoreAlias to trusted administrators at the exact resource + scope. + references: + - https://docs.aws.amazon.com/verifiedpermissions/latest/userguide/policy-store-aliases-using.html + - https://docs.aws.amazon.com/service-authorization/latest/reference/list_verifiedpermissions.html + notes: Requires an exact aws_privesc_challenge_evidence record proving IAM authorization on the specific source + resource and all external prerequisites. Missing or incomplete evidence is UNKNOWN; a verified record yields + only a conditional edge. +- id: aws-waf-sampled-request-session-replay + provider: aws + service: wafv2 + title: Replay a session recovered from WAF request samples + source: src/pentesting-cloud/aws-security/aws-post-exploitation/aws-waf-post-exploitation/README.md#aws-waf-log-credential-harvesting-and-request-replay + summary: GetSampledRequests can expose an unmasked, still-valid session credential for an exact victim identity. + requires: + all_of: + - action: wafv2:GetSampledRequests + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-waf-sampled-request-session-replay + scope: any + aggregate_as: Verified affected identities in {account} + grants: + - Exact victim application or AWS session + conditions: + - id: exact_verified_prerequisites + description: GetSampledRequests on exact Web ACL; no list permission if ARN and metric are known. Evidence must + bind this IAM source, exact target and usable privilege; absent evidence remains UNKNOWN. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict wafv2:GetSampledRequests to trusted administrators at the exact resource scope. + references: + - https://docs.aws.amazon.com/waf/latest/APIReference/API_GetSampledRequests.html + - https://docs.aws.amazon.com/waf/latest/developerguide/web-acl-data-protection.html + notes: Requires an exact aws_privesc_challenge_evidence record proving IAM authorization on the specific source + resource and all external prerequisites. Missing or incomplete evidence is UNKNOWN; a verified record yields + only a conditional edge. diff --git a/src/privilege-escalation-paths/aws/events.yaml b/src/privilege-escalation-paths/aws/events.yaml index 28738c5143..aeac818c80 100644 --- a/src/privilege-escalation-paths/aws/events.yaml +++ b/src/privilege-escalation-paths/aws/events.yaml @@ -1,4 +1,37 @@ # Amazon EventBridge privilege escalation techniques. # Source: hacktricks-cloud aws-eventbridge-privesc/README.md (rev 171e422299). -[] +- id: aws-events-listtargets-static-credential + provider: aws + service: events + title: Recover another identity credential from static rule target Input + source: src/pentesting-cloud/aws-security/aws-services/eventbridgescheduler-enum.md#eventbridge-rule-targets + source_revision: 0b36331 + summary: Recover another identity credential from static rule target Input when the exact target and prerequisites + are verified. + requires: + all_of: + - action: events:ListTargetsByRule + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-events-listtargets-static-credential + scope: same_account + aggregate_as: Verified Recover another identity credential from static rule target Input targets in {account} + grants: + - exact identity authenticated by the literal credential + outcome: permission_grant + conditions: + - id: exact_verified_prerequisites + description: A known rule must return literal static Input containing a credential verified as usable for a + distinct identity; InputPath, future events and RoleArn do not qualify. + 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/eventbridge/latest/APIReference/API_ListTargetsByRule.html + notes: The required aws_privesc_challenge_evidence fact is not collected in current snapshots. Missing or incomplete + evidence evaluates UNKNOWN. diff --git a/src/privilege-escalation-paths/aws/lambda.yaml b/src/privilege-escalation-paths/aws/lambda.yaml index 3e97be97f7..2cf95d2aca 100644 --- a/src/privilege-escalation-paths/aws/lambda.yaml +++ b/src/privilege-escalation-paths/aws/lambda.yaml @@ -814,3 +814,175 @@ 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-listfunctions-secret-identity + provider: aws + service: lambda + title: Recover a distinct identity credential from ListFunctions environment + source: src/pentesting-cloud/aws-security/aws-services/aws-lambda-enum.md#enumeration + source_revision: 0b36331 + summary: Recover a distinct identity credential from ListFunctions environment when the exact target and prerequisites + are verified. + requires: + all_of: + - action: lambda:ListFunctions + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-lambda-listfunctions-secret-identity + scope: same_account + aggregate_as: Verified Recover a distinct identity credential from ListFunctions environment targets in {account} + grants: + - exact distinct identity authenticated by the recovered credential + outcome: permission_grant + conditions: + - id: exact_verified_prerequisites + description: The exact returned Environment.Variables must contain a currently usable credential for a distinct + target identity; arbitrary secrets, identifiers or text produce no edge. + 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: The required aws_privesc_challenge_evidence fact is not collected in current snapshots. Missing or incomplete + evidence evaluates UNKNOWN. +- id: aws-lambda-listversions-secret-identity + provider: aws + service: lambda + title: Recover a distinct identity credential from ListVersionsByFunction environment + source: src/pentesting-cloud/aws-security/aws-services/aws-lambda-enum.md#enumeration + source_revision: 0b36331 + summary: Recover a distinct identity credential from ListVersionsByFunction environment when the exact target + and prerequisites are verified. + requires: + all_of: + - action: lambda:ListVersionsByFunction + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-lambda-listversions-secret-identity + scope: same_account + aggregate_as: Verified Recover a distinct identity credential from ListVersionsByFunction environment targets + in {account} + grants: + - exact distinct identity authenticated by the recovered credential + outcome: permission_grant + conditions: + - id: exact_verified_prerequisites + description: The exact returned version Environment.Variables must contain a currently usable credential for + a distinct target identity; arbitrary secrets, identifiers or text produce no edge. + 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: The required aws_privesc_challenge_evidence fact is not collected in current snapshots. Missing or incomplete + evidence evaluates UNKNOWN. +- 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-services/aws-lambda-enum.md#enumeration + source_revision: 0b36331 + 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_verified_authority + 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 distinct identity authenticated by the recovered credential + outcome: permission_grant + conditions: + - id: exact_verified_prerequisites + description: The exact returned Environment.Variables must contain a currently usable credential for a distinct + target identity; arbitrary secrets, identifiers or text produce no edge. + 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: The required aws_privesc_challenge_evidence fact is not collected in current snapshots. Missing or incomplete + evidence evaluates UNKNOWN. +- id: aws-lambda-getfunction-package-secret-identity + provider: aws + service: lambda + title: Recover a distinct identity credential from Lambda deployment package + source: src/pentesting-cloud/aws-security/aws-services/aws-lambda-enum.md#enumeration + source_revision: 0b36331 + summary: Recover a distinct identity credential from Lambda deployment package when the exact target and prerequisites + are verified. + requires: + all_of: + - action: lambda:GetFunction + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-lambda-getfunction-package-secret-identity + scope: same_account + aggregate_as: Verified Recover a distinct identity credential from Lambda deployment package targets in {account} + grants: + - exact distinct identity authenticated by the recovered credential + outcome: permission_grant + conditions: + - id: exact_verified_prerequisites + description: The exact returned downloaded deployment package must contain a currently usable credential for + a distinct target identity; arbitrary secrets, identifiers or text produce no edge. + 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: The required aws_privesc_challenge_evidence fact is not collected in current snapshots. Missing or incomplete + evidence evaluates UNKNOWN. +- id: aws-lambda-durablehistory-secret-identity + provider: aws + service: lambda + title: Recover a distinct identity credential from Lambda durable history + source: src/pentesting-cloud/aws-security/aws-services/aws-lambda-enum.md#lambda-durable-executions + source_revision: 0b36331 + summary: Recover a distinct identity credential from Lambda durable history when the exact target and prerequisites + are verified. + requires: + all_of: + - action: lambda:GetDurableExecutionHistory + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-lambda-durablehistory-secret-identity + scope: same_account + aggregate_as: Verified Recover a distinct identity credential from Lambda durable history targets in {account} + grants: + - exact distinct identity authenticated by the recovered credential + outcome: permission_grant + conditions: + - id: exact_verified_prerequisites + description: The exact returned retained execution data must contain a currently usable credential for a distinct + target identity; arbitrary secrets, identifiers or text produce no edge. + 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: The required aws_privesc_challenge_evidence fact is not collected in current snapshots. Missing or incomplete + evidence evaluates UNKNOWN. diff --git a/src/privilege-escalation-paths/aws/lex.yaml b/src/privilege-escalation-paths/aws/lex.yaml new file mode 100644 index 0000000000..439b117c65 --- /dev/null +++ b/src/privilege-escalation-paths/aws/lex.yaml @@ -0,0 +1,34 @@ +- id: aws-lex-getsession-other-application-session + provider: aws + service: lex + title: Recover another user application session from Lex GetSession + source: src/pentesting-cloud/aws-security/aws-services/aws-lex-v2-enum.md#runtime-sessions-and-stored-utterances + source_revision: 0b36331 + summary: Recover another user application session from Lex GetSession when the exact target and prerequisites + are verified. + requires: + all_of: + - action: lex:GetSession + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-lex-getsession-other-application-session + scope: same_account + aggregate_as: Verified Recover another user application session from Lex GetSession targets in {account} + grants: + - exact victim application session + outcome: permission_grant + conditions: + - id: exact_verified_prerequisites + description: A known live sessionId, exact bot, alias and locale, and verified returned material usable as a + distinct application identity are required. + 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/lexv2/latest/APIReference/API_runtime_GetSession.html + notes: The required aws_privesc_challenge_evidence fact is not collected in current snapshots. Missing or incomplete + evidence evaluates UNKNOWN. diff --git a/src/privilege-escalation-paths/aws/lightsail.yaml b/src/privilege-escalation-paths/aws/lightsail.yaml new file mode 100644 index 0000000000..4a460bdd60 --- /dev/null +++ b/src/privilege-escalation-paths/aws/lightsail.yaml @@ -0,0 +1,33 @@ +- id: aws-lightsail-imds-verified-role + provider: aws + service: lightsail + title: Read an actual AWS role credential from Lightsail IMDS + source: src/pentesting-cloud/aws-security/aws-services/aws-lightsail-enum.md#metadata + source_revision: 0b36331 + summary: Read an actual AWS role credential from Lightsail IMDS when the exact target and prerequisites are verified. + requires: {} + target: + kind: aws_role + selector: + aws_challenge_fact: aws-lightsail-imds-verified-role + scope: same_account + aggregate_as: Verified Read an actual AWS role credential from Lightsail IMDS targets in {account} + grants: + - actual identified IMDS role + outcome: credentials + conditions: + - id: exact_verified_prerequisites + description: Host access, an enabled reachable IMDS endpoint, actually returned valid role credentials and exact + role identity are required; an instance profile must never be assumed. + 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/lightsail/latest/userguide/amazon-lightsail-instance-metadata.html + notes: The required aws_privesc_challenge_evidence fact is not collected in current snapshots. Missing or incomplete + evidence evaluates UNKNOWN. + source_kind: aws_challenge_foothold + source_selector: + source_id_glob: aws_challenge_foothold:*:local diff --git a/src/privilege-escalation-paths/aws/payment-cryptography.yaml b/src/privilege-escalation-paths/aws/payment-cryptography.yaml new file mode 100644 index 0000000000..89ae54063d --- /dev/null +++ b/src/privilege-escalation-paths/aws/payment-cryptography.yaml @@ -0,0 +1,35 @@ +- id: aws-payment-cryptography-crossaccount-key-policy + provider: aws + service: payment-cryptography + title: Grant a controlled external principal payment-key operations + source: src/pentesting-cloud/aws-security/aws-services/aws-payment-cryptography-enum.md#resource-and-authorization-model + source_revision: 0b36331 + summary: A primary-key policy editor can give a controlled external IAM principal compatible operations on the + exact payment key. + requires: + all_of: + - action: payment-cryptography:PutResourcePolicy + resource: '{target.resource_arn}' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-payment-cryptography-crossaccount-key-policy + scope: any + outcome: permission_grant + grants: + - Compatible payment-cryptography key operations on the exact primary key + aggregate_as: Verified external payment-key authority + conditions: + - id: exact_external_principal + description: The evidence must identify a source-controlled external IAM principal with its own effective identity + allow for the chosen key action. + - id: compatible_key_and_policy + description: The primary key must be enabled and compatible with the selected action, and the policy and all + effective guardrails must permit it. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict PutResourcePolicy on primary keys and review cross-account policy principals and operations. + references: + - https://docs.aws.amazon.com/payment-cryptography/latest/userguide/security_iam_resource-based-policies.html diff --git a/src/privilege-escalation-paths/aws/qbusiness.yaml b/src/privilege-escalation-paths/aws/qbusiness.yaml new file mode 100644 index 0000000000..177d5907f9 --- /dev/null +++ b/src/privilege-escalation-paths/aws/qbusiness.yaml @@ -0,0 +1,42 @@ +- id: aws-qbusiness-crossaccount-data-accessor + provider: aws + service: qbusiness + title: Grant a controlled ISV accessor Q Business retrieval authority + source: src/pentesting-cloud/aws-security/aws-services/aws-q-business-enum.md#data-accessors-and-resource-policies + source_revision: 0b36331 + summary: An application administrator can authorize a controlled registered ISV accessor to retrieve documents + allowed to assigned end users. + requires: + all_of: + - action: qbusiness:CreateDataAccessor + resource: '{target.resource_arn}' + - action: qbusiness:AssociatePermission + resource: '{target.resource_arn}' + - action: qbusiness:PutResourcePolicy + resource: '{target.resource_arn}' + - action: sso:PutApplicationAssignmentConfiguration + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-qbusiness-crossaccount-data-accessor + scope: any + outcome: permission_grant + grants: + - qbusiness:SearchRelevantContent on documents permitted by propagated end-user ACLs + aggregate_as: Verified Q Business ISV accessor authority + conditions: + - id: exact_isv_assignment_and_acl + description: Evidence must bind a controlled registered ISV tenant, the application policy, Identity Center + assignment, propagated end user and document ACL. + - id: tti_variant + description: TTI access also requires qbusiness:CreateDataAccessorWithTti; the base entry covers the standard + CreateDataAccessor flow only. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict accessor creation, resource-policy writes and Identity Center assignments; audit ISV tenant + IDs and data-source filters. + references: + - https://docs.aws.amazon.com/amazonq/latest/qbusiness-ug/data-accessors.html diff --git a/src/privilege-escalation-paths/aws/rds.yaml b/src/privilege-escalation-paths/aws/rds.yaml index 452c28604b..1fd1ddb825 100644 --- a/src/privilege-escalation-paths/aws/rds.yaml +++ b/src/privilege-escalation-paths/aws/rds.yaml @@ -334,3 +334,37 @@ references: - https://docs.aws.amazon.com/AmazonRDS/latest/AuroraUserGuide/AuroraMySQL.Integrating.Authorizing.html notes: Required collector evidence is absent from current snapshots; missing evidence remains UNKNOWN/unresolved. +- id: aws-pa-s03-4-rds-proxy-auth-secret + provider: aws + service: rds + title: Read RDS Proxy backend database credentials + 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 + source_revision: 0b36331 + summary: The source obtains the backend database principal stored in a proxy authentication secret. + requires: + all_of: + - action: rds:DescribeDBProxies + resource: '*' + - action: secretsmanager:GetSecretValue + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-pa-s03-4-rds-proxy-auth-secret + scope: same_account + aggregate_as: Verified proxy backend database identities in {account} + conditions: + - id: proxy_secret_match + description: Exact proxy Auth.SecretArn must equal the readable secret ARN; secret contains a usable backend + username/password and is not an end-to-end IAM proxy. + - id: kms_and_route + description: CMK-encrypted secrets also require kms:Decrypt; using SQL needs a network path. + blockers: + - scp_or_boundary_deny + confidence: conditional + severity: high + mitigation: Restrict GetSecretValue on proxy auth secrets and use least-privileged backend users. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/aws-security/aws-post-exploitation/aws-rds-post-exploitation/README.md + notes: Must remain UNKNOWN until the proxy-to-secret-to-database-principal evidence has been collected and bound + to the source. diff --git a/src/privilege-escalation-paths/aws/scheduler.yaml b/src/privilege-escalation-paths/aws/scheduler.yaml index 451b03dac6..a2a4eeb579 100644 --- a/src/privilege-escalation-paths/aws/scheduler.yaml +++ b/src/privilege-escalation-paths/aws/scheduler.yaml @@ -38,3 +38,37 @@ - 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. +- id: aws-scheduler-getschedule-static-credential + provider: aws + service: scheduler + title: Recover a distinct identity credential from Scheduler Target.Input + source: src/pentesting-cloud/aws-security/aws-services/eventbridgescheduler-enum.md#schedulergetschedule--target-input-disclosure + source_revision: 0b36331 + summary: Recover a distinct identity credential from Scheduler Target.Input when the exact target and prerequisites + are verified. + requires: + all_of: + - action: scheduler:GetSchedule + resource: '*' + target: + kind: aws_verified_authority + selector: + aws_challenge_fact: aws-scheduler-getschedule-static-credential + scope: same_account + aggregate_as: Verified Recover a distinct identity credential from Scheduler Target.Input targets in {account} + grants: + - exact identity authenticated by literal Target.Input credential + outcome: permission_grant + conditions: + - id: exact_verified_prerequisites + description: The exact schedule Target.Input must contain a static, currently usable credential for a distinct + identity. Target.RoleArn and referenced secret/KMS ARNs do not qualify. + 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/scheduler/latest/APIReference/API_GetSchedule.html + notes: The required aws_privesc_challenge_evidence fact is not collected in current snapshots. Missing or incomplete + evidence evaluates UNKNOWN. From dc35ea89c1bf334fb9a687745560a131add2d796 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Mon, 12 Oct 2026 21:09:17 +0200 Subject: [PATCH 08/17] Integrate verified GCP privesc v4 catalog fragments Co-Authored-By: Codex --- .../gcp/_excluded.yaml | 245 +++++++++------ .../gcp/accesscontextmanager.yaml | 122 ++++++++ .../gcp/agentregistry.yaml | 64 ++++ .../gcp/appengine.yaml | 285 +++++++++++++----- .../gcp/artifactregistry.yaml | 68 +++++ .../gcp/backupdr.yaml | 77 +++++ .../gcp/beyondcorp.yaml | 30 ++ .../gcp/bigquery.yaml | 140 +++++++++ .../gcp/bigtable.yaml | 65 ++++ .../gcp/challenge-v3.yaml | 12 +- .../gcp/cloudbuild.yaml | 32 ++ .../gcp/composer.yaml | 2 +- .../gcp/compute.yaml | 52 ++++ .../gcp/configcontroller.yaml | 75 +++-- .../gcp/container.yaml | 167 +++++++--- .../gcp/dataform.yaml | 76 +++-- .../gcp/datafusion.yaml | 42 +-- .../gcp/dataproc.yaml | 26 ++ src/privilege-escalation-paths/gcp/iam.yaml | 174 +++++++++++ .../gcp/integrations.yaml | 62 ++++ .../gcp/privatecatalog.yaml | 28 ++ src/privilege-escalation-paths/gcp/run.yaml | 50 +++ .../gcp/secretmanager.yaml | 59 ++++ .../gcp/storage.yaml | 31 ++ src/privilege-escalation-paths/gcp/wif.yaml | 139 +++++---- .../gcp/workflows.yaml | 62 ++++ .../gcp/workspace.yaml | 37 ++- .../gcp/workstations.yaml | 71 +++-- 28 files changed, 1939 insertions(+), 354 deletions(-) create mode 100644 src/privilege-escalation-paths/gcp/accesscontextmanager.yaml create mode 100644 src/privilege-escalation-paths/gcp/beyondcorp.yaml create mode 100644 src/privilege-escalation-paths/gcp/bigtable.yaml create mode 100644 src/privilege-escalation-paths/gcp/integrations.yaml create mode 100644 src/privilege-escalation-paths/gcp/secretmanager.yaml diff --git a/src/privilege-escalation-paths/gcp/_excluded.yaml b/src/privilege-escalation-paths/gcp/_excluded.yaml index e4d16a107f..8e2c1e400e 100644 --- a/src/privilege-escalation-paths/gcp/_excluded.yaml +++ b/src/privilege-escalation-paths/gcp/_excluded.yaml @@ -30,27 +30,24 @@ - 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#computemachineimagessetiampolicy technique: Machine image setIamPolicy - reason: Grants access to image data only; data read. + reason: Self-granted resource access can expose offline filesystem data only after machine image useReadOnly plus destination reconstruction permissions and CMEK access. Credential escalation additionally needs a live reusable credential or private key in the reconstructed bytes and a principal whose access it grants; policy write alone does not prove either. - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computesnapshotssetiampolicy technique: Snapshot setIamPolicy - reason: Grants access to snapshot data only; data read. + reason: Self-granted resource access can expose offline filesystem data only after snapshot useReadOnly plus destination disk/image creation and CMEK access. Credential escalation additionally needs a live reusable credential or private key in the reconstructed bytes and a principal whose access it grants; policy write alone does not prove either. - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computediskssetiampolicy technique: Disk setIamPolicy - reason: Grants access to disk data only; data read. + reason: Self-granted resource access can expose offline filesystem data only after disk snapshot/attachment or export permissions, destination access and CMEK access. Credential escalation additionally needs a live reusable credential or private key in the reconstructed bytes and a principal whose access it grants; policy write alone does not prove either. - 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. + reason: Queue update plus actAs can redirect later legitimate deliveries without caller tasks.create; this is not covered by gcp-cloudtasks-tasks-create-actas. Credential capture requires an existing/future successfully enqueued task (enqueuer also passes actAs), dispatch to an attacker-controlled HTTPS endpoint, and a relying service accepting the token audience. Those later runtime and audience facts are not established by queue IAM configuration. - 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. @@ -62,19 +59,23 @@ 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. + reason: Reading pod logs can expose bearer tokens or bootstrap secrets only if the known Pod actually logged a live reusable credential; the log bytes, credential principal and validity are runtime content facts not determined by container.pods.getLogs. - 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. + reason: Attach reaches a pod identity only when a known running process accepts stdin and permits commands or token reads. Pod configuration does not prove that process behavior; see the proposed attach-usable-process collector. - 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. + reason: A tunnel can reach privileged functionality only if a known Pod-side endpoint is listening and exposes + a usable admin action or live credential; endpoint behavior, authentication and credential scope are runtime + facts absent from the snapshot. - 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. + reason: Proxy access can recover a secret only when a known internal HTTP endpoint returns a live reusable credential + or performs a privileged action; route, response content, authentication and target principal are runtime facts + absent from the snapshot. - 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. + reason: Authorized-network and Binary Authorization changes alone weaken guardrails. Node-pool metadata-mode change is separately modeled by gcp-container-updatenodepool-expose-node-sa and requires a usable pod plus node-SA scopes. - 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. @@ -264,9 +265,6 @@ - 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). @@ -279,9 +277,6 @@ - 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. @@ -362,13 +357,18 @@ 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. + reason: Direct decrypt grants plaintext access. A principal edge needs an obtainable ciphertext under this key + whose plaintext is a still-valid credential for a named principal; neither ciphertext contents nor validity + are in the snapshot. - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#cloudkmscryptokeyssetiampolicy technique: CryptoKey setIamPolicy - reason: Self-grant of key use; data read. + reason: The key policy setter can self-grant Decrypter, but a principal edge additionally needs obtainable ciphertext + containing a valid credential. No ciphertext-to-principal evidence is collected; record key-use privilege separately + only after a data-privilege target exists. - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-kms-privesc.md#cloudkmscryptokeyversionsusetodecryptviadelegation technique: Decrypt via delegation - reason: Data read. + reason: useToDecryptViaDelegation authorizes an integrated service decrypt path, not a direct Decrypt request. + A principal edge needs a usable service route plus credential-bearing plaintext, both unknown to this snapshot. - 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. @@ -392,10 +392,12 @@ 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. + reason: Readable, live gcloud/ADC/key files may yield another principal credential, but local path contents, file + permissions, token validity and the attacker shell are host/runtime facts absent from the cloud snapshot. - 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. + reason: Regex hits may identify credentials, but file contents, readability, credential validity and the principal + behind a hit are host/content facts absent from the cloud snapshot. - 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. @@ -407,7 +409,9 @@ 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. + reason: The page documents a container-to-host sudo identity gain, but an injectable HTTP metadata poll, container + capabilities, host network placement and race success are runtime/host facts; cloud IAM configuration cannot + decide the path. - 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. @@ -465,9 +469,6 @@ - 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#secretmanagersecretssetiampolicy - technique: Secret setIamPolicy - reason: Self-grant of secret read; data read. - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#references technique: References section reason: Reference list; no technique. @@ -532,8 +533,9 @@ 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. + technique: Modify SDK to cause user to authorize Drive and steal broader token + reason: Local host compromise plus a later interactive user consent and token extraction can yield broader Drive + scope, but these host/session/user-action facts are absent from cloud configuration snapshots. - source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/README.md#from-gws-to-gcp technique: Section intro reason: Heading; no technique. @@ -558,12 +560,6 @@ - source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/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. @@ -587,7 +583,7 @@ 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#computerecoverablesnapshotssetiampolicy technique: compute.recoverableSnapshots.setIamPolicy - reason: Grants recovery/use of a deleted snapshot (offline disk data read or permanent deletion); no identity is obtained. + reason: Self-granted resource access can expose offline filesystem data only after recoverable-snapshot recovery/use plus destination reconstruction and CMEK access. Credential escalation additionally needs a live reusable credential or private key in the reconstructed bytes and a principal whose access it grants; policy write alone does not prove either. - 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. @@ -605,7 +601,7 @@ 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" + reason: "Enabling legacy ABAC on a Standard cluster can grant a controlled legacy client certificate unrestricted API access or widen a controlled KSA/node identity beyond its current RBAC. The edge requires proof that the source controls such an identity and that managed ABAC adds useful permissions; cluster update alone does not establish this." - 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. @@ -617,7 +613,10 @@ 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." + reason: Needs same-namespace native Kubernetes create on IAMServiceAccountKey and get on the generated Secret, + plus the namespace Config Connector identity holding iam.serviceAccountKeys.create on a distinct target SA; + key creation must be allowed and Secret generation enabled. Existing transitive edges do not establish this + conjunction. - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-config-delivery-privesc.md#config-delivery technique: Config Delivery intro reason: Introduction; no technique. @@ -676,9 +675,6 @@ - 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: Access policy setIamPolicy reason: "Grants only Access Context Manager admin on the policy (guardrail control); no IAM principal or project role is reached." -- 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 - technique: Redirect a bound MCP target to capture its provider credential - reason: "Captures an external API key / OAuth token of a third-party (SaaS/Workspace) provider sent by a victim agent; not a Google Cloud IAM principal, and depends on victim traffic." - 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: "Data access to a shared dataset/topic; no identity." @@ -840,7 +836,9 @@ 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. + reason: The introduction assumes an already compromised VM local account. Attached SA and OAuth scopes are configuration + facts, but local shell control and metadata reachability are runtime foothold facts; existing compute IAM-to-VM + entries do not establish them. - 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. @@ -964,9 +962,6 @@ - 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-secretmanager-privesc.md#secretmanagersecretsenablemanagedrotation--reset-a-cloud-sql-users-password-through-the-secret-identity technique: enableManagedRotation Cloud SQL password reset reason: "Yields a Cloud SQL database user credential through the secret identity; database access, not a cloud IAM identity." @@ -1015,12 +1010,6 @@ - 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. @@ -1033,12 +1022,6 @@ - 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-vmwareengine-gcve-privesc.md#vmwareengineprivatecloudsshowvcentercredentials--shownsxcredentials--cross-into-the-vmware-management-plane - technique: showVcenterCredentials / showNsxCredentials - reason: "Yields vCenter CloudOwner / NSX admin passwords: a VMware management-plane identity outside Google Cloud IAM, not a modelled GCP principal." -- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-vmwareengine-gcve-privesc.md#vmwareengineprivatecloudssetiampolicy--grant-a-credential-reading-role-on-one-private-cloud - technique: vmwareengine.privateClouds.setIamPolicy then show credentials - reason: Resource-scoped self-grant on one private cloud leading to the vCenter/NSX credentials above; no GCP principal gained. - 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. @@ -1048,21 +1031,12 @@ - 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. @@ -1874,9 +1848,9 @@ 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. + technique: Read known bucket objects through Design Center Viewer role + reason: Credential exposure is possible only when the returned content contains a verified usable credential mapped + to a target; requires gcp_designcenter_bucket_credentials and remains UNKNOWN without that fact. - 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. @@ -1904,13 +1878,13 @@ 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. + technique: Recover credentials embedded in Artifact Registry package or image + reason: Credential exposure is possible only when the returned content contains a verified usable credential mapped + to a target; requires gcp_artifactregistry_artifact_credentials and remains UNKNOWN without that fact. - 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. + technique: Export Artifact Registry artifact to storage + reason: Credential exposure is possible only when the returned content contains a verified usable credential mapped + to a target; requires gcp_artifactregistry_exported_credentials and remains UNKNOWN without that fact. - 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 @@ -1924,13 +1898,13 @@ 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. + technique: Recover API keys or tokens in other users’ SQL and query parameters + reason: Credential exposure is possible only when the returned content contains a verified usable credential mapped + to a target; requires gcp_bigquery_job_sql_credentials and remains UNKNOWN without that fact. - 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. + technique: Read BigQuery table rows + reason: Credential exposure is possible only when the returned content contains a verified usable credential mapped + to a target; requires gcp_bigquery_table_row_credentials and remains UNKNOWN without that fact. - 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 @@ -1988,9 +1962,9 @@ 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. + technique: Recover credentials printed in App Engine logs + reason: Credential exposure is possible only when the returned content contains a verified usable credential mapped + to a target; requires gcp_appengine_log_credentials and remains UNKNOWN without that fact. - 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 @@ -2321,3 +2295,106 @@ 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-apigee-privesc.md#apigeeproxiescreate--apigeedeploymentscreate--apigeeproxyrevisionsdeploy--iamserviceaccountsactas--deploy-a-malicious-api-proxy-revision + source_revision: 0b36331 + technique: Deploy proxy to capture backend or client credentials without an attached SA + reason: 'The no-SA proxy branch can intercept credentials only if future client/backend traffic contains usable + secrets; configuration alone cannot name a gained credential. Required runtime fact: a specific future request + carries a valid credential to a reachable attacker-controlled receiver; proxy/flow configuration does not prove + it.' +- 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: 0b36331 + technique: Attach malicious shared flow to capture traffic credentials without SA + reason: 'The no-SA shared-flow branch depends on future traffic carrying usable credentials; deployment and hook + attachment alone do not confer an identity. Required runtime fact: a specific future request carries a valid + credential to a reachable attacker-controlled receiver; proxy/flow configuration does not prove it.' +- 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: Dataproc metadata or retained driver-output credential recovery + reason: Needs actual cluster metadata or retained output contents containing a live reusable credential, its principal + and replay scope; dataproc.clusters.get plus storage.objects.get/list only identify readable data. Staging object + poisoning is separately modeled by gcp-dataproc-staging-object-replace and gcp-dataproc-staging-object-plant. + source_revision: 0b36331 +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-composer-privesc.md#composerenvironmentsexecuteairflowcommand--retrieve-airflow-secrets-or-run-available-dag-code + technique: Composer Airflow connection or variable credential replay + reason: Requires actual Airflow connection/variable or Secret Manager backend contents, a live reusable secret, + and the principal and scope it authenticates. composer.environments.executeAirflowCommand alone proves only + CLI reachability; the environment-SA code path remains gcp-composer-environments-executeairflowcommand. + source_revision: 0b36331 +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#gcp--google-workspace-crossings + technique: GhostToken project deletion and restoration hides OAuth app + reason: GhostToken depended on a Google OAuth validation behavior fixed April 2023 and a pre-existing refresh + token; current project deletion/restoration configuration does not establish new access. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#managed-service-tenant--host-escapes + technique: Cloud SQL SQL Server tempdb trigger to sysadmin and host + reason: Historical Cloud SQL SQL Server tempdb flaw requires a vulnerable engine build and SQL trigger execution; + GCP IAM and instance configuration alone do not establish it. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#patched-2026-managed-service-vulnerabilities + technique: SecOps SOAR internal-header spoofing + reason: 'Historical managed-service flaw: the cited page states Google fixed the affected service; current IAM/configuration + cannot imply the old authorization or isolation bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#patched-2026-managed-service-vulnerabilities + technique: Apigee sandbox metadata-token crossing + reason: 'Historical managed-service flaw: page says Google fixed the affected service; a current snapshot needs + an affected customer-managed version and exploit-specific configuration before this can be an active path.' +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#patched-2026-managed-service-vulnerabilities + technique: Dangling logging sink destination and attacker re-registration + reason: The Google sink re-registration flaw is fixed. A remaining dangling bucket may leak logs, but an identity + edge needs a live sink to an attacker-owned name and credential-bearing log content, neither established by + sink configuration alone. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#authorization-bypass-and-shadow-resources + technique: Dangling/staging GCS bucket squatting leading to privileged consumer code + reason: Bucket-name squatting alone yields data access. Privilege gain needs a vulnerable consumer version, actual + execution of attacker-controlled pickle/model content or a credential in victim writes, and ownership/reachability + of the exact name. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/organization-and-central-project-pivots.md#cross-project-visibility-and-exfiltration + technique: Redirect org/folder aggregated logging sink to attacker destination + reason: A logging sink redirects log data; privilege gain requires a credential actually present in emitted logs, + attacker access to the destination, and usable credential scope/validity. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/resource-sharing-and-confused-deputy-attacks.md#cross-project-resource-sharing-service-matrix + technique: Read cloud secret containing credentials across projects + reason: Secret Manager read alone is data access. An identity edge needs the version payload to contain a valid + credential for a different principal and its exact scope; IAM/resource metadata cannot prove that content. +- source: src/pentesting-cloud/gcp-security/gcp-basic-information/README.md#keys--tokens + technique: Steal service-account OAuth token from HTTP request or metadata + reason: HTTP token interception or metadata theft requires a runtime observation of a usable token and its intended + principal; keys/tokens overview supplies no configuration-derived path. +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#patched-2026-managed-service-vulnerabilities + technique: Application Integration internal-task RPC proxy + reason: 'Historical managed-service flaw: the cited page states Google fixed the affected service; current IAM/configuration + cannot imply the old authorization or isolation bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#patched-2026-managed-service-vulnerabilities + technique: Application Integration JavaScript deserialization RCE + reason: 'Historical managed-service flaw: the cited page states Google fixed the affected service; current IAM/configuration + cannot imply the old authorization or isolation bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#patched-2026-managed-service-vulnerabilities + technique: Application Integration Email Task file-read deputy + reason: 'Historical managed-service flaw: the cited page states Google fixed the affected service; current IAM/configuration + cannot imply the old authorization or isolation bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#patched-2026-managed-service-vulnerabilities + technique: Integration Connectors unauthorized SA attachment + reason: 'Historical managed-service flaw: the cited page states Google fixed the affected service; current IAM/configuration + cannot imply the old authorization or isolation bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#patched-2026-managed-service-vulnerabilities + technique: GKE Multi-Cloud missing target-project authorization + reason: 'Historical managed-service flaw: the cited page states Google fixed the affected service; current IAM/configuration + cannot imply the old authorization or isolation bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#patched-2026-managed-service-vulnerabilities + technique: BigQuery Data Transfer JDBC tenant-project escape + reason: 'Historical managed-service flaw: the cited page states Google fixed the affected service; current IAM/configuration + cannot imply the old authorization or isolation bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#patched-2026-managed-service-vulnerabilities + technique: BigQuery Dataform Colab repository takeover + reason: 'Historical managed-service flaw: the cited page states Google fixed the affected service; current IAM/configuration + cannot imply the old authorization or isolation bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#patched-2026-managed-service-vulnerabilities + technique: Developer Connect secret-check deputy + reason: 'Historical managed-service flaw: the cited page states Google fixed the affected service; current IAM/configuration + cannot imply the old authorization or isolation bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#patched-2026-managed-service-vulnerabilities + technique: Cloud Build secret-check deputy + reason: 'Historical managed-service flaw: the cited page states Google fixed the affected service; current IAM/configuration + cannot imply the old authorization or isolation bypass.' +- source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#patched-2026-managed-service-vulnerabilities + technique: App Engine request-log cross-tenant leak + reason: 'Historical managed-service flaw: the cited page states Google fixed the affected service; current IAM/configuration + cannot imply the old authorization or isolation bypass.' diff --git a/src/privilege-escalation-paths/gcp/accesscontextmanager.yaml b/src/privilege-escalation-paths/gcp/accesscontextmanager.yaml new file mode 100644 index 0000000000..7737f20147 --- /dev/null +++ b/src/privilege-escalation-paths/gcp/accesscontextmanager.yaml @@ -0,0 +1,122 @@ + +- id: gcp-audit-s01-02-loosen-access-level-for-atta + provider: gcp + service: access-context-manager + title: Loosen access level for attacker IP, device, region or principal + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanageraccesslevelsupdate--loosen-context-aware-access + summary: The source can gain loosen access level for attacker IP, device, region or principal. Changing an access + level can activate an IAM-authorized path only for a concrete caller, context and protected consumer; the policy + write alone is insufficient. + requires: + all_of: + - action: accesscontextmanager.accessLevels.update + resource: '*' + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-audit-s01-02-loosen-access-level-for-atta + scope: any + aggregate_as: IAP or IAM-Condition protected resource + conditions: + - id: exact_target_evidence + description: Existing exclusion calls this guardrail tamper, but page explicitly says the caller gains passage + through a context gate that formerly excluded it. Missing target evidence evaluates UNKNOWN. + confidence: conditional + severity: high + mitigation: Restrict the listed permissions and review target trust/consumer configuration. + source_revision: 0b36331 + references: + - https://cloud.hacktricks.wiki/en/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc/#accesscontextmanageraccesslevelsupdate--loosen-context-aware-access +- id: gcp-audit-s01-03-create-a-bridge-perimeter-jo + provider: gcp + service: access-context-manager + title: Create a bridge perimeter joining attacker and victim projects + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanagerserviceperimetersupdate--defeat-vpc-sc-data-exfil-protection + summary: The source can gain create a bridge perimeter joining attacker and victim projects. Create uses servicePerimeters.create, + absent from the update entry, but a bridge matters only for a concrete previously blocked API path and two eligible + projects. + requires: + all_of: + - action: accesscontextmanager.servicePerimeters.create + resource: '*' + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-audit-s01-03-create-a-bridge-perimeter-jo + scope: any + aggregate_as: cross-perimeter data channel + conditions: + - id: exact_target_evidence + description: Distinct create permission; update-only entry cannot flag this principal. Needs a victim and attacker + project in bridged perimeters. Missing target evidence evaluates UNKNOWN. + - id: existing_iam + description: The concrete protected request must already be IAM-authorized and blocked only by the gate being + changed. + confidence: conditional + severity: high + mitigation: Restrict the listed permissions and review target trust/consumer configuration. + source_revision: 0b36331 + references: + - https://cloud.hacktricks.wiki/en/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc/#accesscontextmanagerserviceperimetersupdate--defeat-vpc-sc-data-exfil-protection +- id: gcp-audit-s01-04-delete-a-perimeter-or-access + provider: gcp + service: access-context-manager + title: Delete a perimeter or access level to remove protection + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#accesscontextmanagerserviceperimetersupdate--defeat-vpc-sc-data-exfil-protection + summary: The source can gain delete a perimeter or access level to remove protection. Delete permissions are distinct + from update; a path exists only if the deleted gate blocked a specific IAM-authorized request. + requires: + any_of: + - - action: accesscontextmanager.servicePerimeters.delete + resource: '*' + - - action: accesscontextmanager.accessLevels.delete + resource: '*' + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-audit-s01-04-delete-a-perimeter-or-access + scope: any + aggregate_as: VPC-SC or context-aware gate + conditions: + - id: exact_target_evidence + description: Alternative destructive permissions are documented; update-only entry cannot flag them. Missing + target evidence evaluates UNKNOWN. + - id: existing_iam + description: The concrete protected request must already be IAM-authorized and blocked only by the gate being + changed. + confidence: conditional + severity: high + mitigation: Restrict the listed permissions and review target trust/consumer configuration. + source_revision: 0b36331 + references: + - https://cloud.hacktricks.wiki/en/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc/#accesscontextmanagerserviceperimetersupdate--defeat-vpc-sc-data-exfil-protection +- id: gcp-audit-s01-06-delete-or-weaken-a-group-con + provider: gcp + service: access-context-manager + title: Delete or weaken a group context-aware access binding + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc.md#gcpuseraccessbindings-cloud-bindings--context-removal-or-extended-workforce-sessions + summary: The source can gain delete or weaken a group context-aware access binding. A binding deletion or weakening + can unlock access for group members, but a snapshot must join group membership, gate consumer and underlying + permission. + requires: + any_of: + - - action: accesscontextmanager.gcpUserAccessBindings.delete + resource: '*' + - - action: accesscontextmanager.gcpUserAccessBindings.update + resource: '*' + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-audit-s01-06-delete-or-weaken-a-group-con + scope: any + aggregate_as: group formerly blocked by context gate + conditions: + - id: exact_target_evidence + description: Exclusion says no IAM identity, but the page documents new access for group members to Console/API + behind a gate. Missing target evidence evaluates UNKNOWN. + confidence: conditional + severity: high + mitigation: Restrict the listed permissions and review target trust/consumer configuration. + source_revision: 0b36331 + references: + - https://cloud.hacktricks.wiki/en/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-access-context-manager-privesc/#gcpuseraccessbindings-cloud-bindings--context-removal-or-extended-workforce-sessions diff --git a/src/privilege-escalation-paths/gcp/agentregistry.yaml b/src/privilege-escalation-paths/gcp/agentregistry.yaml index c9e788251e..2f28aca470 100644 --- a/src/privilege-escalation-paths/gcp/agentregistry.yaml +++ b/src/privilege-escalation-paths/gcp/agentregistry.yaml @@ -37,3 +37,67 @@ 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. serviceusage.services.use on the quota project is also needed. +- id: gcp-audit-s01-09-redirect-bound-mcp-service-a + provider: gcp + service: agent-registry + title: Redirect bound MCP service and capture victim Agent Identity API key or OAuth token + 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 + summary: The source can gain redirect bound MCP service and capture victim Agent Identity API key or OAuth token. + The redirected Service retains its Binding, but credential capture depends on a later victim invocation, credential + injection and receiver acceptance. + requires: + all_of: + - action: agentregistry.services.update + resource: '*' + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-audit-s01-09-redirect-bound-mcp-service-a + scope: any + aggregate_as: external API/Workspace credential + conditions: + - id: exact_target_evidence + description: Exclusion rejects non-GCP IAM credentials, although the page explicitly documents credential theft + and access in SaaS or Workspace tenant. Requires existing binding and victim invocation. Missing target evidence + evaluates UNKNOWN. + - id: runtime_delivery + description: A later authorized victim must invoke through the unchanged Binding, and the attacker receiver + must accept a useful injected credential. + confidence: conditional + severity: high + mitigation: Restrict the listed permissions and review target trust/consumer configuration. + source_revision: 0b36331 + references: + - https://cloud.hacktricks.wiki/en/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-registry-privesc/#agentregistryservicesupdate--redirect-a-bound-target-and-capture-its-agent-identity-credential +- id: gcp-audit-s01-10-replace-default-executable-s + provider: gcp + service: agent-registry + title: Replace default executable Skill revision + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-registry-privesc.md#agentregistryskillrevisionscreate--agentregistryskillsupdate--replace-an-executable-skills-default-revision + summary: The source can gain replace default executable Skill revision. The existing entry covers mounted GCP + service accounts; Agent Identity and mounted tool authority need a typed runtime identity and exact consumer + inventory. + requires: + all_of: + - action: agentregistry.skillRevisions.create + resource: '*' + - action: agentregistry.skills.update + resource: '*' + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-audit-s01-10-replace-default-executable-s + scope: any + aggregate_as: agent runtime identity + conditions: + - id: exact_target_evidence + description: Entry covers an attached GCP SA but page also allows Agent Identity principal and mounted tools. + Its sole target kind is gcp_service_account, missing those identities. Missing target evidence evaluates UNKNOWN. + - id: runtime_mount + description: The target agent must mount the floating Skill revision and execute it; pinned revisions are unaffected. + confidence: conditional + severity: high + mitigation: Restrict the listed permissions and review target trust/consumer configuration. + source_revision: 0b36331 + references: + - https://cloud.hacktricks.wiki/en/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-agent-registry-privesc/#agentregistryskillrevisionscreate--agentregistryskillsupdate--replace-an-executable-skills-default-revision diff --git a/src/privilege-escalation-paths/gcp/appengine.yaml b/src/privilege-escalation-paths/gcp/appengine.yaml index 3ff8a3867b..f8c20672d1 100644 --- a/src/privilege-escalation-paths/gcp/appengine.yaml +++ b/src/privilege-escalation-paths/gcp/appengine.yaml @@ -9,122 +9,269 @@ 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. + 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: "*" - - action: storage.objects.create - resource: "*" - - action: cloudbuild.builds.create - resource: "*" + - 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 scope: same_project - aggregate_as: "Service accounts usable as App Engine runtime SA in {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 effective deploy permission set varies (Google recommends App Engine Deployer, Service Account User, Cloud Build Editor and Storage Object Admin); read and operation-polling permissions used by the CLI may be avoidable. - - 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. + - id: app_exists + description: An App Engine application must already exist in the project. + - id: deploy_prereqs + description: The effective deploy permission set varies (Google recommends App Engine Deployer, Service Account + User, Cloud Build Editor and Storage Object Admin); read and operation-polling permissions used by the CLI + may be avoidable. + - 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. + - id: source_staging + description: gcloud source deployment additionally needs Storage object staging and Cloud Build creation; direct + Admin API with an already deployable version artifact does not universally require those caller permissions. blockers: - - gcp_deny_policy - - vpc_sc_perimeter + - 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. + 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: A no-promote version is reachable without moving production traffic. Also covers replacing a named version and environment-variable startup injection in app.yaml. The SA must be in the App Engine application's project. - + - https://cloud.google.com/appengine/docs/standard/configure-service-accounts + notes: A no-promote version is reachable without moving production traffic. Also covers replacing a named version + and environment-variable startup injection in app.yaml. The SA must be in the App Engine application's project. - 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. + 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}" + - - 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 scope: same_project - aggregate_as: "SAs of App Engine flexible versions the source can debug" + 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. + - 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. + - id: os_login_debug_state + description: For either OS Login branch the flexible instance must already have debug mode enabled or the source + must also hold appengine.instances.enableDebug on that instance; a usable SSH path is still required. blockers: - - gcp_deny_policy + - 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. OS Login resource "*" is project-level; the VM is the version's flexible instance. - + - 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. OS Login resource "*" is project-level; + the VM is the version's flexible instance. - 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. + 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: "*" - - action: storage.objects.create - resource: "*" - - action: cloudbuild.builds.create - resource: "*" + - action: appengine.versions.create + resource: '*' target: kind: gcp_service_account selector: - target_id_glob: ["*@appspot.gserviceaccount.com"] + target_id_glob: + - '*@appspot.gserviceaccount.com' gcp_sa_in_scope_of_permission: true scope: same_project - aggregate_as: "App Engine default SA deployable without actAs in {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 app-level default SA (no per-version SA and no user-managed app default). - - id: version_sa_artifact_registry - description: The default SA itself needs artifactregistry.repositories.uploadArtifacts (and downloadArtifacts for flexible) or the deployment never reaches execution. + - 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 app-level default + SA (no per-version SA and no user-managed app default). + - id: version_sa_artifact_registry + description: The default SA itself needs artifactregistry.repositories.uploadArtifacts (and downloadArtifacts + for flexible) or the deployment never reaches execution. + - id: source_staging + description: gcloud source deployment additionally needs Storage object staging and Cloud Build creation; direct + Admin API with an already deployable version artifact does not universally require those caller permissions. blockers: - - gcp_deny_policy - - vpc_sc_perimeter - - id: org_policy_constraint - constraint: appengine.enforceServiceAccountActAsCheck + - gcp_deny_policy + - vpc_sc_perimeter + - id: org_policy_constraint + constraint: appengine.enforceServiceAccountActAsCheck confidence: conditional severity: critical - mitigation: Enforce constraints/appengine.enforceServiceAccountActAsCheck and remove roles/editor from the App Engine default SA. + 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; + it does not cover per-version or user-managed default SAs. +- id: gcp-appengine-version-env-credential + provider: gcp + service: appengine + title: Read literal secrets from App Engine version environment + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md#read-secrets-and-deployment-locations-from-version-configuration + source_revision: 0b36331 + summary: Credential represented by an env variable; emit only for the exact verified source, resource and target. + requires: + all_of: + - action: appengine.versions.get + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-appengine-version-env-credential + scope: any + outcome: scope_control + aggregate_as: Verified targets for Read literal secrets from App Engine version environment + conditions: + - id: exact_verified_prerequisites + description: Exact source, resource, target, scope and gain must be verified; missing fact is UNKNOWN. Known + version and view=FULL; alternative is appengine.versions.list on known service. Edge only if a valid reusable + credential is present and its authority can be identified. + confidence: conditional + severity: high + mitigation: Limit appengine.versions.get to trusted operators and monitor the target-specific use. + references: + - src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md#read-secrets-and-deployment-locations-from-version-configuration +- id: gcp-appengine-source-credential + provider: gcp + service: appengine + title: Recover hard-coded credentials from retained App Engine deployment source + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md#read-source-code + source_revision: 0b36331 + summary: Identity authenticated by a valid embedded key or password; emit only for the exact verified source, + resource and target. + requires: + all_of: + - action: appengine.versions.get + resource: '*' + - action: storage.objects.get + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-appengine-source-credential + scope: any + outcome: scope_control + aggregate_as: Verified targets for Recover hard-coded credentials from retained App Engine deployment source + conditions: + - id: exact_verified_prerequisites + description: Exact source, resource, target, scope and gain must be verified; missing fact is UNKNOWN. Known + extant deployment sourceUrl; alternatively versions.list; Console Code Viewer is a separate non-scriptable + path needing roles/appengine.codeViewer. Edge only after credential content and target verified. + confidence: conditional + severity: high + mitigation: Limit appengine.versions.get to trusted operators and monitor the target-specific use. + references: + - src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md#read-source-code +- id: gcp-appengine-memcache-session + provider: gcp + service: appengine + title: Recover cached session token from Memcache + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md#read-or-poison-app-engine-memcache-data + source_revision: 0b36331 + summary: Application session represented by cached token; emit only for the exact verified source, resource and + target. + requires: + all_of: + - action: appengine.memcache.get + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-appengine-memcache-session + scope: any + outcome: scope_control + aggregate_as: Verified targets for Recover cached session token from Memcache + conditions: + - id: exact_verified_prerequisites + description: Exact source, resource, target, scope and gain must be verified; missing fact is UNKNOWN. Known + cache key and type; list/getKey may be needed to discover it; token must be present and usable. + confidence: conditional + severity: high + mitigation: Limit appengine.memcache.get to trusted operators and monitor the target-specific use. + references: + - src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md#read-or-poison-app-engine-memcache-data +- id: gcp-appengine-log-credential + provider: gcp + service: appengine + title: Recover credentials printed in App Engine logs + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md#read-application-logs-with-logginglogentrieslist + source_revision: 0b36331 + summary: Identity authenticated by a valid token or password printed in logs; emit only for the exact verified + source, resource and target. + requires: + all_of: + - action: logging.logEntries.list + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-appengine-log-credential + scope: any + outcome: scope_control + aggregate_as: Verified targets for Recover credentials printed in App Engine logs + conditions: + - id: exact_verified_prerequisites + description: Exact source, resource, target, scope and gain must be verified; missing fact is UNKNOWN. Log entry + actually contains credential; optional logging.privateLogEntries.list for private entries or logging.views.access + for a specific view. No edge from permission alone. + confidence: conditional + severity: high + mitigation: Limit logging.logEntries.list to trusted operators and monitor the target-specific use. 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; it does not cover per-version or user-managed default SAs. + - src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-app-engine-post-exploitation.md#read-application-logs-with-logginglogentrieslist diff --git a/src/privilege-escalation-paths/gcp/artifactregistry.yaml b/src/privilege-escalation-paths/gcp/artifactregistry.yaml index c5b8c325c7..048274ea3c 100644 --- a/src/privilege-escalation-paths/gcp/artifactregistry.yaml +++ b/src/privilege-escalation-paths/gcp/artifactregistry.yaml @@ -165,3 +165,71 @@ severity: medium mitigation: Restrict artifactregistry.repositories.update (roles/artifactregistry.admin, roles/editor) and pin package versions with hashes. notes: HackTricks frames this as a persistence method; the escalation depends on a consumer installing after the change. The variant of a remote repository pointed at an attacker-controlled upstream URL (persistence page) additionally needs artifactregistry.repositories.create and only matters once a consumed virtual repository lists it as an upstream, which is this same update permission. +- id: gcp-artifactregistry-download-credential + provider: gcp + service: artifactregistry + title: Recover credentials embedded in Artifact Registry package or image + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryrepositoriesdownloadartifacts--inspect-stored-artifacts-for-sensitive-data + source_revision: 0b36331 + summary: Identity authenticated by a valid embedded secret; emit only for the exact verified source, resource + and target. + requires: + all_of: + - action: artifactregistry.repositories.downloadArtifacts + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-artifactregistry-download-credential + scope: any + outcome: scope_control + aggregate_as: Verified targets for Recover credentials embedded in Artifact Registry package or image + conditions: + - id: exact_verified_prerequisites + description: Exact source, resource, target, scope and gain must be verified; missing fact is UNKNOWN. Known + artifact coordinate and repository access; inspect bytes and verify secret-to-principal binding. No automatic + consumer SA edge. + confidence: conditional + severity: high + mitigation: Limit artifactregistry.repositories.downloadArtifacts to trusted operators and monitor the target-specific + use. + references: + - src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryrepositoriesdownloadartifacts--inspect-stored-artifacts-for-sensitive-data +- id: gcp-artifactregistry-export-credential + provider: gcp + service: artifactregistry + title: Export Artifact Registry artifact to storage + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryrepositoriesexportartifacts--copy-an-artifact-to-cloud-storage + source_revision: 0b36331 + summary: Usable credential embedded in exported artifact; emit only for the exact verified source, resource and + target. + requires: + all_of: + - action: artifactregistry.repositories.exportArtifacts + resource: '*' + - action: storage.objects.get + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-artifactregistry-export-credential + scope: any + outcome: scope_control + aggregate_as: Verified targets for Export Artifact Registry artifact to storage + conditions: + - id: exact_verified_prerequisites + description: Exact source, resource, target, scope and gain must be verified; missing fact is UNKNOWN. Known + artifact; accepted destination writable by backend and readable by attacker; artifact contains valid credential + mapped to principal. + confidence: conditional + severity: high + mitigation: Limit artifactregistry.repositories.exportArtifacts to trusted operators and monitor the target-specific + use. + references: + - src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryrepositoriesexportartifacts--copy-an-artifact-to-cloud-storage diff --git a/src/privilege-escalation-paths/gcp/backupdr.yaml b/src/privilege-escalation-paths/gcp/backupdr.yaml index 11a490e683..1c537e38d4 100644 --- a/src/privilege-escalation-paths/gcp/backupdr.yaml +++ b/src/privilege-escalation-paths/gcp/backupdr.yaml @@ -52,3 +52,80 @@ The page frames this as data export; the identity gain comes from the documented service-account and metadata inputs of RestoreBackup (alternative VM-creation path to gcp-compute-instances-create-actas that needs no compute.instances.create on the caller). +- id: gcp-backupdr-autoprotection-disk-credential + provider: gcp + service: backupdr + title: Capture future VM disk credentials with Backup and DR auto-protection + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-backup-and-dr-post-exploitation.md#continuously-capture-labelled-compute-resources-with-auto-protection + source_revision: 0b36331 + summary: Credential stored in a matching future disk backup; emit only for the exact verified source, resource + and target. + requires: + all_of: + - action: backupdr.autoProtectionPolicies.create + resource: '*' + - action: backupdr.backupPlans.useForComputeDisk + resource: '*' + - action: backupdr.autoProtectionBindings.create + resource: '*' + - action: backupdr.appliedAutoProtectionPolicies.authorize + resource: '*' + - action: backupdr.bvbackups.restore + resource: '*' + - action: backupdr.compute.restoreFromBackupVault + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-backupdr-autoprotection-disk-credential + scope: any + outcome: scope_control + aggregate_as: Verified targets for Capture future VM disk credentials with Backup and DR auto-protection + conditions: + - id: exact_verified_prerequisites + description: Exact source, resource, target, scope and gain must be verified; missing fact is UNKNOWN. Compatible + vault/plan and label; reciprocal service-agent roles; backup completes; restore target allowed and readable; + credential exists in disk and remains usable. VM variant uses useForComputeInstance. + confidence: conditional + severity: high + mitigation: Limit backupdr.autoProtectionPolicies.create to trusted operators and monitor the target-specific + use. + references: + - src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-backup-and-dr-post-exploitation.md#continuously-capture-labelled-compute-resources-with-auto-protection +- id: gcp-backupdr-restored-disk-credential + provider: gcp + service: backupdr + title: Recover durable credentials stored on backed-up VM disks + 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 + source_revision: 0b36331 + summary: Identity authenticated by recovered disk credential; emit only for the exact verified source, resource + and target. + requires: + all_of: + - action: backupdr.bvbackups.restore + resource: '*' + - action: backupdr.compute.restoreFromBackupVault + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-backupdr-restored-disk-credential + scope: any + outcome: scope_control + aggregate_as: Verified targets for Recover durable credentials stored on backed-up VM disks + conditions: + - id: exact_verified_prerequisites + description: Exact source, resource, target, scope and gain must be verified; missing fact is UNKNOWN. Completed + backup; vault restriction permits controlled target; target service agent role; attacker can inspect restored + disk; credential remains usable. + confidence: conditional + severity: high + mitigation: Limit backupdr.bvbackups.restore to trusted operators and monitor the target-specific use. + references: + - 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 diff --git a/src/privilege-escalation-paths/gcp/beyondcorp.yaml b/src/privilege-escalation-paths/gcp/beyondcorp.yaml new file mode 100644 index 0000000000..600e064743 --- /dev/null +++ b/src/privilege-escalation-paths/gcp/beyondcorp.yaml @@ -0,0 +1,30 @@ + +- id: gcp-audit-s01-21-repoint-accessible-gateway-a + provider: gcp + service: beyondcorp + title: Repoint accessible gateway app to new internal HTTP(S) host + 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 + summary: The source can gain repoint accessible gateway app to new internal HTTP(S) host. A new private host is + reachable only when the caller already has app use, the existing upstream can route to it, and upstream authentication + permits access. + requires: + all_of: + - action: beyondcorp.sgApplications.update + resource: '*' + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-audit-s01-21-repoint-accessible-gateway-a + scope: any + aggregate_as: private web target + conditions: + - id: exact_target_evidence + description: Exclusion calls this a network pivot; page documents new authority to reach a protected target + with existing upstream. Requires existing app user/discovery, reachable web host and upstream authentication. + Missing target evidence evaluates UNKNOWN. + confidence: conditional + severity: high + mitigation: Restrict the listed permissions and review target trust/consumer configuration. + source_revision: 0b36331 + references: + - https://cloud.hacktricks.wiki/en/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-beyondcorp-privesc/#repoint-an-application-the-caller-can-already-use-to-another-web-target-behind-its-existing-upstream diff --git a/src/privilege-escalation-paths/gcp/bigquery.yaml b/src/privilege-escalation-paths/gcp/bigquery.yaml index 671e6af533..6715073202 100644 --- a/src/privilege-escalation-paths/gcp/bigquery.yaml +++ b/src/privilege-escalation-paths/gcp/bigquery.yaml @@ -133,3 +133,143 @@ references: - https://cloud.google.com/bigquery/docs/continuous-queries-introduction notes: Sibling of gcp-bigquery-transfers-scheduled-query-actas; power is limited to the SA's BigQuery data access plus the configured sink. +- id: gcp-audit-s01-26-delete-policies-and-deactiva + provider: gcp + service: bigquery + title: Delete policies and deactivate taxonomy enforcement + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigquerydatapoliciesdelete--datacatalogtaxonomiesupdate--disable-column-level-enforcement + summary: The source can gain delete policies and deactivate taxonomy enforcement. Deleting policies and deactivating + a taxonomy can expose columns only when every associated policy is deleted and an existing reader has base query + rights. + requires: + all_of: + - action: bigquery.dataPolicies.delete + resource: '*' + - action: datacatalog.taxonomies.update + resource: '*' + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-audit-s01-26-delete-policies-and-deactiva + scope: any + aggregate_as: protected-column read entitlement + conditions: + - id: exact_target_evidence + description: Exclusion misses newly unmasked access for existing table readers; both permissions and deletion + of every associated data policy are required. Missing target evidence evaluates UNKNOWN. + confidence: conditional + severity: high + mitigation: Restrict the listed permissions and review target trust/consumer configuration. + source_revision: 0b36331 + references: + - https://cloud.hacktricks.wiki/en/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc/#bigquerydatapoliciesdelete--datacatalogtaxonomiesupdate--disable-column-level-enforcement +- id: gcp-audit-s01-29-widen-or-delete-row-access-p + provider: gcp + service: bigquery + title: Widen or delete row-access policy + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc.md#bigqueryrowaccesspolicies--widen-or-remove-row-level-security + summary: The source can gain widen or delete row-access policy. Row policy mutation widens effective rows only + for an existing base reader and a concrete policy set. + requires: + any_of: + - - action: bigquery.rowAccessPolicies.create + resource: '*' + - action: bigquery.rowAccessPolicies.setIamPolicy + resource: '*' + - action: bigquery.jobs.create + resource: '*' + - - action: bigquery.rowAccessPolicies.update + resource: '*' + - action: bigquery.rowAccessPolicies.setIamPolicy + resource: '*' + - action: bigquery.jobs.create + resource: '*' + - - action: bigquery.rowAccessPolicies.delete + resource: '*' + - action: bigquery.rowAccessPolicies.setIamPolicy + resource: '*' + - action: bigquery.jobs.create + resource: '*' + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-audit-s01-29-widen-or-delete-row-access-p + scope: any + aggregate_as: full-row read entitlement + conditions: + - id: exact_target_evidence + description: Exclusion calls it data tamper, but caller with base table read gains rows formerly filtered. Create/update/delete + are alternative paths with additional setIamPolicy and jobs.create. Missing target evidence evaluates UNKNOWN. + confidence: conditional + severity: high + mitigation: Restrict the listed permissions and review target trust/consumer configuration. + source_revision: 0b36331 + references: + - https://cloud.hacktricks.wiki/en/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigquery-privesc/#bigqueryrowaccesspolicies--widen-or-remove-row-level-security +- id: gcp-bigquery-job-sql-credential + provider: gcp + service: bigquery + title: Recover API keys or tokens in other users’ SQL and query parameters + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigqueryjobslistall--jobslist-jobsget--read-every-principals-sql-silently + source_revision: 0b36331 + summary: Identity authenticated by valid secret in job metadata; emit only for the exact verified source, resource + and target. + requires: + all_of: + - action: bigquery.jobs.listAll + resource: '*' + - action: bigquery.jobs.list + resource: '*' + - action: bigquery.jobs.get + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-bigquery-job-sql-credential + scope: any + outcome: scope_control + aggregate_as: Verified targets for Recover API keys or tokens in other users’ SQL and query parameters + conditions: + - id: exact_verified_prerequisites + description: Exact source, resource, target, scope and gain must be verified; missing fact is UNKNOWN. Relevant + retained job; secret literal or parameter present; target identity and validity verified. INFORMATION_SCHEMA + alternative needs jobs.listAll+jobs.create. + confidence: conditional + severity: high + mitigation: Limit bigquery.jobs.listAll to trusted operators and monitor the target-specific use. + references: + - src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigqueryjobslistall--jobslist-jobsget--read-every-principals-sql-silently +- id: gcp-bigquery-table-row-credential + provider: gcp + service: bigquery + title: Read BigQuery table rows + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigquerytablesgetdata--paginate-an-entire-table-without-running-a-query + source_revision: 0b36331 + summary: Usable token or secret in table row; emit only for the exact verified source, resource and target. + requires: + all_of: + - action: bigquery.tables.getData + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-bigquery-table-row-credential + scope: any + outcome: scope_control + aggregate_as: Verified targets for Read BigQuery table rows + conditions: + - id: exact_verified_prerequisites + description: Exact source, resource, target, scope and gain must be verified; missing fact is UNKNOWN. Known + eligible table; row and column policies permit access; a usable credential actually appears in returned cells + and maps to a target principal. + confidence: conditional + severity: high + mitigation: Limit bigquery.tables.getData to trusted operators and monitor the target-specific use. + references: + - src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigquery-post-exploitation.md#bigquerytablesgetdata--paginate-an-entire-table-without-running-a-query diff --git a/src/privilege-escalation-paths/gcp/bigtable.yaml b/src/privilege-escalation-paths/gcp/bigtable.yaml new file mode 100644 index 0000000000..6e0f921295 --- /dev/null +++ b/src/privilege-escalation-paths/gcp/bigtable.yaml @@ -0,0 +1,65 @@ + +- id: gcp-audit-s01-35-widen-a-view-caller-can-alre + provider: gcp + service: bigtable + title: Widen a view caller can already read or mutate + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc.md#bigtableauthorizedviewsupdate--widen-a-view-that-you-can-already-use + summary: The source can gain widen a view caller can already read or mutate. Updating a view expands rows or columns + only if the caller can already use that view and the new subset is broader. + requires: + any_of: + - - action: bigtable.authorizedViews.update + resource: '*' + - action: bigtable.authorizedViews.readRows + resource: '*' + - - action: bigtable.authorizedViews.update + resource: '*' + - action: bigtable.authorizedViews.mutateRows + resource: '*' + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-audit-s01-35-widen-a-view-caller-can-alre + scope: any + aggregate_as: additional base-table rows/columns + conditions: + - id: exact_target_evidence + description: Exclusion treats it as ordinary data widening, but page describes new read or mutation privilege + beyond view definition; readRows/mutateRows are alternatives. Missing target evidence evaluates UNKNOWN. + confidence: conditional + severity: high + mitigation: Restrict the listed permissions and review target trust/consumer configuration. + source_revision: 0b36331 + references: + - https://cloud.hacktricks.wiki/en/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-bigtable-privesc/#bigtableauthorizedviewsupdate--widen-a-view-that-you-can-already-use +- id: gcp-bigtable-row-credential + provider: gcp + service: bigtable + title: Read Bigtable base-table rows + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigtable-post-exploitation.md#read-base-table-rows + source_revision: 0b36331 + summary: Usable token or credential in Bigtable cell; emit only for the exact verified source, resource and target. + requires: + all_of: + - action: bigtable.tables.readRows + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-bigtable-row-credential + scope: any + outcome: scope_control + aggregate_as: Verified targets for Read Bigtable base-table rows + conditions: + - id: exact_verified_prerequisites + description: Exact source, resource, target, scope and gain must be verified; missing fact is UNKNOWN. Known + table and row permission; returned cells contain a valid reusable credential mapped to a principal. GoogleSQL + alternative additionally needs bigtable.instances.executeQuery. + confidence: conditional + severity: high + mitigation: Limit bigtable.tables.readRows to trusted operators and monitor the target-specific use. + references: + - src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-bigtable-post-exploitation.md#read-base-table-rows diff --git a/src/privilege-escalation-paths/gcp/challenge-v3.yaml b/src/privilege-escalation-paths/gcp/challenge-v3.yaml index 82d1acfe75..d23edb6f0e 100644 --- a/src/privilege-escalation-paths/gcp/challenge-v3.yaml +++ b/src/privilege-escalation-paths/gcp/challenge-v3.yaml @@ -1199,7 +1199,17 @@ summary: 'Pool/template update relaxes exact issuance restriction, then #40 trust chain. Exact source, target, scope and prerequisite proof are required.' requires: - all_of: [] + any_of: + - - action: privateca.caPools.update + resource: '*' + - action: privateca.certificates.create + resource: '*' + - - action: privateca.certificateTemplates.update + resource: '*' + - action: privateca.certificates.create + resource: '*' + - action: privateca.certificateTemplates.use + resource: '*' source_kind: - gcp_user - gcp_service_account diff --git a/src/privilege-escalation-paths/gcp/cloudbuild.yaml b/src/privilege-escalation-paths/gcp/cloudbuild.yaml index f94856fbef..0b52f0f806 100644 --- a/src/privilege-escalation-paths/gcp/cloudbuild.yaml +++ b/src/privilege-escalation-paths/gcp/cloudbuild.yaml @@ -136,3 +136,35 @@ 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. +- id: gcp-cloudbuild-log-credential + provider: gcp + service: cloudbuild + title: Recover credentials printed in stored Cloud Build logs + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-build-post-exploitation.md#read-stored-build-output + source_revision: 0b36331 + summary: Identity authenticated by valid credential in build output; emit only for the exact verified source, + resource and target. + requires: + all_of: + - action: logging.logEntries.list + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-cloudbuild-log-credential + scope: any + outcome: scope_control + aggregate_as: Verified targets for Recover credentials printed in stored Cloud Build logs + conditions: + - id: exact_verified_prerequisites + description: Exact source, resource, target, scope and gain must be verified; missing fact is UNKNOWN. Useful + retained log; alternate user-bucket route needs storage.objects.get, default-bucket helper needs cloudbuild.builds.get + and supported Viewer; content and target verified. + confidence: conditional + severity: high + mitigation: Limit logging.logEntries.list to trusted operators and monitor the target-specific use. + references: + - src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-build-post-exploitation.md#read-stored-build-output diff --git a/src/privilege-escalation-paths/gcp/composer.yaml b/src/privilege-escalation-paths/gcp/composer.yaml index 3a19b1ce4b..5caa1b1671 100644 --- a/src/privilege-escalation-paths/gcp/composer.yaml +++ b/src/privilege-escalation-paths/gcp/composer.yaml @@ -71,7 +71,7 @@ mitigation: Restrict composer.environments.executeAirflowCommand (roles/composer.admin, roles/composer.environmentAndStorageObjectAdmin). references: - https://cloud.google.com/composer/docs/composer-2/access-control - notes: No actAs needed. Also dumps Airflow connections and variables (data, not modelled). + notes: No actAs needed. Airflow connections and variables can yield replayable credentials, but this entry reaches only the environment SA through available code. Credential replay requires actual connection/variable contents, a live secret and its principal; see the separate exclusion. - id: gcp-composer-environments-update provider: gcp diff --git a/src/privilege-escalation-paths/gcp/compute.yaml b/src/privilege-escalation-paths/gcp/compute.yaml index 4beb652aab..656c167cb5 100644 --- a/src/privilege-escalation-paths/gcp/compute.yaml +++ b/src/privilege-escalation-paths/gcp/compute.yaml @@ -364,3 +364,55 @@ severity: high mitigation: Pin concrete image names in instance templates, restrict compute.images.create in image projects and enforce compute.trustedImageProjects. notes: Targets are SAs of collected instance templates whose boot disk sourceImage is projects/

/global/images/family/; MIG-only consumers resolve through their template. +- id: gcp-gke-pod-node-metadata-token + provider: gcp + service: container + title: Compromised pod reads node SA token or legacy kube-env from metadata + source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#federation-and-metadata-server-abuse + source_revision: 0b36331 + summary: Compromised pod reads node SA token or legacy kube-env from metadata; emit only when exact source, target, + and prerequisite evidence is verified. + requires: + all_of: [] + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-gke-pod-node-metadata-token + scope: any + outcome: credentials + aggregate_as: Compromised pod reads node SA token or legacy kube-env from metadata + conditions: + - id: exact_verified_prerequisites + description: The exact source, target and exploit-enabling facts must be verified; missing facts evaluate UNKNOWN. + confidence: conditional + severity: high + mitigation: Restrict the stated permission and remove the exploitable trust or configuration. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#federation-and-metadata-server-abuse + source_kind: gcp_challenge_foothold +- id: gcp-compromised-vm-metadata-sa-token + provider: gcp + service: compute + title: Read attached VM SA token from metadata after host access + source: src/pentesting-cloud/gcp-security/gcp-basic-information/README.md#service-accounts + source_revision: 0b36331 + summary: Read attached VM SA token from metadata after host access; emit only when exact source, target, and prerequisite + evidence is verified. + requires: + all_of: [] + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-compromised-vm-metadata-sa-token + scope: any + outcome: credentials + aggregate_as: Read attached VM SA token from metadata after host access + conditions: + - id: exact_verified_prerequisites + description: The exact source, target and exploit-enabling facts must be verified; missing facts evaluate UNKNOWN. + confidence: conditional + severity: high + mitigation: Restrict the stated permission and remove the exploitable trust or configuration. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/gcp-security/gcp-basic-information/README.md#service-accounts + source_kind: gcp_challenge_foothold diff --git a/src/privilege-escalation-paths/gcp/configcontroller.yaml b/src/privilege-escalation-paths/gcp/configcontroller.yaml index a59aad70b8..3ab6dcf315 100644 --- a/src/privilege-escalation-paths/gcp/configcontroller.yaml +++ b/src/privilege-escalation-paths/gcp/configcontroller.yaml @@ -11,38 +11,44 @@ title: Write Config Connector resources so KCC acts as its configured Google service account 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 obtain the privileges of the Config Connector identity of a Config Controller (or KCC-enabled GKE) cluster where it can create or update *.cnrm.cloud.google.com custom resources. + summary: The source can obtain the privileges of the Config Connector identity of a Config Controller (or KCC-enabled + GKE) cluster where it can create or update *.cnrm.cloud.google.com custom resources. requires: any_of: - - - action: container.thirdPartyObjects.create - resource: "{target.host_resource}" - - - action: container.thirdPartyObjects.update - resource: "{target.host_resource}" + - - action: container.thirdPartyObjects.create + resource: '{target.host_resource}' + - - action: container.thirdPartyObjects.update + resource: '{target.host_resource}' target: kind: gcp_service_account selector: attached_to_service: config_connector_identity scope: any - aggregate_as: "Config Connector identities of clusters where the source can write KCC resources" + aggregate_as: Config Connector identities of clusters where the source can write KCC resources conditions: - - id: in_cluster_rbac - description: The same write is possible through in-cluster Kubernetes RBAC on the KCC CRDs (not visible to GCP IAM); the GKE IAM permissions cover all custom resources of the cluster. - - id: watched_namespace - description: The resource must be written in a namespace KCC reconciles (namespaced mode uses the namespace's ConfigConnectorContext identity). - - id: admission - description: Policy Controller constraints or validating webhooks can reject the manifest. - - id: api_server_reachable - description: Needs network reachability and credentials to the cluster API server. + - id: in_cluster_rbac + description: Native Kubernetes RBAC create/update/patch on the watched KCC CRD is an independently sufficient + authorization path. This GCP-IAM entry covers only container.thirdPartyObjects.*; the native path requires + a cross-plane RBAC evaluator and must remain UNKNOWN until implemented. + - id: watched_namespace + description: The resource must be written in a namespace KCC reconciles (namespaced mode uses the namespace's + ConfigConnectorContext identity). + - id: admission + description: Policy Controller constraints or validating webhooks can reject the manifest. + - id: api_server_reachable + description: Needs network reachability and credentials to the cluster API server. blockers: - - gcp_deny_policy + - 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). + 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: The reach is bounded by the Config Connector identity's own IAM permissions; the reconciled API calls are attributed to that identity. Any KCC resource (IAMPolicyMember, IAMServiceAccountKey, compute instances) is a deputy for it. - + - https://docs.cloud.google.com/config-connector/docs/how-to/install-manually + - https://docs.cloud.google.com/kubernetes-engine/docs/reference/api-permissions + notes: The reach is bounded by the Config Connector identity's own IAM permissions; the reconciled API calls are + attributed to that identity. Any KCC resource (IAMPolicyMember, IAMServiceAccountKey, compute instances) is + a deputy for it. - id: gcp-configcontroller-krmapihosts-setiampolicy provider: gcp service: configcontroller @@ -73,3 +79,32 @@ references: - https://cloud.google.com/kubernetes-engine/enterprise/config-controller/docs/access-control notes: Two-hop path (instance IAM grant, then gcp-configcontroller-kcc-resource-write); documented on the persistence page at 171e422. +- id: gcp-kcc-k8s-rbac-iam-member + provider: gcp + service: configcontroller + title: ConfigConfusion in-cluster RBAC permits IAMPolicyMember CRD self grant + source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#authorization-bypass-and-shadow-resources + source_revision: 0b36331 + summary: ConfigConfusion in-cluster RBAC permits IAMPolicyMember CRD self grant; emit only when exact source, + target, and prerequisite evidence is verified. + requires: + all_of: [] + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-kcc-k8s-rbac-iam-member + scope: any + outcome: scope_control + aggregate_as: ConfigConfusion in-cluster RBAC permits IAMPolicyMember CRD self grant + conditions: + - id: exact_verified_prerequisites + description: The exact source, target and exploit-enabling facts must be verified; missing facts evaluate UNKNOWN. + confidence: conditional + severity: high + mitigation: Restrict the stated permission and remove the exploitable trust or configuration. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#authorization-bypass-and-shadow-resources + source_kind: + - gcp_user + - gcp_service_account + source_selector: {} diff --git a/src/privilege-escalation-paths/gcp/container.yaml b/src/privilege-escalation-paths/gcp/container.yaml index 36f95ca276..50b5ec296e 100644 --- a/src/privilege-escalation-paths/gcp/container.yaml +++ b/src/privilege-escalation-paths/gcp/container.yaml @@ -527,66 +527,75 @@ 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. + 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.jobs.update - resource: "{target.scope}" - - - action: container.replicaSets.update - resource: "{target.scope}" - - - action: container.replicationControllers.update - resource: "{target.scope}" + - - 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.jobs.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 scope: cluster - aggregate_as: "KSAs selectable in pod templates of GKE cluster {target.scope}" + 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). + - 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 + - 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. + 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. 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. - + - 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. container.pods.update alone only swaps an existing Pod image and keeps its KSA; that narrower existing-pod + KSA credential path is gcp-container-pods-update-running-ksa. The node SA path remains 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 @@ -691,3 +700,65 @@ 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: 0b36331 + 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}' + target: + kind: k8s_service_account + selector: + k8s_sa_used_by_running_pod: 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/ +- id: gcp-container-pods-attach-running-ksa + provider: gcp + service: container + title: Use attach to control an interactive process in a running pod + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-container-privesc.md#containerpodsattach + source_revision: 0b36331 + summary: An attach-capable source can issue commands as the pod KSA only when its existing process accepts useful + stdin. + requires: + all_of: + - action: container.pods.attach + resource: '{target.scope}' + target: + kind: k8s_service_account + selector: + k8s_sa_used_by_running_pod: true + gcp_challenge_fact: gcp-container-pods-attach-running-ksa + scope: cluster + outcome: credentials + conditions: + - id: interactive_process + description: A running container process must accept attacker-controlled stdin and permit commands that expose + its token. + - id: api_server + description: Cluster API and attach stream must be reachable. + confidence: conditional + severity: high + mitigation: Restrict pod attach and avoid interactive privileged containers. + references: + - https://kubernetes.io/docs/reference/kubectl/generated/kubectl_attach/ + notes: Must remain UNKNOWN until the collector supplies an attach-usable process fact joined to the pod and KSA. diff --git a/src/privilege-escalation-paths/gcp/dataform.yaml b/src/privilege-escalation-paths/gcp/dataform.yaml index 6da900d9c1..9d18ff6451 100644 --- a/src/privilege-escalation-paths/gcp/dataform.yaml +++ b/src/privilege-escalation-paths/gcp/dataform.yaml @@ -68,32 +68,74 @@ title: Trigger an existing Dataform workflow configuration that runs with a Google Account's user credentials source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataform-privesc.md#dataformworkflowinvocationscreate--invoke-an-existing-compilation-result-or-user-credential-workflow source_revision: 171e422 - summary: The source can make the saved actions of a user-credential Dataform workflow configuration run as the Google Account that authorized it, without iam.serviceAccounts.actAs. + summary: The source can make the saved actions of a user-credential Dataform workflow configuration run as the + Google Account that authorized it, without iam.serviceAccounts.actAs. requires: all_of: - - action: dataform.workflowInvocations.create - resource: "{target.host_resource}" + - action: dataform.workflowInvocations.create + resource: '{target.host_resource}' target: kind: gcp_user selector: attached_to_service: dataform_workflow_config_end_user scope: same_project - aggregate_as: "Google Accounts whose stored Dataform user credentials back workflow configs the source can invoke" + aggregate_as: Google Accounts whose stored Dataform user credentials back workflow configs the source can invoke conditions: - - id: preset_actions_only - description: Only the release and action selection already saved in the workflow configuration run; invocation authority cannot change the SQL, release config, OAuth owner or scopes, and no user token is returned. - - id: valid_user_authorization - description: The workflow configuration must carry invocationConfig.endUserAuthConfig with a still-valid Google Account authorization. - - id: service_account_variant - description: For service-account-backed compilation results or workflow configs strict act-as mode requires caller actAs on the effective SA; that path is covered by gcp-dataform-workflow-invocation-actas. + - id: preset_actions_only + description: Only the release and action selection already saved in the workflow configuration run; invocation + authority cannot change the SQL, release config, OAuth owner or scopes, and no user token is returned. + - id: valid_user_authorization + description: The workflow configuration must carry invocationConfig.endUserAuthConfig with a still-valid Google + Account authorization. + - id: service_account_variant + description: Service-account-backed invocation also requires caller actAs on the effective SA. gcp-dataform-workflow-invocation-actas + covers attacker-authored SQL; invocation of a pre-existing compilation result with only workflowInvocations.create + plus actAs is a separate fixed-actions path requiring result/SA inventory. blockers: - - gcp_deny_policy - - vpc_sc_perimeter + - gcp_deny_policy + - vpc_sc_perimeter confidence: conditional severity: medium - mitigation: Prefer dedicated service accounts over end-user credentials for Dataform workflows, restrict dataform.workflowInvocations.create on such repositories, and deny end_user_auth_config with a custom organization policy constraint. + mitigation: Prefer dedicated service accounts over end-user credentials for Dataform workflows, restrict dataform.workflowInvocations.create + on such repositories, and deny end_user_auth_config with a custom organization policy constraint. references: - - https://docs.cloud.google.com/dataform/docs/schedule-runs - - https://docs.cloud.google.com/dataform/reference/rest/v1/InvocationConfig - - https://docs.cloud.google.com/dataform/docs/strict-act-as-mode - notes: Replaces gcp-dataform-scheduled-workflow-code-tamper; at 171e422 HackTricks no longer treats internal-repository commit poisoning as a current path, because strict act-as mode blocks cron releases for repositories without a third-party remote. Google's docs do not explicitly state which caller permission triggers a user-credential config, so this follows HackTricks. + - https://docs.cloud.google.com/dataform/docs/schedule-runs + - https://docs.cloud.google.com/dataform/reference/rest/v1/InvocationConfig + - https://docs.cloud.google.com/dataform/docs/strict-act-as-mode + notes: Replaces gcp-dataform-scheduled-workflow-code-tamper; at 171e422 HackTricks no longer treats internal-repository + commit poisoning as a current path, because strict act-as mode blocks cron releases for repositories without + a third-party remote. Google's docs do not explicitly state which caller permission triggers a user-credential + config, so this follows HackTricks. +- id: gcp-dataform-existing-compilation-result-actas + provider: gcp + service: dataform + title: Invoke saved Dataform actions as their effective service account + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-dataform-privesc.md#dataformworkflowinvocationscreate--invoke-an-existing-compilation-result-or-user-credential-workflow + source_revision: 0b36331 + summary: A caller can trigger the saved BigQuery actions of an existing compilation result as its effective service + account. + requires: + all_of: + - action: dataform.workflowInvocations.create + resource: '{target.host_resource}' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + gcp_actas_granted_on_target: true + gcp_challenge_fact: gcp-dataform-existing-compilation-result-actas + scope: same_project + conditions: + - id: saved_actions + description: A known existing compilation result must contain useful saved actions; the invoker cannot author + SQL through this permission alone. + - id: service_agent + description: The Dataform service agent must be able to mint a token for the effective SA. + confidence: conditional + severity: high + mitigation: Restrict workflow invocation and actAs on service accounts used by saved Dataform results. + references: + - https://docs.cloud.google.com/dataform/reference/rest/v1/projects.locations.repositories.workflowInvocations/create + - https://docs.cloud.google.com/dataform/docs/strict-act-as-mode + notes: UNKNOWN until compilation result to repository, effective SA, and action inventory are joined. diff --git a/src/privilege-escalation-paths/gcp/datafusion.yaml b/src/privilege-escalation-paths/gcp/datafusion.yaml index 777e5718dc..3e3003b9ef 100644 --- a/src/privilege-escalation-paths/gcp/datafusion.yaml +++ b/src/privilege-escalation-paths/gcp/datafusion.yaml @@ -11,37 +11,41 @@ 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 obtain the privileges of the pipeline VM service account of Data Fusion instances where it can create and execute pipelines (PySpark / Scala Spark plugins run arbitrary code on the Dataproc cluster). + summary: The source can obtain the privileges of the pipeline VM service account of Data Fusion instances where + it can create and execute pipelines (PySpark / Scala Spark plugins run arbitrary code on the Dataproc cluster). requires: all_of: - - action: datafusion.instances.get - resource: "{target.host_resource}" - - action: datafusion.pipelines.create - resource: "{target.host_resource}" - - action: datafusion.pipelines.execute - resource: "{target.host_resource}" + - action: datafusion.instances.get + resource: '{target.host_resource}' + - action: datafusion.namespaces.get + resource: '{target.host_resource}' + - action: datafusion.pipelines.create + resource: '{target.host_resource}' + - action: datafusion.pipelines.execute + resource: '{target.host_resource}' target: kind: gcp_service_account selector: attached_to_service: datafusion_instance scope: same_project - aggregate_as: "Pipeline VM SAs of Data Fusion instances where the source can run pipelines" + aggregate_as: Pipeline VM SAs of Data Fusion instances where the source can run pipelines conditions: - - id: plugin_installed - description: A code-capable plugin (PySpark Program, Scala Spark) must be installed; uploading one needs datafusion.artifacts.create/update. - - 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. + - id: plugin_installed + description: A code-capable plugin (PySpark Program, Scala Spark) must be installed; uploading one needs datafusion.artifacts.create/update. + - 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 + - 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. + 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 - + - 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 diff --git a/src/privilege-escalation-paths/gcp/dataproc.yaml b/src/privilege-escalation-paths/gcp/dataproc.yaml index 4bce7e91d9..c51ddc15ea 100644 --- a/src/privilege-escalation-paths/gcp/dataproc.yaml +++ b/src/privilege-escalation-paths/gcp/dataproc.yaml @@ -282,3 +282,29 @@ notes: dataproc.clusters.get only discovers the SA, scopes and bucket names; the escalation is the object replacement. Planting a brand-new object needs only storage.objects.create but executes nothing unless a consumer references it. +- id: gcp-dataproc-yarn-unauthenticated-job + provider: gcp + service: dataproc + title: Unauthenticated Dataproc YARN UI submits job as cluster identity + source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#managed-service-tenant--host-escapes + source_revision: 0b36331 + summary: Unauthenticated Dataproc YARN UI submits job as cluster identity; emit only when exact source, target, + and prerequisite evidence is verified. + requires: + all_of: [] + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-dataproc-yarn-unauthenticated-job + scope: any + outcome: workload_execution + aggregate_as: Unauthenticated Dataproc YARN UI submits job as cluster identity + conditions: + - id: exact_verified_prerequisites + description: The exact source, target and exploit-enabling facts must be verified; missing facts evaluate UNKNOWN. + confidence: conditional + severity: high + mitigation: Restrict the stated permission and remove the exploitable trust or configuration. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/historical-cross-project-vulnerabilities.md#managed-service-tenant--host-escapes + source_kind: gcp_challenge_foothold diff --git a/src/privilege-escalation-paths/gcp/iam.yaml b/src/privilege-escalation-paths/gcp/iam.yaml index 988aa0a3fd..b3a7fc6ca0 100644 --- a/src/privilege-escalation-paths/gcp/iam.yaml +++ b/src/privilege-escalation-paths/gcp/iam.yaml @@ -223,3 +223,177 @@ references: - https://cloud.google.com/iam/docs/creating-custom-roles notes: EXTENSION selector gcp_custom_role_bound_to_source = target scope is one where the source (directly or via group) has a binding to a custom role defined in the scope covered by iam.roles.update. Adding e.g. resourcemanager.projects.setIamPolicy yields scope ownership. +- id: gcp-audit-s01-00-steal-a-service-account-key + provider: gcp + service: iam + title: Steal a service-account key from a compromised VM to bypass narrow metadata-token scopes + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/README.md#bypassing-access-scopes + summary: The source can gain unscoped access token and effective IAM permissions blocked by VM scope. A key on + a compromised VM can mint a token with wider scopes, but GCP inventory cannot establish guest-file presence, + source access to it, or active key state. + requires: + all_of: [] + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-audit-s01-00-steal-a-service-account-key + scope: any + aggregate_as: key-owning GCP service account and its broader OAuth authority + conditions: + - id: exact_target_evidence + description: The page explicitly suggests finding a service key on a compromised host to mint a new OAuth token + without the VM metadata token scope restriction. The exclusion treats this as no new identity edge, but it + is a new credential and can enable IAM permissions previously blocked by the old token scope. A key must actually + be present, accessible in guest storage, unrevoked, and belong to an SA whose IAM rights exceed the VM scopes. + Missing target evidence evaluates UNKNOWN. + - id: effective_scope_delta + description: The key must be accessible and active, belong to the target SA, and permit an OAuth scope with + an effective permission absent from the VM metadata token. + confidence: conditional + severity: high + mitigation: Remove service-account keys from VMs and rotate exposed keys. + source_revision: 0b36331 + references: + - https://cloud.hacktricks.wiki/en/pentesting-cloud/gcp-security/gcp-privilege-escalation/README/#bypassing-access-scopes + source_kind: + - gcp_user + - gcp_service_account +- id: gcp-iam-serviceaccounts-getopenidtoken-application + provider: gcp + service: iam + title: iam.serviceAccounts.getOpenIdToken` — impersonate a service account to an OIDC-protected application + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iam-privesc.md#iamserviceaccountsgetopenidtoken--impersonate-a-service-account-to-an-oidc-protected-application + source_revision: 0b36331 + summary: The source can mint a Google-signed OIDC ID token representing any target service account on which it + has iam.serviceAccounts.getOpenIdToken; application use depends on audience and authorization. + requires: + all_of: + - action: iam.serviceAccounts.getOpenIdToken + resource: '{target.email}' + target: + kind: gcp_service_account + selector: + resource_permission_covers_target: iam.serviceAccounts.getOpenIdToken + scope: any + outcome: credentials + grants: + - OIDC identity token for target service account + conditions: + - id: c1 + description: Service Account Credentials API must be enabled. + - id: c2 + description: An application must trust the audience and authorize the service-account identity; no Google API + OAuth access follows. + blockers: + - gcp_deny_policy + confidence: derived + severity: medium + mitigation: Restrict roles/iam.serviceAccountOpenIdTokenCreator to intended service accounts and audiences; enforce + application authorization. + references: + - https://cloud.google.com/iam/docs/reference/credentials/rest/v1/projects.serviceAccounts/generateIdToken +- id: gcp-sa-getopenidtoken-protected-endpoint + provider: gcp + service: iam + title: Mint OIDC ID token to invoke protected endpoint as SA + source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/iam-and-service-account-impersonation-attacks.md#service-account-impersonation--the-crown-jewel + source_revision: 0b36331 + summary: Mint OIDC ID token to invoke protected endpoint as SA; emit only when exact source, target, and prerequisite + evidence is verified. + requires: + all_of: + - action: iam.serviceAccounts.getOpenIdToken + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-sa-getopenidtoken-protected-endpoint + scope: any + outcome: impersonation + aggregate_as: Mint OIDC ID token to invoke protected endpoint as SA + grants: + - OIDC ID token accepted only by the verified audience + conditions: + - id: exact_verified_prerequisites + description: The exact source, target and exploit-enabling facts must be verified; missing facts evaluate UNKNOWN. + confidence: conditional + severity: high + mitigation: Restrict the stated permission and remove the exploitable trust or configuration. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/iam-and-service-account-impersonation-attacks.md#service-account-impersonation--the-crown-jewel + source_kind: + - gcp_user + - gcp_service_account + source_selector: {} +- id: gcp-pubsub-push-oidc-endpoint + provider: gcp + service: pubsub + title: Pub/Sub push OIDC token to attacker endpoint + source: src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/resource-sharing-and-confused-deputy-attacks.md#notable-subtleties + source_revision: 0b36331 + summary: Pub/Sub push OIDC token to attacker endpoint; emit only when exact source, target, and prerequisite evidence + is verified. + requires: + any_of: + - - action: pubsub.subscriptions.create + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.host_resource}' + - - action: pubsub.subscriptions.update + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.host_resource}' + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-pubsub-push-oidc-endpoint + scope: any + outcome: impersonation + aggregate_as: Pub/Sub push OIDC token to attacker endpoint + grants: + - OIDC ID token accepted only by the verified audience + conditions: + - id: exact_verified_prerequisites + description: The exact source, target and exploit-enabling facts must be verified; missing facts evaluate UNKNOWN. + confidence: conditional + severity: high + mitigation: Restrict the stated permission and remove the exploitable trust or configuration. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/gcp-security/gcp-cross-project-attacks/resource-sharing-and-confused-deputy-attacks.md#notable-subtleties + source_kind: + - gcp_user + - gcp_service_account + source_selector: {} +- id: gcp-pab-delete-unblock-allow + provider: gcp + service: iam + title: Delete PAB binding or policy to lift principal resource boundary + source: src/pentesting-cloud/gcp-security/gcp-basic-information/README.md#remove + source_revision: 0b36331 + summary: Delete PAB binding or policy to lift principal resource boundary; emit only when exact source, target, + and prerequisite evidence is verified. + requires: + any_of: + - - action: iam.policyBindings.delete + resource: '*' + - - action: iam.principalAccessBoundaryPolicies.delete + resource: '*' + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-pab-delete-unblock-allow + scope: any + outcome: permission_grant + aggregate_as: Delete PAB binding or policy to lift principal resource boundary + conditions: + - id: exact_verified_prerequisites + description: The exact source, target and exploit-enabling facts must be verified; missing facts evaluate UNKNOWN. + confidence: conditional + severity: high + mitigation: Restrict the stated permission and remove the exploitable trust or configuration. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/gcp-security/gcp-basic-information/README.md#remove + source_kind: + - gcp_user + - gcp_service_account + source_selector: {} diff --git a/src/privilege-escalation-paths/gcp/integrations.yaml b/src/privilege-escalation-paths/gcp/integrations.yaml new file mode 100644 index 0000000000..90781d6884 --- /dev/null +++ b/src/privilege-escalation-paths/gcp/integrations.yaml @@ -0,0 +1,62 @@ +- id: gcp-integration-invoke-input-effect-12 + provider: gcp + service: integrations + title: Invoke existing published credentialed integration with chosen inputs + source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#integrationsintegrationsinvoke--invoke-a-credentialed-workflow + source_revision: 0b36331 + summary: Invoke existing published credentialed integration with chosen inputs; emit only when exact source, target, + and prerequisite evidence is verified. + requires: + all_of: + - action: integrations.integrations.invoke + resource: '*' + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-integration-invoke-input-effect-12 + scope: any + outcome: scope_control + aggregate_as: Invoke existing published credentialed integration with chosen inputs + conditions: + - id: exact_verified_prerequisites + description: The exact source, target and exploit-enabling facts must be verified; missing facts evaluate UNKNOWN. + confidence: conditional + severity: high + mitigation: Restrict the stated permission and remove the exploitable trust or configuration. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#integrationsintegrationsinvoke--invoke-a-credentialed-workflow + source_kind: + - gcp_user + - gcp_service_account + source_selector: {} +- id: gcp-integration-invoke-input-effect-13 + provider: gcp + service: integrations + title: Redirect credentialed HTTP connector via caller-controlled URL + source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#http-connector-credential-forwarding + source_revision: 0b36331 + summary: Redirect credentialed HTTP connector via caller-controlled URL; emit only when exact source, target, + and prerequisite evidence is verified. + requires: + all_of: + - action: integrations.integrations.invoke + resource: '*' + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-integration-invoke-input-effect-13 + scope: any + outcome: scope_control + aggregate_as: Redirect credentialed HTTP connector via caller-controlled URL + conditions: + - id: exact_verified_prerequisites + description: The exact source, target and exploit-enabling facts must be verified; missing facts evaluate UNKNOWN. + confidence: conditional + severity: high + mitigation: Restrict the stated permission and remove the exploitable trust or configuration. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#http-connector-credential-forwarding + source_kind: + - gcp_user + - gcp_service_account + source_selector: {} diff --git a/src/privilege-escalation-paths/gcp/privatecatalog.yaml b/src/privilege-escalation-paths/gcp/privatecatalog.yaml index f858003bc4..d582fb0551 100644 --- a/src/privilege-escalation-paths/gcp/privatecatalog.yaml +++ b/src/privilege-escalation-paths/gcp/privatecatalog.yaml @@ -35,3 +35,31 @@ references: - https://docs.cloud.google.com/service-catalog/docs/create-solutions notes: Deployment Manager solutions run as the consumer project's Google APIs Service Agent (roles/editor by default), like gcp-deploymentmanager-deployments-create. +- id: gcp-privatecatalog-terraform-version-poison + provider: gcp + service: cloudprivatecatalogproducer + title: Poison a Terraform solution deployed by a consumer + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-private-catalog-privesc.md#cloudprivatecatalogproducerproductsupdate--poison-an-existing-deployable-solution-version + summary: Product-version update can cause a later consumer deployment to execute attacker content as its Cloud + Build identity. + requires: + all_of: + - action: cloudprivatecatalogproducer.products.update + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-privatecatalog-terraform-version-poison + scope: any + conditions: + - id: terraform_consumer_deploys + description: An attached Terraform solution version must be selected for a consumer deployment; its configured + or default Cloud Build service account must execute the modified asset and hold privileges beyond the source. + confidence: conditional + severity: high + mitigation: Restrict producer updates and review version assets before consumer deployment. + references: + - https://docs.cloud.google.com/service-catalog/docs/overview + source_revision: 0b36331 + notes: Exact source/resource/target evidence must be emitted in gcp_privesc_challenge_evidence from the requested + collector. Missing evidence is UNKNOWN; do not infer any other service account. diff --git a/src/privilege-escalation-paths/gcp/run.yaml b/src/privilege-escalation-paths/gcp/run.yaml index 7284cf96a8..1da409bc39 100644 --- a/src/privilege-escalation-paths/gcp/run.yaml +++ b/src/privilege-escalation-paths/gcp/run.yaml @@ -391,3 +391,53 @@ severity: high mitigation: Restrict run.workerpools.setIamPolicy (roles/run.admin, roles/owner). notes: Mirrors gcp-run-services-setiampolicy-actas for the worker pool resource type. +- id: gcp-run-literal-sa-key-disclosure + provider: gcp + service: run + title: Plaintext credential theft + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-run-privesc.md#plaintext-environment-disclosure-with-cloud-run-read-permissions + requires: + any_of: + - - action: run.services.get + resource: '*' + - - action: run.services.list + resource: '*' + - - action: run.configurations.get + resource: '*' + - - action: run.configurations.list + resource: '*' + - - action: run.revisions.get + resource: '*' + - - action: run.revisions.list + resource: '*' + - - action: run.jobs.get + resource: '*' + - - action: run.jobs.list + resource: '*' + - - action: run.executions.get + resource: '*' + - - action: run.executions.list + resource: '*' + - - action: run.tasks.get + resource: '*' + - - action: run.tasks.list + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-run-literal-sa-key-disclosure + scope: any + conditions: + - id: active_key_in_literal_env + description: An environment value must contain an active Google service-account key, not a Secret Manager reference + or opaque application password. The active key ID and service-account email must match collector evidence. + confidence: conditional + severity: high + mitigation: Restrict the listed permissions and audit the target configuration. + references: + - https://docs.cloud.google.com/run/docs/instances/create-and-manage-instances + summary: Reading a Cloud Run template with an embedded active Google service-account key can disclose that stronger + credential. + source_revision: 0b36331 + notes: Exact source/resource/target evidence must be emitted in gcp_privesc_challenge_evidence from the requested + collector. Missing evidence is UNKNOWN; do not infer any other service account. diff --git a/src/privilege-escalation-paths/gcp/secretmanager.yaml b/src/privilege-escalation-paths/gcp/secretmanager.yaml new file mode 100644 index 0000000000..4c6a339dab --- /dev/null +++ b/src/privilege-escalation-paths/gcp/secretmanager.yaml @@ -0,0 +1,59 @@ + +- id: gcp-secretmanager-versions-access-sa-key + provider: gcp + service: secretmanager + title: Stored credential theft + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#escalation-through-a-recovered-secret + requires: + all_of: + - action: secretmanager.versions.access + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-secretmanager-versions-access-sa-key + scope: any + conditions: + - id: active_key_in_secret + description: The accessible enabled secret version must contain an active key for a stronger service account; + the source must not already have equivalent access. The active key ID and service-account email must match + collector evidence. + confidence: conditional + severity: high + mitigation: Restrict the listed permissions and audit the target configuration. + references: + - https://docs.cloud.google.com/secret-manager/docs/access-secret-version + summary: The source can obtain a stronger service-account credential stored in an accessible secret version when + the credential has been verified active. + source_revision: 0b36331 + notes: Exact source/resource/target evidence must be emitted in gcp_privesc_challenge_evidence from the requested + collector. Missing evidence is UNKNOWN; do not infer any other service account. +- id: gcp-secretmanager-setiampolicy-sa-key + provider: gcp + service: secretmanager + title: Secret IAM self-grant to credential theft + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-secretmanager-privesc.md#secretmanagersecretssetiampolicy + requires: + all_of: + - action: secretmanager.secrets.setIamPolicy + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-secretmanager-setiampolicy-sa-key + scope: any + conditions: + - id: active_key_in_secret + description: The writable secret must hold an enabled version with an active stronger service-account key; IAM + Deny and policy conditions must allow the self-grant. The active key ID and service-account email must match + collector evidence. + confidence: conditional + severity: high + mitigation: Restrict the listed permissions and audit the target configuration. + references: + - https://docs.cloud.google.com/secret-manager/docs/access-secret-version + summary: The source can obtain a stronger service-account credential stored in an accessible secret version when + the credential has been verified active. + source_revision: 0b36331 + notes: Exact source/resource/target evidence must be emitted in gcp_privesc_challenge_evidence from the requested + collector. Missing evidence is UNKNOWN; do not infer any other service account. diff --git a/src/privilege-escalation-paths/gcp/storage.yaml b/src/privilege-escalation-paths/gcp/storage.yaml index ade22ce66a..92aa91ca5f 100644 --- a/src/privilege-escalation-paths/gcp/storage.yaml +++ b/src/privilege-escalation-paths/gcp/storage.yaml @@ -155,3 +155,34 @@ mitigation: Restrict storage.buckets.setIamPolicy and storage.managedFolders.setIamPolicy on buckets that hold code, staging artifacts or build sources. references: - https://docs.cloud.google.com/storage/docs/access-control/iam-permissions +- id: gcp-designcenter-bucket-credential + provider: gcp + service: storage + title: Read known bucket objects through Design Center Viewer 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 + source_revision: 0b36331 + summary: Credential in known bucket object; emit only for the exact verified source, resource and target. + requires: + all_of: + - action: storage.objects.get + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-designcenter-bucket-credential + scope: any + outcome: scope_control + aggregate_as: Verified targets for Read known bucket objects through Design Center Viewer role + conditions: + - id: exact_verified_prerequisites + description: Exact source, resource, target, scope and gain must be verified; missing fact is UNKNOWN. Known + bucket/object; effective role grant supplies object get; object contains usable credential mapped to a principal. + Storage list is optional discovery. + confidence: conditional + severity: high + mitigation: Limit storage.objects.get to trusted operators and monitor the target-specific use. + references: + - src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-application-design-center-post-exploitation.md#rolesdesigncenterviewer--read-objects-from-known-cloud-storage-buckets diff --git a/src/privilege-escalation-paths/gcp/wif.yaml b/src/privilege-escalation-paths/gcp/wif.yaml index 06bddc9d32..9c7f304cd6 100644 --- a/src/privilege-escalation-paths/gcp/wif.yaml +++ b/src/privilege-escalation-paths/gcp/wif.yaml @@ -11,129 +11,144 @@ 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 obtain the privileges of service accounts and roles bound to pool-wide principals of workload identity pools on which it holds workloadIdentityPoolProviders.create. + summary: The source can obtain the privileges of service accounts bound to pool-wide principals of workload identity + pools on which it holds workloadIdentityPoolProviders.create. requires: all_of: - - action: iam.googleapis.com/workloadIdentityPoolProviders.create - resource: "{target.host_resource}" + - action: iam.googleapis.com/workloadIdentityPoolProviders.create + resource: '{target.host_resource}' target: kind: gcp_service_account selector: attached_to_service: wif_pool_bound scope: any - aggregate_as: "SAs and roles bound to pool-wide principals of controllable WIF pools" + aggregate_as: SAs bound to pool-wide principals of controllable WIF pools conditions: - - id: pool_wide_binding - description: Only effective when the pool has a binding for all its identities (principalSet .../workloadIdentityPools//*) or for attribute values the new provider can assert. - - id: pool_active - description: The pool must be enabled. + - id: pool_wide_binding + description: Only effective when the pool has a binding for all its identities (principalSet .../workloadIdentityPools//*) + or for attribute values the new provider can assert. + - id: pool_active + description: The pool must be enabled. blockers: - - gcp_deny_policy - - {id: org_policy_constraint, constraint: iam.workloadIdentityPoolProviders} + - gcp_deny_policy + - id: org_policy_constraint + constraint: iam.workloadIdentityPoolProviders confidence: conditional severity: critical - mitigation: Restrict workloadIdentityPoolProviders.* (roles/iam.workloadIdentityPoolAdmin), avoid pool-wide bindings and restrict allowed providers by org policy. - + mitigation: Restrict workloadIdentityPoolProviders.* (roles/iam.workloadIdentityPoolAdmin), avoid pool-wide 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 obtain the privileges of service accounts and roles bound to principals of workload identity pools whose providers it can update. + summary: The source can obtain the privileges of service accounts bound to principals of workload identity pools + whose providers it can update. requires: all_of: - - action: iam.googleapis.com/workloadIdentityPoolProviders.update - resource: "{target.host_resource}" + - action: iam.googleapis.com/workloadIdentityPoolProviders.update + resource: '{target.host_resource}' target: kind: gcp_service_account selector: attached_to_service: wif_pool_bound scope: any - aggregate_as: "SAs and roles bound to principals of WIF pools with updatable providers" + aggregate_as: SAs bound to principals of WIF pools with updatable providers conditions: - - id: matching_binding - description: An IAM binding must exist for a subject, group or mapped attribute the modified provider can assert, and the provider's attribute condition must be satisfiable. - - id: provider_enabled - description: The provider and pool must be enabled. + - id: matching_binding + description: An IAM binding must exist for a subject, group or mapped attribute the modified provider can assert, + and the provider's attribute condition must be satisfiable. + - id: provider_enabled + description: The provider and pool must be enabled. blockers: - - gcp_deny_policy + - 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. - + 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 obtain the privileges of service accounts and roles still bound to principals of disabled or deleted workload identity pools or providers it can restore. + summary: The source can obtain the privileges of service accounts still bound to principals of disabled or deleted + workload identity pools or providers it can restore. requires: any_of: - - - action: iam.googleapis.com/workloadIdentityPoolProviders.undelete - resource: "{target.host_resource}" - - - action: iam.googleapis.com/workloadIdentityPools.update - resource: "{target.host_resource}" - - - action: iam.googleapis.com/workloadIdentityPools.undelete - resource: "{target.host_resource}" + - - action: iam.googleapis.com/workloadIdentityPoolProviders.undelete + resource: '{target.host_resource}' + - - action: iam.googleapis.com/workloadIdentityPools.update + resource: '{target.host_resource}' + - - action: iam.googleapis.com/workloadIdentityPools.undelete + resource: '{target.host_resource}' target: kind: gcp_service_account selector: attached_to_service: wif_pool_bound scope: any - aggregate_as: "SAs and roles bound to principals of restorable WIF pools" + aggregate_as: SAs bound to principals of restorable WIF pools conditions: - - id: residual_trust - description: The restored provider must already accept an identity the source controls and a matching IAM binding must remain. - - id: retention - description: Deleted pools/providers are restorable for approximately 30 days. + - id: residual_trust + description: The restored provider must already accept an identity the source controls and a matching IAM binding + must remain. + - id: retention + description: Deleted pools/providers are restorable for approximately 30 days. blockers: - - gcp_deny_policy + - 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. - + 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 obtain the privileges of service accounts that grant impersonation to principals of workforce pools whose providers or state it controls. + summary: The source can obtain the privileges of service accounts that grant impersonation to principals of workforce + pools whose providers or state it controls. requires: any_of: - - - action: iam.googleapis.com/workforcePoolProviders.create - resource: "{target.host_resource}" - - - action: iam.googleapis.com/workforcePoolProviders.update - resource: "{target.host_resource}" - - - action: iam.googleapis.com/workforcePoolProviders.undelete - resource: "{target.host_resource}" - - - action: iam.googleapis.com/workforcePools.update - resource: "{target.host_resource}" - - - action: iam.googleapis.com/workforcePools.undelete - resource: "{target.host_resource}" + - - action: iam.googleapis.com/workforcePoolProviders.create + resource: '{target.host_resource}' + - - action: iam.googleapis.com/workforcePoolProviders.update + resource: '{target.host_resource}' + - - action: iam.googleapis.com/workforcePoolProviders.undelete + resource: '{target.host_resource}' + - - action: iam.googleapis.com/workforcePools.update + resource: '{target.host_resource}' + - - action: iam.googleapis.com/workforcePools.undelete + resource: '{target.host_resource}' target: kind: gcp_service_account selector: attached_to_service: workforce_pool_bound scope: any - aggregate_as: "SAs and roles bound to principals of controllable workforce pools" + aggregate_as: SAs bound to principals of controllable workforce pools conditions: - - id: matching_binding - description: An existing IAM binding must cover a workforce principal, group, attribute or pool-wide set that the created, changed or restored provider can assert; no target policy is changed. - - 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. + - id: matching_binding + description: An existing IAM binding must cover a workforce principal, group, attribute or pool-wide set that + the created, changed or restored provider can assert; no target policy is changed. + - 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 + - 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. + 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 usually receive roles directly; those direct grants need the proposed gcp_federated_principal kind. Only service accounts that grant token creation or workloadIdentityUser to workforce principals are reachable today. + - 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 usually receive roles directly; those direct + grants need the proposed gcp_federated_principal kind. Only service accounts that grant token creation or workloadIdentityUser + to workforce principals are reachable today. diff --git a/src/privilege-escalation-paths/gcp/workflows.yaml b/src/privilege-escalation-paths/gcp/workflows.yaml index de306a6a18..b6adad6ed9 100644 --- a/src/privilege-escalation-paths/gcp/workflows.yaml +++ b/src/privilege-escalation-paths/gcp/workflows.yaml @@ -130,3 +130,65 @@ 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-workflow-input-effect-2 + provider: gcp + service: workflows + title: Invoke privileged existing workflow with chosen parameters + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsexecutionscreate--invoke-an-existing-privileged-workflow + source_revision: 0b36331 + summary: Invoke privileged existing workflow with chosen parameters; emit only when exact source, target, and + prerequisite evidence is verified. + requires: + all_of: + - action: workflows.executions.create + resource: '*' + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-workflow-input-effect-2 + scope: any + outcome: scope_control + aggregate_as: Invoke privileged existing workflow with chosen parameters + conditions: + - id: exact_verified_prerequisites + description: The exact source, target and exploit-enabling facts must be verified; missing facts evaluate UNKNOWN. + confidence: conditional + severity: high + mitigation: Restrict the stated permission and remove the exploitable trust or configuration. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowsexecutionscreate--invoke-an-existing-privileged-workflow + source_kind: + - gcp_user + - gcp_service_account + source_selector: {} +- id: gcp-workflow-input-effect-3 + provider: gcp + service: workflows + title: Inject callback data into paused privileged execution + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowscallbackssend--inject-data-into-a-paused-privileged-execution + source_revision: 0b36331 + summary: Inject callback data into paused privileged execution; emit only when exact source, target, and prerequisite + evidence is verified. + requires: + all_of: + - action: workflows.callbacks.send + resource: '*' + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-workflow-input-effect-3 + scope: any + outcome: scope_control + aggregate_as: Inject callback data into paused privileged execution + conditions: + - id: exact_verified_prerequisites + description: The exact source, target and exploit-enabling facts must be verified; missing facts evaluate UNKNOWN. + confidence: conditional + severity: high + mitigation: Restrict the stated permission and remove the exploitable trust or configuration. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-workflows-privesc.md#workflowscallbackssend--inject-data-into-a-paused-privileged-execution + source_kind: + - gcp_user + - gcp_service_account + source_selector: {} diff --git a/src/privilege-escalation-paths/gcp/workspace.yaml b/src/privilege-escalation-paths/gcp/workspace.yaml index f304d08851..dc6af37d01 100644 --- a/src/privilege-escalation-paths/gcp/workspace.yaml +++ b/src/privilege-escalation-paths/gcp/workspace.yaml @@ -193,7 +193,8 @@ service: integrations title: Publish an Application Integration version with a chosen run-as service account source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#runasserviceaccount--author--publish-an-integration-that-runs-as-an-arbitrary-sa - summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, by authoring, publishing and running an integration version configured to run as that account. + summary: The source can obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, + by authoring, publishing and running an integration version configured to run as that account. requires: all_of: - action: integrations.integrationVersions.create @@ -203,11 +204,6 @@ resource: '*' - - action: integrations.integrations.deploy resource: '*' - - any_of: - - - action: integrations.integrationVersions.invoke - resource: '*' - - - action: integrations.integrations.invoke - resource: '*' - action: iam.serviceAccounts.actAs resource: '{target.email}' target: @@ -219,16 +215,21 @@ aggregate_as: Service accounts usable as Application Integration run-as SA in {project} conditions: - id: task_level - description: The SA token is used by Connector, REST caller and Cloud Function tasks of the integration (request level). A trigger-level run-as account also lets scheduled or event triggers run the integration without the invoke permission. + description: The SA token is used by Connector, REST caller and Cloud Function tasks of the integration (request + level). A trigger-level run-as account also lets scheduled or event triggers run the integration without the + invoke permission. - id: legacy_behavior - description: Before Google's authorization change, publish did not enforce actAs and unset run-as fell back to the integrations service agent. + description: Before Google's authorization change, publish did not enforce actAs and unset run-as fell back + to the integrations service agent. + - id: execution_trigger + description: Without caller invoke permission, require a deployed scheduled/event trigger or a verified different + principal that invokes the published version; otherwise the path remains UNKNOWN. blockers: - gcp_deny_policy - vpc_sc_perimeter - confidence: derived + confidence: conditional severity: critical mitigation: Grant actAs only on dedicated integration SAs; roles/editor and roles/owner contain both halves. - - id: gcp-workspace-super-admin-org-admin provider: gcp service: resourcemanager @@ -264,7 +265,8 @@ service: integrations title: Read a decrypted Application Integration authentication profile source: src/pentesting-cloud/gcp-security/gcp-to-workspace-pivoting/gcp-application-integration-privesc.md#integrationsauthconfigsget--retrieve-decrypted-credentials - summary: The source can obtain the privileges of the identities whose OAuth tokens or reusable credentials are stored in Application Integration authentication profiles on which it holds integrations.authConfigs.get, limited to the stored scopes. + summary: The source can obtain a Google Workspace user OAuth credential from a known auth config only when its + type and scopes establish that user; external credentials and SA names require separate target modeling. pivot_resource_type: appintegration_auth_config requires: all_of: @@ -278,9 +280,12 @@ aggregate_as: Identities whose credentials are stored in {pivot} conditions: - id: credential_type - description: Only OAuth authorization-code profiles (access and refresh token plus client secret) carry a Google user's identity; token, password and JWT profiles reach the external system they authenticate to, and service-account profiles hold only the SA name and scopes, not a key. + description: Only OAuth authorization-code profiles (access and refresh token plus client secret) carry a Google + user's identity; token, password and JWT profiles reach the external system they authenticate to, and service-account + profiles hold only the SA name and scopes, not a key. - id: google_scopes - description: Workspace impact needs a Google OAuth profile whose user consented to Workspace scopes; the token does not expand scopes or impersonate other users. + description: Workspace impact needs a Google OAuth profile whose user consented to Workspace scopes; the token + does not expand scopes or impersonate other users. - id: known_name description: The auth config name (UUID) must be known; authConfigs.get does not imply list. blockers: @@ -288,8 +293,10 @@ - vpc_sc_perimeter confidence: conditional severity: high - mitigation: Treat integrations.authConfigs.get (included in roles/integrations.integrationViewer) as credential-vault access and prefer run-as service accounts over stored OAuth tokens. + mitigation: Treat integrations.authConfigs.get (included in roles/integrations.integrationViewer) as credential-vault + access and prefer run-as service accounts over stored OAuth tokens. references: - https://docs.cloud.google.com/application-integration/docs/reference/rest/v1/projects.locations.authConfigs/get - https://docs.cloud.google.com/application-integration/docs/configure-authentication-profiles - notes: Modelled like gcp-agentidentity-retrieve-credentials; the GET method returns the decrypted credential. Previously excluded as a plain secret read. + notes: Modelled like gcp-agentidentity-retrieve-credentials; the GET method returns the decrypted credential. + Previously excluded as a plain secret read. diff --git a/src/privilege-escalation-paths/gcp/workstations.yaml b/src/privilege-escalation-paths/gcp/workstations.yaml index eaafd16a83..8dc5b939b0 100644 --- a/src/privilege-escalation-paths/gcp/workstations.yaml +++ b/src/privilege-escalation-paths/gcp/workstations.yaml @@ -83,35 +83,37 @@ 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. + summary: The source can obtain the SA of an existing workstation it can use or whose workstation IAM policy it + controls; config-policy self-grant needs a separate config-to-workstation join. requires: any_of: - - - action: workstations.workstations.use - resource: "{target.host_resource}" - - action: workstations.workstations.start - resource: "{target.host_resource}" - - - action: workstations.workstations.setIamPolicy - resource: "{target.host_resource}" - - - action: workstations.workstationConfigs.setIamPolicy - resource: "{target.host_resource}" + - - action: workstations.workstations.use + resource: '{target.host_resource}' + - - action: workstations.workstations.setIamPolicy + resource: '{target.host_resource}' target: kind: gcp_service_account selector: attached_to_service: workstations_workstation scope: same_project - aggregate_as: "SAs of Cloud Workstations the source can connect to" + 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: 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. + - id: scoped_config_actas + description: If the config sets service-account scopes, users also need actAs on the SA at launch/use time. + - 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. + - id: running_or_startable + description: For the direct use branch the workstation must already be running, or the source must additionally + hold workstations.workstations.start on it. blockers: - - gcp_deny_policy + - 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. - + 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. Config setIamPolicy requires + its own config resource join and a later create/start/use or another user session. - id: gcp-workstations-create-from-existing-config provider: gcp service: workstations @@ -145,3 +147,36 @@ 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. +- id: gcp-audit-s01-39-escape-workstation-container + provider: gcp + service: cloud-workstations + title: Escape workstation container to VM and steal metadata SA token + source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc.md#container-breakout-via-docker-socket-container---vm---project + summary: The source can gain escape workstation container to VM and steal metadata SA token. Host breakout needs + an actual shell plus exposed Docker socket/privileged container and reachable metadata; config-create paths + require different IAM permissions. + requires: + all_of: [] + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-audit-s01-39-escape-workstation-container + scope: any + aggregate_as: workstation VM OS root and attached SA token + conditions: + - id: exact_target_evidence + description: Exclusion calls this already covered by config-create entries, but the page explicitly says a shell + in any accessible workstation plus Docker socket/privileged container suffices with no IAM config-create or + actAs permissions. Missing target evidence evaluates UNKNOWN. + - id: host_configuration + description: An accessible running workstation must expose Docker host control or privileged container access + and a usable metadata SA token. + confidence: conditional + severity: high + mitigation: Restrict the listed permissions and review target trust/consumer configuration. + source_revision: 0b36331 + references: + - https://cloud.hacktricks.wiki/en/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloud-workstations-privesc/#container-breakout-via-docker-socket-container---vm---project + source_kind: + - gcp_user + - gcp_service_account From 4c03ef579e0208b7aa813a3f7af404fdc1dae44c Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Mon, 12 Oct 2026 21:14:19 +0200 Subject: [PATCH 09/17] Integrate GCP post-exploitation and persistence catalog fragments Co-Authored-By: Codex --- .../gcp/_excluded.yaml | 277 ++++++++++++++++-- .../gcp/artifactregistry.yaml | 65 +++- .../gcp/compute.yaml | 70 ----- .../gcp/configcontroller.yaml | 31 +- .../gcp/deploymentmanager.yaml | 33 +++ .../gcp/dialogflow.yaml | 32 ++ .../gcp/workspace.yaml | 41 +++ 7 files changed, 404 insertions(+), 145 deletions(-) create mode 100644 src/privilege-escalation-paths/gcp/dialogflow.yaml diff --git a/src/privilege-escalation-paths/gcp/_excluded.yaml b/src/privilege-escalation-paths/gcp/_excluded.yaml index 8e2c1e400e..2891eeebf9 100644 --- a/src/privilege-escalation-paths/gcp/_excluded.yaml +++ b/src/privilege-escalation-paths/gcp/_excluded.yaml @@ -1180,14 +1180,22 @@ 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. + reason: fetchAccessToken returns only the authenticated Google user's own linked provider OAuth token. This may supply + a new usable external credential within the same user's delegated scopes, but it cannot select another user; external-provider-user + targets and same-user connector joins are unavailable. + source_revision: 0b36331 - 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.' + reason: fetchReadToken returns a time-limited provider credential for the linked repository. The catalog lacks an external + SCM repository authority target and a link-to-provider-rights join; no GCP principal or authority outside the link + follows. + source_revision: 0b36331 - 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). + reason: The provider write token grants a distinct external SCM foothold even without a pipeline. gcp-developerconnect-readwrite-token-pipeline-poison + covers only a repository that automatically feeds a privileged GCP consumer; external repository authority needs + its own target model. + source_revision: 0b36331 - 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.' @@ -1215,8 +1223,11 @@ 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. + reason: A retained header, Basic credential, or third-party OAuth client secret can be sent to a changed endpoint after + a matching conversation. The exact active route, auth material, reachable endpoint, later invocation, and external + credential target are not in the snapshot; Google-SA token variants remain excluded for the page-stated audience/actAs + restrictions. + source_revision: 0b36331 - 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. @@ -1257,7 +1268,10 @@ 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.' + reason: Manifest get may disclose an author-embedded reusable credential, but its presence, validity, target principal, + and permissions depend on the actual unredacted manifest bytes. A read-only manifest/credential-target inventory + is required; absent it the target is UNKNOWN. + source_revision: 0b36331 - 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.' @@ -1275,7 +1289,9 @@ 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. + reason: The section allows sourceContents to contain a hardcoded credential, but presence, usability and downstream + identity are content facts absent from the configuration snapshot; the service-account email alone is reconnaissance. + source_revision: 0b36331 - 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.' @@ -1284,7 +1300,8 @@ 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. + reason: Repository history and review diffs may contain valid credentials. Their identity, validity, and downstream + permissions are runtime content and cannot be inferred from repository read permission alone. - 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. @@ -1424,7 +1441,8 @@ 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. + reason: Repository history may contain valid committed credentials. Their identity, validity, and downstream permissions + are runtime content and cannot be inferred from source.repos.get alone. - 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. @@ -1537,10 +1555,16 @@ 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. + reason: ImpersonateQuery/Mutation can run a predefined connector operation under a chosen end-user sub/claims, granting + that application-user data context. It does not grant GCP IAM; the evaluator lacks an application-user target and + connector-operation auth join. + source_revision: 0b36331 - 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. + technique: Admin GraphQL mutation of app privilege fields + reason: executeGraphql has admin data authority and can mutate an application role field where the particular schema + and application code give that field privilege meaning. The example role=admin mutation does not prove such a field + or its runtime effect in every service; application schema and authorization semantics are required. + source_revision: 0b36331 - 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. @@ -1570,7 +1594,10 @@ 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. + reason: Import can overwrite role/isAdmin entity fields, but an application privilege is gained only if a particular + application maps those keys to an account and trusts them after import. That content-to-authority mapping and subsequent + behavior are not collected. + source_revision: 0b36331 - 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. @@ -1612,7 +1639,9 @@ 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. + reason: A supported sink connector can copy records from topics that the Connect service agent may consume to a destination + where it may publish. This is data exfiltration through a server-side pipeline; no connector credential or second + principal is gained. - 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. @@ -1646,7 +1675,9 @@ 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. + reason: Importing attacker-known material and promoting it can escrow future ciphertext for offline decryption; destructive + old-version steps also cause availability loss. Whether any future ciphertext is encrypted under that version is + runtime data evidence, and neither effect yields another principal. - 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. @@ -1662,7 +1693,9 @@ 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. + reason: Updating an NFS export policy can widen client CIDRs and file access if the client can route to the volume + and Unix file permissions allow it. This is data-plane file access, not monitoring control or impersonation of another + principal. - 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. @@ -2052,8 +2085,9 @@ 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. + reason: Native CREATE ROLE/GRANT requires an already-authorized SQL session and creates database authority; SQL session + privileges and PostgreSQL catalog objects are absent from the GCP IAM snapshot. + source_revision: 0b36331 - 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 @@ -2091,8 +2125,9 @@ 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: 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. + reason: A dataset ACL can grant a controlled principal new dataset rights. The current evaluator has no dataset-role + target or fine-grained ACL-mode branching. + source_revision: 0b36331 - 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. @@ -2113,14 +2148,17 @@ 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. + reason: A BMS SSH key can grant host login, but no BMS host-principal target or attacker network reachability fact + exists in the current evaluator. + source_revision: 0b36331 - 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. + reason: An NFS CIDR entry may grant share read/write to a reachable attacker client; the current evaluator has no NFS + data-plane target or BMS network-client reachability fact. + source_revision: 0b36331 - 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. @@ -2138,8 +2176,9 @@ 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. + reason: A registration IAM binding grants new registration-scoped DNS/contact/management rights. The current evaluator + has no registration-role target; Workspace recovery is a separate path. + source_revision: 0b36331 - 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 @@ -2259,14 +2298,20 @@ 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. + reason: CreateKey returns a project API-key credential accepted by enabled key-accepting APIs. The current principal-edge + schema has no API-key target or API capability selector. + source_revision: 0b36331 - 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. + reason: Undelete restores an existing API-key credential only if the key is recoverable and its string is known or + separately retrievable. The current principal-edge schema has no API-key target. + source_revision: 0b36331 - 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. + technique: privateca.certificateAuthorities.create + attacker-controlled signing key — retain a trusted subordinate + CA credential + reason: A retained subordinate KMS signing key can issue certificates under a trusted CA chain. The current evaluator + has no CA authority target or relying-party trust and name-constraint join. + source_revision: 0b36331 - 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 @@ -2398,3 +2443,173 @@ technique: App Engine request-log cross-tenant leak reason: 'Historical managed-service flaw: the cited page states Google fixed the affected service; current IAM/configuration cannot imply the old authorization or isolation bypass.' + +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-functions-post-exploitation.md#read-managed-source-bucket-objects-directly + technique: Read managed source-bucket objects directly + reason: storage.objects.get can recover a retained function archive, but impersonation requires a reusable, unexpired + credential embedded in its source bytes and a known owner. Archive existence, contents, and credential validity are + not determined by source-bucket IAM. + +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-run-post-exploitation.md#access-the-images + technique: Access the images + reason: Registry pull access yields image bytes. An identity pivot requires a reusable credential actually embedded + in image layers and still valid; the image digest and repository permissions do not establish that fact or identify + the target. + +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-shell-post-exploitation.md#recover-the-authorized-users-session-access-token + technique: Recover the authorized user's session access token + reason: Recovering the user token requires code or shell execution as that Unix user in a running Cloud Shell session + after the user authorized tools. Session state and the locally supplied short-lived token are runtime host facts + absent from the cloud IAM snapshot. + +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-composer-post-exploitation.md#export-dags-data-and-plugins + technique: Export DAGs, data, and plugins + reason: Exporting Composer bucket objects yields DAG, plugin, or data bytes. A privilege pivot requires an unexpired + credential embedded in those files and its principal mapping; bucket permissions do not establish either fact. + +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#read-literal-configuration-from-compute-metadata + technique: Read literal configuration from Compute metadata + reason: Compute get/list can expose literal metadata. A privilege pivot requires a valid password, key, or token in + an actual metadata value and a mapped target identity; free-form metadata may contain none. + +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#export--inspect-images-locally + technique: Export & Inspect Images locally + reason: Image export yields filesystem bytes. Identity gain requires a live credential actually stored on the exported + image and a principal to which it belongs; export IAM and image metadata do not prove that content fact. + +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#export--inspect-snapshots--disks-locally + technique: Export & Inspect Snapshots & Disks locally + reason: Snapshot/disk conversion and export yield filesystem bytes. Credential gain requires a live credential on the + source volume and a mapped owner; resource permissions and snapshot inventory cannot prove either. + +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#recover-deleted-standard-snapshots-before-expiry + technique: Recover deleted standard snapshots before expiry + reason: Recovering a standard snapshot yields retained disk data. An identity edge requires an unexpired credential + in the deleted filesystem and a known owner; retention and recoverability alone cannot establish this. + +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#inspect-an-image-creating-a-vm + technique: Inspect an Image creating a VM + reason: Booting an image for inspection exposes guest filesystem data only if the source can access the inspection + VM. A credential pivot needs a live secret in the image bytes; the attached-SA code-execution route is already gcp-compute-instances-create-actas. + +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-compute-post-exploitation.md#inspect-a-snapshotdisk-attaching-it-to-a-vm + technique: Inspect a Snapshot/Disk attaching it to a VM + reason: Attaching a compatible disk to an inspection VM exposes filesystem bytes. A privilege pivot requires an unexpired + credential on that disk and its principal mapping, neither inferable from attach/use permissions. + +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-config-controller-post-exploitation.md#kubernetes-secret-read--recover-credentials-supplied-to-or-generated-by-config-connector-and-config-sync + technique: Kubernetes Secret read — recover credentials supplied to or generated by Config Connector and Config Sync + reason: A Config Connector or Config Sync Secret may contain an SA private key, DB password, or Git token, but its + actual bytes, credential type, target principal, and current validity are needed. KSA token Secrets are separately + modeled by gcp-container-secrets-read-ksa-token-secret and K8s RBAC entries. + +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-contact-center-insights-post-exploitation.md#read-stored-transcripts-and-analysis-results + technique: Read stored transcripts and analysis results + reason: Conversation and analysis reads return stored content. A privilege pivot requires an unredacted reusable credential + in an actual transcript or result plus its still-valid target identity; list/get permission does not prove those + facts. + +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-ids-post-exploitation.md#route-selected-vpc-flows-through-an-attacker-controlled-intercept-service + technique: Route selected VPC flows through an attacker-controlled intercept service + reason: Interception can reveal a second principal only if a live selected flow carries a usable credential in plaintext + or in traffic the appliance can decrypt; firewall and endpoint configuration cannot identify that runtime payload + or credential owner. + +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-ids-post-exploitation.md#mirror-selected-vpc-traffic-to-an-attacker-controlled-collector-through-nsi + technique: Mirror selected VPC traffic to an attacker-controlled collector through NSI + reason: Mirroring can reveal a second principal only if a selected live flow carries a usable credential visible to + the collector; configuration cannot prove the payload, decryption, or credential owner. + +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-parameter-manager-post-exploitation.md#parameter-poisoning--inject-configsecret-refs-consumed-by-workloads + technique: Parameter poisoning — inject config/secret-refs consumed by workloads + reason: The config-poisoning branch depends on a runtime workload consuming the modified version and on how that application + interprets the value. The __REF__/render branch returns arbitrary Secret Manager content; only inspection of the + secret bytes can establish whether they are a usable credential for a named second principal. + +- source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-workflows-post-exploitation.md#read-execution-arguments-results-and-detailed-step-variables + source_revision: 0b36331 + technique: Read credential from execution records or detailed history; List FULL executions to recover recorded credentials + reason: Execution arguments, results and DETAILED step values may contain a usable credential, but retained content, + redaction and credential validity are runtime facts. FULL execution listing can reveal a credential only if retained + argument/result content contains an unredacted usable secret. + +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-artifact-registry-persistence.md#upstream-credential-tamper--disclosure---remote-username----remote-password-secret-version + source_revision: 0b36331 + technique: Locate upstream secret and read backing credential + reason: Repository metadata reveals only a Secret Manager version path; the password value, usability and distinct + authority require reading secret content. + +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-beyondcorp-persistence.md#retain-service-level-access-with-gateway-and-application-iam-bindings + source_revision: 0b36331 + technique: Grant controlled principal BeyondCorp gateway/application access; Create and grant new BeyondCorp application + reason: Gateway and application bindings permit browser routing, but upstream application authentication, Chrome licensing + and a reachable gateway are not proved by IAM configuration. A newly created BeyondCorp application does not bypass + upstream authentication; usable app privileges depend on gateway route, licensed client and backend access. + +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-functions-persistence.md#expose-an-http-backdoor + source_revision: 0b36331 + technique: Expose attacker-controlled function for unauthenticated privileged execution + reason: An allUsers invoker binding grants only invocation; SA privilege gain requires a backdoored handler whose behavior + cannot be established from service IAM. + +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-run-persistence.md#publicly-accessible-service + source_revision: 0b36331 + technique: Grant allUsers invocation of backdoored Cloud Run service + reason: An allUsers invoker binding grants only invocation; SA privilege gain requires a backdoored handler whose behavior + cannot be established from service IAM. + +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-scheduler-persistence.md#pubsub-and-app-engine-jobs---identity-free-dormant-triggers + source_revision: 0b36331 + technique: Scheduler trigger for existing privileged App Engine handler or backdoored function + reason: A Pub/Sub/App Engine job only sends a chosen request; privileged behavior depends on an existing handler and + task payload, not job creation alone. + +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-shell-persistence.md#backdoor-bashrc + technique: Victim Cloud Shell .bashrc callback and active user credential use + reason: Code executes as the victim only if the attacker has already written that specific user's private Cloud Shell + home and the victim later opens an interactive shell; project IAM configuration has no cross-user home mapping or + write grant to evaluate. + +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-shell-persistence.md#backdoor-customize_environment + technique: Root Cloud Shell boot callback and active-user credential use + reason: Root code execution in the ephemeral Cloud Shell VM requires a prior write to that victim's private home and + a later VM boot; whether the victim has authorized Google API access is a separate session fact, absent from project + configuration. + +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-shell-persistence.md#authorization-and-tokens + technique: Read active gcloud/ADC access tokens after Cloud Shell code execution + reason: The active gcloud or ADC token is readable only after victim-session code execution and, when required, browser + authorization; token-cache state and consent are runtime per-user facts outside the project snapshot. + +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-cloud-sql-persistence.md#sql-server-contained-database-authentication--hidden-portable-db-user + technique: Enable contained authentication and create portable SQL Server DB user + reason: The flag does not create a login. A SQL Server principal with CREATE USER rights must issue an in-database + statement; the resulting contained database identity is outside the catalog's Google IAM target kinds and is not + visible in Cloud SQL users.list. + +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-dataflow-persistence.md#invisible-persistence-in-built-container + technique: Build-time environment-variable injection executes as Flex Template builder + reason: The build-time callback depends on attacker control of a particular build invocation's --env values and on + the selected base/tool actually executing the hook. Neither the source of those values nor that runtime tool behavior + is established by a configuration snapshot; a caller who can submit arbitrary Cloud Build steps is already covered + by gcp-cloudbuild-builds-create. + +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-compute-persistence.md#poison-a-consumed-custom-image-family + technique: Create poisoned latest image in consumed family + reason: The source disk, image, or snapshot must be controlled by the caller and usable via its exact useReadOnly permission, + then a later VM must boot the new family image. The current rule cannot bind source-resource permission and filesystem + control to the family-consumer target; keep this path out of reachability until those facts are represented. + +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-compute-privesc/README.md#computeinstancegroupmanagersupdate--templatevm-permissions--hijack-an-existing-managed-instance-group + technique: Create template and repoint existing MIG + reason: A selected existing MIG must accept a new template whose get/useReadOnly and every referenced image, disk, + network, subnet and metadata permission is satisfied, and its Google APIs Service Agent must be able to use the attached + SA. The current rule cannot bind all template references and permissions to that MIG; suppress the edge until these + joins are machine checked. + +- source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-config-controller-persistence.md#durable-instance-iam-binding-krmapihostingkrmapihostssetiampolicy + technique: Instance IAM binding to re-enter KCC + reason: An instance-level roles/krmapihosting.admin binding is a persistent re-entry grant. It reaches the KCC identity + only if that granted principal can also create or update KCC custom resources on the same instance (through container.thirdPartyObjects + or in-cluster RBAC), with a verified instance-to-cluster identity join. That additional grant is not checked by the + current entry. diff --git a/src/privilege-escalation-paths/gcp/artifactregistry.yaml b/src/privilege-escalation-paths/gcp/artifactregistry.yaml index 048274ea3c..158814f235 100644 --- a/src/privilege-escalation-paths/gcp/artifactregistry.yaml +++ b/src/privilege-escalation-paths/gcp/artifactregistry.yaml @@ -108,33 +108,38 @@ title: Create the missing gcr.io-named repository to claim a redirected legacy namespace source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-artifact-registry-persistence.md#squat-the-legacy-gcrio-namespace-as-a-permanent-backdoor---artifactregistryrepositoriescreate source_revision: 171e422 - summary: The source can obtain the privileges of the run-as service accounts of workloads that still pull gcr.io references of projects where it holds artifactregistry.repositories.create. + summary: The source can obtain the privileges of run-as service accounts of workloads pulling mutable gcr.io references + only when it can both create the missing host-named repository and push a malicious artifact into it. requires: all_of: - - action: artifactregistry.repositories.create - resource: "*" + - action: artifactregistry.repositories.create + resource: '*' + - action: artifactregistry.repositories.uploadArtifacts + resource: '*' target: kind: gcp_service_account selector: attached_to_service: artifact_consumer gcp_sa_in_scope_of_permission: true + gcp_challenge_fact: gcp-artifactregistry-gcrio-namespace-squat scope: same_project - aggregate_as: "Run-as SAs of workloads pulling gcr.io references of {project}" + aggregate_as: Run-as SAs of workloads pulling gcr.io references of {project} conditions: - - id: redirection_enabled - description: The project must have gcr.io redirection to Artifact Registry enabled and the host-named repository (gcr.io, us.gcr.io, eu.gcr.io, asia.gcr.io) must not exist yet. - - id: legacy_consumers - description: Workloads must still reference gcr.io//... by tag and repull after the squat. - - id: push_after_create - description: Pushing into the new repository additionally needs uploadArtifacts (the creator normally holds it). + - id: redirection_enabled + description: The project must have gcr.io redirection to Artifact Registry enabled and the host-named repository + (gcr.io, us.gcr.io, eu.gcr.io, asia.gcr.io) must not exist yet. + - id: legacy_consumers + description: Workloads must still reference gcr.io//... by tag and repull after the squat. + - id: same_new_repository_push + description: The uploadArtifacts grant must cover the specific newly created gcr.io-named repository; absent exact + same-repository evidence remains UNKNOWN. blockers: - - gcp_deny_policy - - vpc_sc_perimeter + - gcp_deny_policy + - vpc_sc_perimeter confidence: conditional severity: high - mitigation: Create the gcr.io-named repositories in every migrated project and restrict artifactregistry.repositories.create. + mitigation: Pre-create migrated gcr.io repositories and restrict both artifactregistry.repositories.create and uploadArtifacts. notes: roles/artifactregistry.createOnPushWriter can create the repository implicitly on first push. - - id: gcp-artifactregistry-repositories-update-dependency-confusion provider: gcp service: artifactregistry @@ -233,3 +238,35 @@ use. references: - src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-artifact-registry-post-exploitation.md#artifactregistryrepositoriesexportartifacts--copy-an-artifact-to-cloud-storage + +- id: gcp-create-attacker-upstream-remote-repository-consumed-directly + provider: gcp + service: artifact-registry + title: Create attacker-upstream remote repository consumed directly + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-artifact-registry-persistence.md#remote-repository-pointing-at-an-attacker-controlled-upstream-url + source_revision: 0b36331 + summary: Code execution as artifact-consuming workload identity. + requires: + all_of: + - action: artifactregistry.repositories.create + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-create-attacker-upstream-remote-repository-consumed-directly + attached_to_service: artifact_consumer + scope: any + aggregate_as: gcp_service_account + conditions: + - id: exact_evidence + description: Draft only. Emit UNKNOWN unless every target, permission, and stated precondition is supported by collected + evidence. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict the listed permissions and review affected resource state. + notes: Unenabled draft. The bounded authority kind and gcp_challenge_fact are schema-valid placeholders; implement + the feature before activation. + references: + - https://cloud.google.com/artifact-registry/docs/repositories/virtual-overview diff --git a/src/privilege-escalation-paths/gcp/compute.yaml b/src/privilege-escalation-paths/gcp/compute.yaml index 656c167cb5..cdeb56954d 100644 --- a/src/privilege-escalation-paths/gcp/compute.yaml +++ b/src/privilege-escalation-paths/gcp/compute.yaml @@ -294,76 +294,6 @@ 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. -- id: gcp-compute-instancegroupmanagers-update-template - provider: gcp - 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: The source can obtain the privileges of any service account in the project on which the project's Google APIs Service Agent holds iam.serviceAccounts.actAs (every project service account by default); the caller itself needs no actAs. - requires: - all_of: - - action: compute.instanceGroupManagers.update - resource: "*" - - action: compute.instanceTemplates.create - resource: "*" - target: - kind: gcp_service_account - selector: - gcp_actas_granted_to_service_agent: cloudservices - 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: Needs an existing MIG covered by compute.instanceGroupManagers.update; the new template only applies to VMs created after a recreate/apply-updates/proactive update or self-healing. - - id: supporting_permissions - description: Setting the template can also require instanceTemplates get/useReadOnly, compute.instances.create, compute.disks.create, compute.images.useReadOnly, compute.instances.setMetadata and compute.subnetworks.use. - - id: service_agent_actas - description: Compute validates that the Google APIs Service Agent (not the caller) holds Service Account User on the template's SA; it has roles/editor by default. - 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: Also reaches the SA already attached to the MIG's current template. Durable through self-healing and scale-out. - -- id: gcp-compute-images-create-family-poison - provider: gcp - service: compute - title: Publish a newer image into an image family consumed by instance templates - source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-compute-persistence.md#poison-a-consumed-custom-image-family - source_revision: 171e422 - summary: The source can obtain the privileges of the service accounts of VMs later created from image families it can publish to. - requires: - all_of: - - action: compute.images.create - resource: "{target.image_family_project}" - target: - kind: gcp_service_account - selector: - gcp_image_family_consumer: true - scope: any - aggregate_as: "SAs of workloads booting from image families the source can publish to" - conditions: - - id: later_boot - description: Only VMs created or recreated after the publish are affected (MIG scale-out, autohealing, rebuilds); running VMs and templates pinned to a concrete image are not. - - id: controlled_image_source - description: The source also needs read use of an image source it controls (compute.disks.useReadOnly, compute.images.useReadOnly or compute.snapshots.useReadOnly), usually in its own project; CMEK and source constraints must be satisfied. - - id: vm_scopes - description: The obtained token is bounded by the access scopes assigned to each new VM. - blockers: - - gcp_deny_policy - - id: org_policy_constraint - constraint: compute.trustedImageProjects - confidence: conditional - severity: high - mitigation: Pin concrete image names in instance templates, restrict compute.images.create in image projects and enforce compute.trustedImageProjects. - notes: Targets are SAs of collected instance templates whose boot disk sourceImage is projects/

/global/images/family/; MIG-only consumers resolve through their template. - id: gcp-gke-pod-node-metadata-token provider: gcp service: container diff --git a/src/privilege-escalation-paths/gcp/configcontroller.yaml b/src/privilege-escalation-paths/gcp/configcontroller.yaml index 3ab6dcf315..e903f0f64d 100644 --- a/src/privilege-escalation-paths/gcp/configcontroller.yaml +++ b/src/privilege-escalation-paths/gcp/configcontroller.yaml @@ -49,36 +49,7 @@ notes: The reach is bounded by the Config Connector identity's own IAM permissions; the reconciled API calls are attributed to that identity. Any KCC resource (IAMPolicyMember, IAMServiceAccountKey, compute instances) is a deputy for it. -- id: gcp-configcontroller-krmapihosts-setiampolicy - provider: gcp - service: configcontroller - title: Self-grant Config Controller instance admin and act through Config Connector - source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-config-controller-persistence.md#durable-instance-iam-binding-krmapihostingkrmapihostssetiampolicy - source_revision: 171e422 - summary: The source can obtain the privileges of the Config Connector identity of Config Controller instances whose instance IAM policy it can write, by granting itself roles/krmapihosting.admin and writing KCC resources. - requires: - all_of: - - action: krmapihosting.krmApiHosts.setIamPolicy - resource: "{target.host_resource}" - target: - kind: gcp_service_account - selector: - attached_to_service: config_connector_identity - scope: any - aggregate_as: "Config Connector identities of Config Controller instances whose IAM policy the source controls" - conditions: - - id: instance_admin_gives_kcc_write - description: HackTricks states roles/krmapihosting.admin on the instance yields full KCC access; whether it alone grants Kubernetes write on KCC resources (vs. container.thirdPartyObjects.* / in-cluster RBAC) is not confirmed. - - id: api_server_reachable - description: Needs network reachability to the instance's API server. - blockers: - - gcp_deny_policy - confidence: conditional - severity: high - mitigation: Keep krmapihosting.krmApiHosts.setIamPolicy to administrators and review instance-level IAM policies. - references: - - https://cloud.google.com/kubernetes-engine/enterprise/config-controller/docs/access-control - notes: Two-hop path (instance IAM grant, then gcp-configcontroller-kcc-resource-write); documented on the persistence page at 171e422. + - id: gcp-kcc-k8s-rbac-iam-member provider: gcp service: configcontroller diff --git a/src/privilege-escalation-paths/gcp/deploymentmanager.yaml b/src/privilege-escalation-paths/gcp/deploymentmanager.yaml index 893eb3a657..8782e75390 100644 --- a/src/privilege-escalation-paths/gcp/deploymentmanager.yaml +++ b/src/privilege-escalation-paths/gcp/deploymentmanager.yaml @@ -101,3 +101,36 @@ mitigation: Restrict deploymentmanager.deployments.setIamPolicy (Owner, Deployment Manager Admin, Security Admin). references: - https://docs.cloud.google.com/deployment-manager/docs/access-control + +- id: gcp-pa-s03-1-deploymentmanager + provider: gcp + service: deploymentmanager + title: Recover a second identity credential from a Deployment Manager manifest + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-deployment-manager-post-exploitation.md#deploymentmanagermanifestsget--discovery-permissions--recover-configuration-and-unredacted-credentials + source_revision: 0b36331 + summary: A manifest read may disclose a usable credential for a separately identified principal. + requires: + all_of: + - action: deploymentmanager.manifests.get + resource: '*' + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-pa-s03-1-deploymentmanager + scope: any + aggregate_as: Exact externally verified target for Recover a second identity credential from a Deployment Manager + manifest + conditions: + - id: exact_verified_prerequisites + description: Only a safely verified unredacted manifest credential with an exact, valid target identity yields a + conditional path. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict deploymentmanager.manifests.get to trusted operators and remove or narrow the underlying delegated + credential or operation. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-deployment-manager-post-exploitation.md + notes: Schema-valid provisional draft only. Requires credential-target inventory and exact source-to-manifest-to-target + join. Missing joined facts must evaluate UNKNOWN; do not emit an edge from permission alone. diff --git a/src/privilege-escalation-paths/gcp/dialogflow.yaml b/src/privilege-escalation-paths/gcp/dialogflow.yaml new file mode 100644 index 0000000000..eeac494a3c --- /dev/null +++ b/src/privilege-escalation-paths/gcp/dialogflow.yaml @@ -0,0 +1,32 @@ +# GCP Dialogflow credential routes. The required collector fact is not yet available. +- id: gcp-pa-s03-4-dialogflow + provider: gcp + service: dialogflow + title: Redirect a routed webhook retaining an external credential + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dialogflow-post-exploitation.md#dialogflowwebhooksupdate--redirect-retained-external-authentication-material + source_revision: 0b36331 + summary: Changing a routed webhook endpoint may disclose its retained external authentication material. + requires: + all_of: + - action: dialogflow.webhooks.update + resource: '*' + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-pa-s03-4-dialogflow + scope: any + aggregate_as: Exact externally verified target for Redirect a routed webhook retaining an external credential + conditions: + - id: exact_verified_prerequisites + description: A routed invocation reaches an allowed attacker endpoint while a valid reusable external credential + remains attached. + blockers: + - gcp_deny_policy + confidence: conditional + severity: high + mitigation: Restrict dialogflow.webhooks.update to trusted operators and remove or narrow the underlying delegated + credential or operation. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-dialogflow-post-exploitation.md + notes: Schema-valid provisional draft only. Needs external credential target kind as well as collector facts; future + invocation is conditional. Missing joined facts must evaluate UNKNOWN; do not emit an edge from permission alone. diff --git a/src/privilege-escalation-paths/gcp/workspace.yaml b/src/privilege-escalation-paths/gcp/workspace.yaml index dc6af37d01..958ec1292a 100644 --- a/src/privilege-escalation-paths/gcp/workspace.yaml +++ b/src/privilege-escalation-paths/gcp/workspace.yaml @@ -300,3 +300,44 @@ - https://docs.cloud.google.com/application-integration/docs/configure-authentication-profiles notes: Modelled like gcp-agentidentity-retrieve-credentials; the GET method returns the decrypted credential. Previously excluded as a plain secret read. + +- id: gcp-dns-managedzones-setiampolicy-workspace-admin-recovery + provider: gcp + service: dns + title: Self-grant DNS record-write permission on a Workspace domain zone and complete administrator recovery + source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-cloud-dns-post-exploitation.md#scope-boundaries + source_revision: 0b36331 + summary: The source can grant itself record-write authority on a public Cloud DNS zone and use the administrator-recovery + challenge to reach a Workspace super administrator of that domain. + pivot_resource_type: dns_managed_zone + requires: + all_of: + - action: dns.managedZones.setIamPolicy + resource: '{pivot}' + target: + kind: gcp_workspace_user + selector: + attached_to_service: workspace_super_admin_of_zone_domain + scope: any + aggregate_as: Workspace super administrators of domains served by {pivot} + outcome: identity + conditions: + - id: zone_self_grant + description: The source can add itself to a zone-scoped DNS role granting dns.changes.create plus dns.resourceRecordSets.create + or update and then write the challenge record. + - id: public_delegation + description: The zone is the publicly delegated authoritative zone for the Workspace primary domain. + - id: recovery_process + description: A live recovery challenge is available and Google accepts its DNS proof and any additional verification. + blockers: + - gcp_deny_policy + confidence: conditional + severity: critical + mitigation: Restrict dns.managedZones.setIamPolicy on zones serving Workspace primary domains and monitor zone IAM + changes, DNS challenges, and Workspace recovery. + references: + - https://docs.cloud.google.com/dns/docs/zones/iam-per-resource-zones + - https://docs.cloud.google.com/dns/docs/access-control + - https://knowledge.workspace.google.com/admin/users/recovering-administrator-access-to-your-account + notes: Distinct from gcp-workspace-cloud-dns-admin-recovery, which requires record-write permissions initially; this + path obtains those permissions through a zone IAM self-grant. From 802281f15fc59a6ff95bf38fe015c7ad125e2c8a Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Mon, 12 Oct 2026 21:17:50 +0200 Subject: [PATCH 10/17] Integrate verified GCP catalog fragments Co-Authored-By: Codex --- .../gcp/_excluded.yaml | 190 ++++++++++++++---- .../gcp/cloudscheduler.yaml | 69 ------- .../gcp/datafusion.yaml | 39 ---- .../gcp/deploymentmanager.yaml | 31 +++ .../gcp/eventarc.yaml | 57 ++++-- .../gcp/monitoring.yaml | 33 +++ .../gcp/privatecatalog.yaml | 32 +++ .../gcp/workflows.yaml | 61 ++++++ .../gcp/workspace.yaml | 33 +++ 9 files changed, 374 insertions(+), 171 deletions(-) create mode 100644 src/privilege-escalation-paths/gcp/monitoring.yaml diff --git a/src/privilege-escalation-paths/gcp/_excluded.yaml b/src/privilege-escalation-paths/gcp/_excluded.yaml index 2891eeebf9..c67dd39d0d 100644 --- a/src/privilege-escalation-paths/gcp/_excluded.yaml +++ b/src/privilege-escalation-paths/gcp/_excluded.yaml @@ -677,7 +677,11 @@ reason: "Grants only Access Context Manager admin on the policy (guardrail control); no IAM principal or project role is reached." - 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: "Data access to a shared dataset/topic; no identity." + reason: Subscription can newly authorize cross-project reads of the objects intentionally published by a + listing. The current catalog lacks a data-resource target and listing-to-source join; a sound edge also + needs listing type, subscribability, destination creation and effective linked-resource read permissions, + and commercial, regional, restricted-export and VPC-SC constraints. It does not confer the publisher's + IAM identity or unrestricted source-data access. - 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: "Data access under clean-room rules; no identity." @@ -1063,7 +1067,11 @@ 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). + reason: Config creation plus actAs and gateway deployment can deliver a Google-signed audience-bound ID token + asserting the chosen SA. This can confer access to a relying service that trusts both audience and SA, + but it is not a general Google API OAuth token. The current SA target means general impersonation and would + be a false positive. A sound edge requires an audience-bound assertion target, exact relying-service trust + and gateway invocation facts, none represented here. - 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. @@ -1081,7 +1089,9 @@ 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). + reason: Same audience-bound ID-token primitive as the API Gateway post-exploitation heading; requires a relying + service trusting the selected audience and SA. Do not model it as general SA impersonation or an OAuth + access token. - 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." @@ -1180,21 +1190,21 @@ 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: fetchAccessToken returns only the authenticated Google user's own linked provider OAuth token. This may supply - a new usable external credential within the same user's delegated scopes, but it cannot select another user; external-provider-user - targets and same-user connector joins are unavailable. + reason: This method is self-only for the Google user, but it can return that user’s linked external-provider + OAuth token. Model only the same user’s provider identity and consented scopes when supported; never another + User record. source_revision: 0b36331 - 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: fetchReadToken returns a time-limited provider credential for the linked repository. The catalog lacks an external - SCM repository authority target and a link-to-provider-rights join; no GCP principal or authority outside the link - follows. + reason: A raw token can authenticate to the named external repository as the linked installation; retain + an exclusion only until external_scm_identity targets and repository-link facts are supported. Do not infer + wider provider scope. source_revision: 0b36331 - 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: The provider write token grants a distinct external SCM foothold even without a pipeline. gcp-developerconnect-readwrite-token-pipeline-poison - covers only a repository that automatically feeds a privileged GCP consumer; external repository authority needs - its own target model. + reason: The pipeline entry covers downstream GCP execution only. A fetched write token independently grants + access to the named external repository when the provider permits writes; model that external identity + when supported. source_revision: 0b36331 - 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 @@ -1223,10 +1233,9 @@ 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: A retained header, Basic credential, or third-party OAuth client secret can be sent to a changed endpoint after - a matching conversation. The exact active route, auth material, reachable endpoint, later invocation, and external - credential target are not in the snapshot; Google-SA token variants remain excluded for the page-stated audience/actAs - restrictions. + reason: Existing generic webhooks can forward retained external headers, Basic credentials, or OAuth client + secrets to a controlled endpoint on a later matching route. Model the external credential target when supported; + Google SA/OIDC variants remain excluded. source_revision: 0b36331 - source: src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-storage-post-exploitation.md#storagebucketsrestore technique: storage.buckets.restore @@ -1267,10 +1276,11 @@ 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: Manifest get may disclose an author-embedded reusable credential, but its presence, validity, target principal, - and permissions depend on the actual unredacted manifest bytes. A read-only manifest/credential-target inventory - is required; absent it the target is UNKNOWN. + technique: deploymentmanager.manifests.get (+ discovery permissions) — recover configuration and unredacted + credentials + reason: Manifest content may expose a reusable credential, but the target identity is unknown until a verified + credential is found. A collected, live GCP service-account key is modeled by gcp-deploymentmanager-manifest-credential; + other secret types remain content-dependent. source_revision: 0b36331 - 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 @@ -1555,15 +1565,14 @@ 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: ImpersonateQuery/Mutation can run a predefined connector operation under a chosen end-user sub/claims, granting - that application-user data context. It does not grant GCP IAM; the evaluator lacks an application-user target and - connector-operation auth join. + reason: Impersonation of a selected application user for a deployed connector operation is an identity gain + in the application plane. Model that user and operation when supported; no GCP IAM identity is implied. source_revision: 0b36331 - 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: Admin GraphQL mutation of app privilege fields - reason: executeGraphql has admin data authority and can mutate an application role field where the particular schema - and application code give that field privilege meaning. The example role=admin mutation does not prove such a field - or its runtime effect in every service; application schema and authorization semantics are required. + reason: executeGraphql grants direct administrator authority over the existing Data Connect service data + plane, including writes and @auth bypass. Model the service-plane admin target when supported; executeGraphqlRead + is read-only and distinct. source_revision: 0b36331 - 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 @@ -1806,7 +1815,9 @@ 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. + reason: The heading gives service context, but connectors.create/update can publish new operations or relax + @auth for a controlled app user. Model only a deployed, newly callable privileged operation; inventory + alone remains excluded. - 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. @@ -2112,9 +2123,11 @@ 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. + technique: Remove or relax a PAB suppressing an existing IAM allow + reason: Project binding removal/update is conditionally modeled by gcp-v3-31-projects-deletepolicybinding-updatepolicybinding-pab-escap. + Folder/organization binding and PAB policy update/delete need exact PAB inventory, owning-organization + bind/unbind authorization as applicable, and recomputation of all remaining boundaries before an existing + allow is treated as effective. - 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; @@ -2140,8 +2153,10 @@ 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. + technique: Create or reset Firestore Enterprise user credentials + reason: Create or reset-password returns a usable Firestore Enterprise database credential. Catalog emission + awaits a database-credential target kind and exact Enterprise userCreds facts; Google IAM service-account + status is irrelevant. - 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 @@ -2200,9 +2215,10 @@ 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. + technique: Receive Monitoring service-agent OIDC tokens + reason: The scheduled token is a real service-agent credential bound to the check audience. Usable escalation + requires an exact endpoint accepting that audience and authorizing this agent; without the receiver and + authorization facts the path is UNKNOWN. - 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 @@ -2253,9 +2269,9 @@ 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. + technique: Continuous sink of audit logs potentially containing bearer tokens + reason: A sink exports log data. Whether it yields a usable bearer/ID token depends on runtime log content + and token validity, which configuration cannot establish; sink creation alone identifies no gained principal. - 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 @@ -2266,8 +2282,9 @@ 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. + reason: Deleting or downgrading a Security Posture deployment can revert preventive Org Policy constraints + as well as detection. The write alone grants no identity; an escalation edge needs the exact enforced constraint, + before/after effective policy, and a separately authorized privilege path that becomes usable. - 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 @@ -2281,9 +2298,9 @@ 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: 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. + technique: Grant controlled Kafka principal topic access + reason: A native Kafka ACL may grant READ or WRITE to a controlled Kafka principal on an exact topic. Catalog + emission awaits Kafka-principal/resource target support and ACL enforcement, authentication and topic facts. - 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 @@ -2613,3 +2630,90 @@ only if that granted principal can also create or update KCC custom resources on the same instance (through container.thirdPartyObjects or in-cluster RBAC), with a verified instance-to-cluster identity join. That additional grant is not checked by the current entry. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-api-gateway-enum.md#enumeration + technique: Read a FULL API config and recover an embedded credential + reason: apigateway.apiconfigs.get exposes the spec, but a credential edge needs the decoded OpenAPI content + to contain a live, usable key or password with authority the reader lacks. Backend URLs and JWT audiences + alone are reconnaissance. The snapshot does not inventory or validate embedded credential content or its + downstream authority. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-apigee-enum.md#enumerate-secrets-credentials-and-tls-material + technique: Read an Apigee KVM value or developer-app consumer credential + reason: A KVM value may be arbitrary data; a developer-app key may be revoked or limited to products the + source can already use. A credential edge requires the actual entry/key value, active status, product authorization, + and proof that its authority exceeds the reader's. These content and authorization facts are not collected. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-apigee-enum.md#enumerate-trace-masks-and-resource-iam + technique: Recover a live credential from an Apigee debug trace + reason: apigee.tracesessions.get only permits reading a trace. An edge requires a captured request actually + containing an unmasked, still-valid credential with privileges the reader lacks. Trace bytes, masking results, + and credential validity are runtime/content facts absent from the configuration snapshot. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-apigee-enum.md#basic-information + technique: Deploy proxy or shared-flow logic to capture request credentials without an SA + reason: Proxy or flow-hook authoring can intercept traffic, but gaining a credential requires a victim request + to traverse the deployed revision with a reusable secret that the proxy logic can observe and the source + cannot already use. Traffic, request content, secret validity, and destination authorization are runtime + facts; deployment writes alone cannot establish a credential edge. SA-bound Google identity paths are already + modeled by gcp-apigee-proxy-deploy-with-sa-actas and gcp-apigee-sharedflow-flowhook-with-sa-actas. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-app-engine-enum.md#enumeration + technique: Read a credential in App Engine version variables or source files + reason: appengine.versions.get reveals envVariables and source object pointers, but source bytes also require + storage.objects.get. Neither permission proves a live secret is present or grants its authority. An edge + needs the actual value or source contents, credential validity, and a downstream principal or resource + mapping; these content facts are not in the configuration snapshot. +- source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-cloudscheduler-privesc.md#cloudschedulerjobscreate-or-update--iamserviceaccountsactas--authenticated-http-dispatch-as-a-service-account + technique: cloudscheduler.jobs.create + iam.serviceAccounts.actAs — one configured OAuth request as a service + account + reason: Creating or updating an HTTP job dispatches configured requests with the selected same-project service + account, but returns neither its OAuth access token nor the downstream response body. The caller obtains + only the effects of requests accepted by a reachable endpoint and authorized by the service account. A + read-only account or an account lacking a useful state-changing operation does not yield an identity or + principal-to-principal edge. Exact privilege gain depends on the chosen method, URI, body, scope, delivery-service-agent + health, downstream IAM and network controls; the current selector cannot prove a self-grant or credential-exfiltration + chain. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cloud-sql-enum.md#password + technique: Unset Cloud SQL MySQL root database password + reason: Root@% can confer database administrator access if it exists, has no password, and the endpoint is + reachable. The catalog models cloud/Kubernetes identity edges, and neither a usable blank database password + nor network login success is established by the read-only configuration snapshot; these require a database + authentication check. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-cloud-workstations-enum.md#enumeration + technique: Other-user credentials on a Cloud Workstations persistent disk + reason: A user with workstation use can read another principal’s credentials only if that workstation’s mounted + persistent home actually contains usable credential content. Workstation IAM and persistentDirectories + metadata do not reveal file contents or credential owner; the configured VM service account is already + covered by gcp-workstations-use-existing-workstation. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-compute-instances-enum/gcp-compute-instance.md#metadata + technique: VM metadata service-account token theft through workload SSRF + reason: 'The token is obtainable only if an application has an exploitable SSRF that reaches metadata.google.internal, + supplies Metadata-Flavor: Google, and exposes the response. VM configuration and caller IAM grants do not + establish that runtime application vulnerability or exfiltration path.' +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-containers-gke-and-composer-enum.md#credentials-outside-workload-identity + technique: Non-workload-identity credentials in GKE pod environments and volumes + reason: An env variable, Secret, CSI volume or container file yields another identity only when its runtime + content is a usable credential and its owner is known. Pod/Secret metadata cannot establish that fact. + Static Google SA keys in Secrets are conditionally covered by k8s-cloud-pivot-secret-static-gcp-sa-key; + KSA token reads have separate entries. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-containers-gke-and-composer-enum.md#external-user-authentication-and-standard-node-access + technique: External OIDC issuer or ClientConfig control for GKE user authentication + reason: Issuer trust and RBAC bindings alone do not show attacker control of the issuer, signing key, or + mutable ClientConfig, nor the exact accepted claims. Those external trust/control facts and effective user/group + mapping are required before another Kubernetes principal’s RBAC rights can be inferred. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-data-fusion-enum.md#access-model-notes + technique: Set Data Fusion namespace design-time service account as pipeline runtime identity + reason: datafusion.namespaces.setServiceAccount selects the design-time identity for Preview/Wrangler/validation + on RBAC-enabled 6.10.0+ instances. Pipeline execution uses the service account from the effective compute + profile, so this permission plus actAs does not give runtime execution as the chosen namespace account; + gcp-datafusion-pipelines-create-execute covers the compute-profile VM SA path. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-dataform-enum.md#enumeration + technique: Read credentials that an author hardcoded in Dataform workspace files + reason: Workspace file reads can disclose a stronger identity only if a file contains a live credential. + The credential content, owner, and validity are not control-plane facts; queryDirectoryContents by itself + merely lists files, and readFile is needed for content. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-dataplex-enum.md#enumeration + technique: Read data-profile topNValues that could include a credential + reason: topNValues are sampled table cells. A privilege edge requires an actual live credential in a sampled + value and its owner/scope; scan metadata and dataplex.datascans.getData alone cannot establish either. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-filestore-enum.md#enumeration + technique: Mount a reachable NFS share and recover a credential stored in files + reason: NFS access depends on the compromised host network, export rule, and POSIX permissions. A stronger + identity is gained only if readable file content contains a live credential; Filestore instance metadata + does not identify one. diff --git a/src/privilege-escalation-paths/gcp/cloudscheduler.yaml b/src/privilege-escalation-paths/gcp/cloudscheduler.yaml index 2c18021f01..522fd2d94b 100644 --- a/src/privilege-escalation-paths/gcp/cloudscheduler.yaml +++ b/src/privilege-escalation-paths/gcp/cloudscheduler.yaml @@ -4,72 +4,3 @@ # 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 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: cloudscheduler.jobs.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 Cloud Scheduler OAuth identity in {project}" - conditions: - - 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: derived - 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 obtain the privileges of any service account in the project on which it holds iam.serviceAccounts.actAs, by updating an existing job. - 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 - scope: same_project - aggregate_as: "Service accounts attachable to existing Cloud Scheduler jobs in {project}" - conditions: - - id: existing_job - description: Needs an existing job in the project. - - 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: derived - severity: critical - mitigation: Restrict cloudscheduler.jobs.update and grant actAs only on specific SAs. diff --git a/src/privilege-escalation-paths/gcp/datafusion.yaml b/src/privilege-escalation-paths/gcp/datafusion.yaml index 3e3003b9ef..c89b3503cb 100644 --- a/src/privilege-escalation-paths/gcp/datafusion.yaml +++ b/src/privilege-escalation-paths/gcp/datafusion.yaml @@ -109,42 +109,3 @@ mitigation: Restrict datafusion.artifacts.create/update, pin plugin versions in pipelines and use a low-privilege pipeline SA. references: - https://docs.cloud.google.com/data-fusion/docs/concepts/rbac - -- id: gcp-datafusion-namespace-setserviceaccount-actas - provider: gcp - service: datafusion - title: Pin a Data Fusion namespace to a chosen service account and run pipelines as it - source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-data-fusion-persistence.md#scheduled-backdoor-pipeline-pinned-to-a-privileged-runtime-sa - 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 setting it as a Data Fusion namespace service account and deploying and running pipelines in that namespace. - requires: - all_of: - - action: iam.serviceAccounts.actAs - resource: "{target.email}" - - action: datafusion.namespaces.setServiceAccount - resource: "*" - - action: datafusion.pipelines.create - resource: "*" - - action: datafusion.pipelines.execute - 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 pinnable as Data Fusion namespace SA in {project}" - conditions: - - id: namespace_identity_use - description: HackTricks states scheduled pipeline runs in the pinned namespace execute as that SA; on RBAC-enabled instances the namespace SA is the design-time identity, so whether runtime code (compute profile) also uses it depends on the instance version and profile configuration. - - id: plugin_installed - description: A code-capable plugin (PySpark Program, Scala Spark) must be installed, and the Data Fusion service agent must be able to act as / mint tokens for the chosen SA. - - id: instance_access - description: The caller also needs effective datafusion.instances.get on the instance. - blockers: - - gcp_deny_policy - - vpc_sc_perimeter - confidence: conditional - severity: high - mitigation: Grant actAs only on dedicated Data Fusion namespace SAs and restrict datafusion.namespaces.setServiceAccount to platform administrators. - notes: The recurring schedule is persistence and is not modelled; the edge is the namespace SA pin plus pipeline execution. diff --git a/src/privilege-escalation-paths/gcp/deploymentmanager.yaml b/src/privilege-escalation-paths/gcp/deploymentmanager.yaml index 8782e75390..730008483b 100644 --- a/src/privilege-escalation-paths/gcp/deploymentmanager.yaml +++ b/src/privilege-escalation-paths/gcp/deploymentmanager.yaml @@ -134,3 +134,34 @@ - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-deployment-manager-post-exploitation.md notes: Schema-valid provisional draft only. Requires credential-target inventory and exact source-to-manifest-to-target join. Missing joined facts must evaluate UNKNOWN; do not emit an edge from permission alone. +- id: gcp-deploymentmanager-manifest-credential + provider: gcp + service: deploymentmanager + title: Recover an unredacted credential from a deployment manifest + source: src/pentesting-cloud/gcp-security/gcp-services/gcp-deployment-manager-enum.md#what-to-review + summary: A readable manifest with a verified embedded credential can expose the credential owner. + requires: + all_of: + - action: deploymentmanager.manifests.get + resource: '{target.host_resource}' + target: + kind: gcp_service_account + selector: + attached_to_service: deploymentmanager_manifest_credential + scope: any + outcome: credentials + aggregate_as: Service accounts with verified live keys in readable Deployment Manager manifests + conditions: + - id: credential_evidence + description: The manifest must contain a live, unredacted GCP service-account private key, with the client + email verified; only that service account is a target. + confidence: conditional + severity: high + mitigation: Remove credentials from deployment templates and restrict manifest reads. + source_revision: 0b36331 + blockers: + - gcp_deny_policy + references: + - https://docs.cloud.google.com/deployment-manager/docs/best-practices#including_credentials_in_your_deployment + notes: Discovery permissions are not required when the deployment and manifest names are known. Non-GCP credentials + require a separate target kind. diff --git a/src/privilege-escalation-paths/gcp/eventarc.yaml b/src/privilege-escalation-paths/gcp/eventarc.yaml index 4edcc88ca3..78d6732216 100644 --- a/src/privilege-escalation-paths/gcp/eventarc.yaml +++ b/src/privilege-escalation-paths/gcp/eventarc.yaml @@ -9,36 +9,53 @@ 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: The source can obtain an access token, and so the privileges, of any service account on which it holds iam.serviceAccounts.actAs, by routing bus events through a pipeline whose HTTPS destination it controls. + summary: The source can obtain an access token, and so the privileges, of any service account on which it + holds iam.serviceAccounts.actAs, by routing bus events through a pipeline whose HTTPS destination it controls. requires: all_of: - - action: eventarc.pipelines.create - resource: "*" - - action: iam.serviceAccounts.actAs - resource: "{target.email}" + - action: eventarc.pipelines.create + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + any_of: + - - action: eventarc.enrollments.create + resource: '*' + - action: eventarc.messageBuses.use + resource: '*' + - - action: eventarc.enrollments.update + 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 Eventarc pipeline OAuth identity in {project}" + aggregate_as: Service accounts usable as Eventarc pipeline OAuth identity in {project} conditions: - - id: enrollment - description: The source must also route bus events into the pipeline, with eventarc.enrollments.create plus eventarc.messageBuses.use on the bus, or eventarc.enrollments.update on an existing enrollment (create/use are not in the permission catalog, so this is kept as a condition). - - id: service_agent_token - description: The pipeline project's Eventarc service agent needs iam.serviceAccounts.getAccessToken on the SA (roles/eventarc.serviceAgent supplies it for same-project SAs; cross-project SAs need an explicit grant). - - 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. + - id: enrollment + description: An enrollment must route a compatible bus to this pipeline in the same region. The update + branch requires an existing enrollment that can be repointed; an enrollment with no matching event does + not deliver a token. + - id: service_agent_token + description: The pipeline project's Eventarc service agent needs iam.serviceAccounts.getAccessToken on + the SA (roles/eventarc.serviceAgent supplies it for same-project SAs; cross-project SAs need an explicit + grant). + - 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 + - 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. + 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. + - 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. Enrollment-create/bus-use or enrollment-update + is an IAM prerequisite, not merely a descriptive condition. diff --git a/src/privilege-escalation-paths/gcp/monitoring.yaml b/src/privilege-escalation-paths/gcp/monitoring.yaml new file mode 100644 index 0000000000..8cb76f5ae8 --- /dev/null +++ b/src/privilege-escalation-paths/gcp/monitoring.yaml @@ -0,0 +1,33 @@ +- id: gcp-s08-10-receive-monitoring-service-agent-oidc-tokens + provider: gcp + service: monitoring + title: 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 + summary: A resource-typed uptime check sends the Monitoring service agent OIDC token to an attacker-controlled + endpoint; reuse is limited to matching audience and authorization. + requires: + all_of: [] + any_of: + - - action: monitoring.uptimeCheckConfigs.create + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-s08-10-receive-monitoring-service-agent-oidc-tokens + scope: any + aggregate_as: Monitoring notification service agent accepted at exact audience + conditions: + - id: exact_verified_prerequisites + description: Require OIDC_TOKEN, exact resource type and endpoint control; identify token aud and a target + that accepts that audience and authorizes this service agent. Missing facts must evaluate UNKNOWN; emit + no derived path. + confidence: conditional + severity: high + mitigation: Restrict the named permission and review the exact resource and resulting grant. + references: + - https://cloud.hacktricks.wiki/pentesting-cloud/gcp-security/gcp-persistence/gcp-monitoring-persistence.md + notes: Draft only. The selector is a schema-valid placeholder for the feature or collector specified in this + fragment. diff --git a/src/privilege-escalation-paths/gcp/privatecatalog.yaml b/src/privilege-escalation-paths/gcp/privatecatalog.yaml index d582fb0551..70f90fbd53 100644 --- a/src/privilege-escalation-paths/gcp/privatecatalog.yaml +++ b/src/privilege-escalation-paths/gcp/privatecatalog.yaml @@ -63,3 +63,35 @@ source_revision: 0b36331 notes: Exact source/resource/target evidence must be emitted in gcp_privesc_challenge_evidence from the requested collector. Missing evidence is UNKNOWN; do not infer any other service account. +- id: gcp-s08-16-associate-poisoned-catalog-with-additional-consumer-hie + provider: gcp + service: privatecatalog + title: Associate poisoned catalog with additional consumer hierarchy + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-private-catalog-persistence.md#durable-poisoned-product-in-an-associated-catalog + summary: Associate an attacker-controlled poisoned product with a new consumer hierarchy; a consumer deployment + then executes its template. + requires: + all_of: [] + any_of: + - - action: cloudprivatecatalogproducer.catalogAssociations.create + resource: '*' + source_kind: + - gcp_user + - gcp_service_account + target: + kind: gcp_verified_authority + selector: + gcp_challenge_fact: gcp-s08-16-associate-poisoned-catalog-with-additional-consumer-hie + scope: any + aggregate_as: Consumer service agent of exact catalog deployment + conditions: + - id: exact_verified_prerequisites + description: Require controlled poisoned product/version, exact association to consumer folder/org, deployment + of that version and execution identity. Missing facts must evaluate UNKNOWN; emit no derived path. + confidence: conditional + severity: high + mitigation: Restrict the named permission and review the exact resource and resulting grant. + references: + - https://cloud.hacktricks.wiki/pentesting-cloud/gcp-security/gcp-persistence/gcp-private-catalog-persistence.md + notes: Draft only. The selector is a schema-valid placeholder for the feature or collector specified in this + fragment. diff --git a/src/privilege-escalation-paths/gcp/workflows.yaml b/src/privilege-escalation-paths/gcp/workflows.yaml index b6adad6ed9..554af43ce6 100644 --- a/src/privilege-escalation-paths/gcp/workflows.yaml +++ b/src/privilege-escalation-paths/gcp/workflows.yaml @@ -192,3 +192,64 @@ - gcp_user - gcp_service_account source_selector: {} +- id: gcp-workflows-existing-parameterized-invoke + provider: gcp + service: workflows + title: Invoke an existing parameterized workflow as its service account + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-workflows-persistence.md#backdoor-workflow-bound-to-a-privileged-service-account + source_revision: 0b36331 + summary: A caller of an existing workflow can select a Google API operation that its attached service account + executes. + requires: + all_of: + - action: workflows.executions.create + resource: '*' + target: + kind: gcp_service_account + selector: + attached_to_service: workflows_workflow + gcp_challenge_fact: gcp-workflows-existing-parameterized-invoke + scope: any + outcome: impersonation + aggregate_as: Verified attached SAs of parameterized workflows + conditions: + - id: argument_to_oauth_request + description: The deployed source revision must pass caller-controlled method, URL, or body into an OAuth-authenticated + Google API request; fixed workflows do not qualify. + confidence: conditional + severity: high + mitigation: Restrict invocation of workflows that accept caller-controlled authenticated requests. + references: + - https://cloud.google.com/workflows/docs/authenticate-workflow + - https://cloud.google.com/workflows/docs/access-control +- id: gcp-workflows-parameterized-callback + provider: gcp + service: workflows + title: Resume a privileged workflow through a parameterized callback + source: src/pentesting-cloud/gcp-security/gcp-persistence/gcp-workflows-persistence.md#long-lived-callback-endpoint---a-waiting-execution-as-a-trigger + source_revision: 0b36331 + summary: A callback sender can choose an authenticated Google API request executed by a waiting workflow + SA. + requires: + all_of: + - action: workflows.callbacks.send + resource: '*' + target: + kind: gcp_service_account + selector: + attached_to_service: workflows_workflow + gcp_challenge_fact: gcp-workflows-parameterized-callback + scope: any + outcome: impersonation + aggregate_as: Verified SAs of waiting parameterized workflows + conditions: + - id: live_callback_and_oauth_flow + description: An ACTIVE execution must have an active callback waiter and the pinned workflow revision must + feed callback fields into an OAuth-authenticated Google API request. + confidence: conditional + severity: high + mitigation: Restrict callback sending and remove workflow definitions that proxy untrusted callback data. + references: + - https://cloud.google.com/workflows/docs/authenticate-workflow + - https://cloud.google.com/workflows/docs/access-control + - https://cloud.google.com/workflows/docs/creating-callback-endpoints diff --git a/src/privilege-escalation-paths/gcp/workspace.yaml b/src/privilege-escalation-paths/gcp/workspace.yaml index 958ec1292a..04780a769e 100644 --- a/src/privilege-escalation-paths/gcp/workspace.yaml +++ b/src/privilege-escalation-paths/gcp/workspace.yaml @@ -341,3 +341,36 @@ - https://knowledge.workspace.google.com/admin/users/recovering-administrator-access-to-your-account notes: Distinct from gcp-workspace-cloud-dns-admin-recovery, which requires record-write permissions initially; this path obtains those permissions through a zone IAM self-grant. +- id: gcp-workspace-cloud-dns-zone-policy-recovery + provider: gcp + service: dns + title: Self-grant zone DNS write and publish a Workspace recovery challenge + source: src/pentesting-cloud/gcp-security/gcp-services/gcp-dns-enum.md#gcp---cloud-dns + summary: Managed-zone policy write can grant record-write permissions used in Workspace administrator recovery. + pivot_resource_type: dns_managed_zone + requires: + all_of: + - action: dns.managedZones.setIamPolicy + resource: '{pivot}' + target: + kind: gcp_workspace_user + selector: + attached_to_service: workspace_super_admin_of_zone_domain + scope: any + outcome: impersonation + aggregate_as: Workspace super administrators of domains served by {pivot} + conditions: + - id: recovery_process + description: Google administrator recovery must accept the DNS challenge for the tenant; this is an external + process, not a guaranteed result. + confidence: conditional + severity: critical + mitigation: Restrict managed-zone policy writes on Workspace domains. + source_revision: 0b36331 + blockers: + - gcp_deny_policy + references: + - https://docs.cloud.google.com/dns/docs/access-control + - https://docs.cloud.google.com/dns/docs/reference/rest/v1/managedZones/setIamPolicy + notes: Only zone-scoped roles/dns.admin on the authoritative managed zone is assumed; this grants the record-write + actions needed by gcp-workspace-cloud-dns-admin-recovery. No project-wide DNS grant is inferred. From 08873ca82bb677ca4fac8847740155165e55c538 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Mon, 12 Oct 2026 21:22:04 +0200 Subject: [PATCH 11/17] Integrate verified GCP privesc catalog fragments Co-Authored-By: Codex --- .../gcp/_excluded.yaml | 104 ++++++++++++------ .../gcp/aiplatform.yaml | 27 +++++ src/privilege-escalation-paths/gcp/dlp.yaml | 28 +++++ src/privilege-escalation-paths/gcp/pam.yaml | 2 +- .../gcp/parametermanager.yaml | 93 ++++++++++++++++ .../gcp/privatecatalog.yaml | 12 +- .../gcp/securesourcemanager.yaml | 63 +++++++++++ .../gcp/storage.yaml | 27 +++++ .../gcp/workflows.yaml | 27 +++++ 9 files changed, 344 insertions(+), 39 deletions(-) create mode 100644 src/privilege-escalation-paths/gcp/aiplatform.yaml create mode 100644 src/privilege-escalation-paths/gcp/dlp.yaml create mode 100644 src/privilege-escalation-paths/gcp/parametermanager.yaml diff --git a/src/privilege-escalation-paths/gcp/_excluded.yaml b/src/privilege-escalation-paths/gcp/_excluded.yaml index c67dd39d0d..769447a1f9 100644 --- a/src/privilege-escalation-paths/gcp/_excluded.yaml +++ b/src/privilege-escalation-paths/gcp/_excluded.yaml @@ -9,9 +9,6 @@ - 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-integration-connectors-privesc.md#connectorsconnectionssetiampolicy--resource-level-self-grant-to-use-a-connection - technique: Connection IAM self-grant for stored backend credentials - reason: The grant permits connector operations with a stored external backend credential; the page does not identify an attached GCP service account or grant its IAM permissions. The former GCP-SA attachment bypass is documented as fixed. - 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. @@ -801,7 +798,8 @@ reason: Service introduction; no technique. - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-discovery-engine-privesc.md#discoveryengineenginesdatastorescollectionssetiampolicy--self-grant-app-or-corpus-access technique: Discovery Engine engines/dataStores/collections setIamPolicy self-grant - reason: "Grants use or administration of one Gemini Enterprise app or corpus (indexed data); data access, no new cloud identity." + reason: Grants a new administrative or use role on the exact Gemini Enterprise app or corpus, but the GCP evaluator + lacks a resource-scoped privilege target and the linked-resource/persona join; do not infer project-wide access. - 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: "Maps an attacker identity into a group for per-document search ACLs; data access, no new cloud identity." @@ -829,9 +827,6 @@ - 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-healthcare-privesc.md#healthcaresetiampolicy--grant-a-clinical-data-role-to-your-principal - technique: "healthcare.*.setIamPolicy clinical-data self-grant" - reason: "Grants FHIR/DICOM/HL7v2/consent data roles on one dataset or store; data access, no new identity (the Healthcare service agent is not reachable)." - source: src/pentesting-cloud/gcp-security/gcp-privilege-escalation/gcp-iap-privesc.md#iap technique: Page intro reason: Service introduction; no technique. @@ -947,7 +942,8 @@ reason: "Resource-bounded publish/consume/redirect control of one topic or subscription; data access, no new identity." - 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." + reason: Audience-bound OIDC can authenticate as the selected SA to a trusting receiver, but delivery, capture, + audience and receiver trust require evidence; it is not OAuth access to arbitrary Google APIs. - 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." @@ -968,13 +964,16 @@ reason: Service introduction; no technique. - 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: enableManagedRotation Cloud SQL password reset - reason: "Yields a Cloud SQL database user credential through the secret identity; database access, not a cloud IAM identity." + reason: Managed rotation can set a known Cloud SQL database-user password through the secret identity; model the + exact DB user and first-enable prerequisites. - 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. + reason: Event exfiltration is data access; authenticated delivery may carry a scoped SA OIDC token only with signing + authority, a matching event and a trusting receiver. - 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. + technique: sshkeys.createAny on a service account's git identity + reason: createAny plus actAs can grant Git fetch/push as the SA; repository IAM and key registration must be verified, + and this is not general Google API impersonation. - 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. @@ -1072,9 +1071,6 @@ but it is not a general Google API OAuth token. The current SA target means general impersonation and would be a false positive. A sound edge requires an audience-bound assertion target, exact relying-service trust and gateway invocation facts, none represented here. -- 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). @@ -1186,8 +1182,8 @@ 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. + reason: Render returns referenced secret values. An identity edge requires validated credential content and an + exact stronger-principal mapping; arbitrary payloads remain data. - 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: This method is self-only for the Google user, but it can return that user’s linked external-provider @@ -1299,9 +1295,8 @@ 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: The section allows sourceContents to contain a hardcoded credential, but presence, usability and downstream - identity are content facts absent from the configuration snapshot; the service-account email alone is reconnaissance. - source_revision: 0b36331 + reason: Workflow serviceAccount metadata is reconnaissance; sourceContents can disclose a reusable credential + only when content and owner are verified. workflows.workflows.get alone does not establish an identity edge. - 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.' @@ -1310,8 +1305,8 @@ 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: Repository history and review diffs may contain valid credentials. Their identity, validity, and downstream - permissions are runtime content and cannot be inferred from repository read permission alone. + reason: Repository fetch is data access unless committed content contains a validated stronger credential mapped + to an exact principal. - 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. @@ -1393,8 +1388,8 @@ 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. + reason: A secret version can hold a stronger credential, but its content, validity and exact principal mapping + must be verified; metadata or permission alone is data read. - 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. @@ -1424,7 +1419,8 @@ 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. + reason: Wallet retrieval can grant a database-user credential; current catalog lacks a DB-user target and wallet + authentication facts. It does not confer GCP IAM identity. - 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. @@ -1451,8 +1447,8 @@ 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: Repository history may contain valid committed credentials. Their identity, validity, and downstream permissions - are runtime content and cannot be inferred from source.repos.get alone. + reason: Repository read can expose a reusable service-account key in reachable Git history, but that requires + validated content and key-owner evidence; source.repos.get alone does not identify a gained principal. - 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. @@ -1518,7 +1514,8 @@ 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. + reason: Render returns referenced secret values. An identity edge requires validated credential content and an + exact stronger-principal mapping; arbitrary payloads remain data. - 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. @@ -1530,7 +1527,8 @@ 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. + reason: Service overview. DLP findings can quote a reusable credential only when includeQuote and the output content + support it; IAM/job metadata alone cannot identify a gained principal. - 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. @@ -1562,7 +1560,9 @@ 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. + reason: The caller may act under a distinct stored backend credential, but current backend authorization, credential + validity, exact action/entity support, and successful execution are external runtime facts not established by + the GCP configuration snapshot. Listener only receives the configured event stream. - 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: Impersonation of a selected application user for a deployed connector operation is an identity gain @@ -2347,8 +2347,10 @@ 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. + reason: A queue binding to allUsers or allAuthenticatedUsers permits task enqueueing by any Google-authenticated + caller without a victim-project grant; the Cloud Tasks API still requires a valid Google bearer token. Creating + a task with an OAuth/OIDC token for a service account additionally requires iam.serviceAccounts.actAs on that + account, so the queue grant alone does not confer its 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 @@ -2717,3 +2719,41 @@ reason: NFS access depends on the compromised host network, export rule, and POSIX permissions. A stronger identity is gained only if readable file content contains a live credential; Filestore instance metadata does not identify one. +- source: src/pentesting-cloud/gcp-security/gcp-services/gcp-integration-connectors-enum.md#enumerate-connections + technique: Invoke a connection using stored backend credentials + reason: The connection inventory and GCP Invoker permission do not establish that a specific action or SQL statement + succeeds as a distinct backend identity. That requires the current external backend account permissions, credential + validity, connector action schema, and execution result; the GCP snapshot cannot determine them without false + positive identity edges. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/README.md#service-account-private-keys + technique: Use a leaked service-account private key found in public material + reason: A valid leaked service-account private key authenticates as its service account, but the public repository, + log, bundle, or artifact containing it and the key's validity and owner are content and runtime facts absent + from the configuration snapshot. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/README.md#bearer-identity-tokens + technique: Reuse a leaked bearer identity token + reason: A valid bearer token can confer a session as its represented identity, but signature validity, audience, + scopes, expiry, and token owner depend on the token and accepting service at runtime, not IAM configuration. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-api-keys-unauthenticated-enum.md#service-account-private-keys + technique: Use a leaked service-account private key from public client material + reason: A valid private key in public client material authenticates as its service account, but the material's + contents, key validity, and target service account cannot be inferred from IAM policy or API-key configuration. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-artifact-registry-unauthenticated-enum.md#anonymous-pull-from-a-public-repository + technique: Pull public image layers that may contain credentials + reason: Anonymous Artifact Registry read exposes image bytes; an identity gain requires a valid service-account + key or other credential actually embedded in an image layer, plus its owner and current validity, none of which + the repository IAM grant establishes. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-compute-unauthenticated-enum.md#ssrf---server-side-request-forgery + technique: Use header-capable SSRF to read a VM service-account metadata token + reason: The VM metadata token would authenticate as its attached service account, but a reachable web application + with header-capable SSRF and a successful request to the metadata server are runtime application and network + facts absent from the snapshot. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-gke-kubelet-unauthenticated-access.md#historical-kubelet-read-only-metadata + technique: Read legacy kubelet /pods metadata that may expose environment credentials + reason: The legacy read-only kubelet port provides pod metadata; a credential gain requires a reachable port 10255 + and a usable credential actually present in a /pods environment value, with owner and validity determined from + live response content. +- source: src/pentesting-cloud/gcp-security/gcp-unauthenticated-enum-and-access/gcp-google-groups-unauthenticated-enum.md#read-a-publicly-visible-group-archive + technique: Read public Google Groups messages that may contain pasted secrets + reason: A public Google Groups archive discloses messages, not group membership; a credential gain requires a + usable secret actually pasted in a message and validation of its owner and current validity. diff --git a/src/privilege-escalation-paths/gcp/aiplatform.yaml b/src/privilege-escalation-paths/gcp/aiplatform.yaml new file mode 100644 index 0000000000..b44fe4bfae --- /dev/null +++ b/src/privilege-escalation-paths/gcp/aiplatform.yaml @@ -0,0 +1,27 @@ +- id: gcp-vertex-customjob-env-sa-credential + provider: gcp + service: aiplatform + title: Read inline credentials in custom-job environment of a GCP service account + source: src/pentesting-cloud/gcp-security/gcp-services/gcp-vertex-ai-enum.md#custom-job-information + source_revision: 0b36331 + summary: A readable vertex custom job env contains a verified reusable credential belonging to another GCP service + account. + requires: + all_of: + - action: aiplatform.customJobs.get + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-vertex-customjob-env-sa-credential + scope: any + outcome: credentials + conditions: + - id: verified_content + description: Emit only for exact source, resource, target and scope evidence after verifying credential validity; + absent or incomplete content is UNKNOWN, and metadata or secret names alone do not qualify. + confidence: conditional + severity: high + mitigation: Restrict aiplatform.customJobs.get on sensitive resources; rotate exposed service-account credentials. + references: + - https://cloud.google.com/vertex-ai/docs/reference/rest/v1/projects.locations.customJobs/get diff --git a/src/privilege-escalation-paths/gcp/dlp.yaml b/src/privilege-escalation-paths/gcp/dlp.yaml new file mode 100644 index 0000000000..9053c94015 --- /dev/null +++ b/src/privilege-escalation-paths/gcp/dlp.yaml @@ -0,0 +1,28 @@ +- id: gcp-dlp-job-quote-sa-credential + provider: gcp + service: dlp + title: Read quoted credentials from DLP job findings of a GCP service account + source: src/pentesting-cloud/gcp-security/gcp-services/gcp-sensitive-data-protection-dlp-enum.md#enumeration + source_revision: 0b36331 + summary: A readable dlp job quote contains a verified reusable credential belonging to another GCP service account. + requires: + all_of: + - action: dlp.jobs.get + resource: '*' + - action: bigquery.tables.getData + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-dlp-job-quote-sa-credential + scope: any + outcome: credentials + conditions: + - id: verified_content + description: Emit only for exact source, resource, target and scope evidence after verifying credential validity; + absent or incomplete content is UNKNOWN, and metadata or secret names alone do not qualify. + confidence: conditional + severity: high + mitigation: Restrict dlp.jobs.get on sensitive resources; rotate exposed service-account credentials. + references: + - https://docs.cloud.google.com/sensitive-data-protection/docs/reference/rest diff --git a/src/privilege-escalation-paths/gcp/pam.yaml b/src/privilege-escalation-paths/gcp/pam.yaml index 886e4ede30..4f58004f0c 100644 --- a/src/privilege-escalation-paths/gcp/pam.yaml +++ b/src/privilege-escalation-paths/gcp/pam.yaml @@ -39,4 +39,4 @@ - https://docs.cloud.google.com/iam/docs/pam-permissions-and-setup - https://docs.cloud.google.com/iam/docs/pam-create-entitlements - https://docs.cloud.google.com/iam/docs/pam-approve-deny-grants - notes: Google states requesters and approvers need no PAM-specific permissions and that you cannot approve your own request. Entitlement creation needs the scope's setIamPolicy, so it is not modelled as an escalation. Outcome role_activation (time-bound activation of an eligible role, like Entra PIM) replaces the default scope_control because full scope control holds only when the offered role manages IAM. The evaluator still returns None for gcp_pam_entitlement_requester, so the edge is not emitted until the collector reads entitlements. + notes: Google states requesters and approvers need no PAM-specific permissions and that you cannot approve your own request. Entitlement creation needs the scope's setIamPolicy, so it is not modelled as an escalation. Outcome role_activation (time-bound activation of an eligible role, like Entra PIM) replaces the default scope_control because full scope control holds only when the offered role manages IAM. The evaluator still returns None for gcp_pam_entitlement_requester, so the edge is not emitted until the collector reads entitlements. This rule is limited to IAM-management entitlements; non-admin offered roles need the separate role-specific model in gap-12. diff --git a/src/privilege-escalation-paths/gcp/parametermanager.yaml b/src/privilege-escalation-paths/gcp/parametermanager.yaml new file mode 100644 index 0000000000..dbfddbfe60 --- /dev/null +++ b/src/privilege-escalation-paths/gcp/parametermanager.yaml @@ -0,0 +1,93 @@ +- id: gcp-parametermanager-version-render-credential + provider: gcp + service: parametermanager + title: Render a parameter version to recover a stronger credential + source: src/pentesting-cloud/gcp-security/gcp-services/gcp-parameter-manager-enum.md#relevant-permissions + summary: Render resolves a Secret Manager reference as the parameter identity and returns a credential the caller + cannot access directly. + requires: + all_of: + - action: parametermanager.parameterVersions.render + resource: '*' + target: + kind: gcp_service_account + outcome: credentials + scope: any + selector: + gcp_challenge_fact: gcp-parametermanager-version-render-credential + conditions: + - A version embeds a __REF__ to a Secret Manager version holding a stronger credential. + - The parameter/template service identity can access that secret; the caller can render the version. + - The returned payload must actually contain a usable credential. + confidence: conditional + severity: high + mitigation: Restrict render grants; scope the parameter identity’s Secret Manager access. + references: + - https://cloud.google.com/secret-manager/parameter-manager/docs/reference-secrets + notes: Exact verified source/resource/target fact is mandatory. Missing evidence evaluates UNKNOWN. Only a validated + stronger service-account credential qualifies; arbitrary content is data. + source_revision: 0b36331 +- id: gcp-parametermanager-template-render-credential + provider: gcp + service: parametermanager + title: Render a template version to recover a stronger credential + source: src/pentesting-cloud/gcp-security/gcp-services/gcp-parameter-manager-enum.md#relevant-permissions + summary: Render resolves a Secret Manager reference as the parameter identity and returns a credential the caller + cannot access directly. + requires: + all_of: + - action: parametermanager.templateVersions.render + resource: '*' + target: + kind: gcp_service_account + outcome: credentials + scope: any + selector: + gcp_challenge_fact: gcp-parametermanager-template-render-credential + conditions: + - A version embeds a __REF__ to a Secret Manager version holding a stronger credential. + - The parameter/template service identity can access that secret; the caller can render the version. + - The returned payload must actually contain a usable credential. + confidence: conditional + severity: high + mitigation: Restrict render grants; scope the parameter identity’s Secret Manager access. + references: + - https://cloud.google.com/secret-manager/parameter-manager/docs/reference-secrets + notes: Exact verified source/resource/target fact is mandatory. Missing evidence evaluates UNKNOWN. Only a validated + stronger service-account credential qualifies; arbitrary content is data. + source_revision: 0b36331 +- id: gcp-parametermanager-write-reference-render-credential + provider: gcp + service: parametermanager + title: Insert a secret reference and render it through Parameter Manager identity + source: src/pentesting-cloud/gcp-security/gcp-services/gcp-parameter-manager-enum.md#relevant-permissions + summary: A caller able to write a parameter version and render it can cause the parameter identity to dereference + a credential-bearing Secret Manager version it can access. + requires: + any_of: + - - action: parametermanager.parameterVersions.create + resource: '*' + - action: parametermanager.parameterVersions.render + resource: '*' + - - action: parametermanager.parameterVersions.update + resource: '*' + - action: parametermanager.parameterVersions.render + resource: '*' + target: + kind: gcp_service_account + outcome: credentials + scope: any + selector: + gcp_challenge_fact: gcp-parametermanager-write-reference-render-credential + conditions: + - Parameter identity can access the chosen secret; the written __REF__ is accepted; the caller can render the + resulting version. + - Referenced secret contains a usable stronger credential; target relation needs content evidence. + confidence: conditional + severity: high + mitigation: Do not give untrusted principals both version write and render on identities with broad secret access. + references: + - https://cloud.google.com/secret-manager/parameter-manager/docs/reference-secrets + notes: Exact verified source/resource/target fact is mandatory. Missing evidence evaluates UNKNOWN. Only a validated + stronger service-account credential qualifies; arbitrary content is data. + source_revision: 0b36331 diff --git a/src/privilege-escalation-paths/gcp/privatecatalog.yaml b/src/privilege-escalation-paths/gcp/privatecatalog.yaml index 70f90fbd53..31bf9df8d4 100644 --- a/src/privilege-escalation-paths/gcp/privatecatalog.yaml +++ b/src/privilege-escalation-paths/gcp/privatecatalog.yaml @@ -11,9 +11,11 @@ source_revision: 171e422 summary: The source can make the Google APIs Service Agent of consumer projects that later deploy a shared solution version it can update create attacker-chosen resources. requires: - all_of: - - action: cloudprivatecatalogproducer.products.update - resource: "*" + any_of: + - - action: cloudprivatecatalogproducer.products.update + resource: "*" + - - action: cloudprivatecatalogproducer.products.setIamPolicy + resource: "*" target: kind: gcp_service_account selector: @@ -25,8 +27,6 @@ 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: terraform_solutions - description: Terraform-based solutions run as the configured or default Cloud Build identity instead of the cloudservices agent. blockers: - gcp_deny_policy confidence: conditional @@ -34,7 +34,7 @@ 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: Deployment Manager solutions run as the consumer project's Google APIs Service Agent (roles/editor by default), like gcp-deploymentmanager-deployments-create. + notes: Deployment Manager branch only; Terraform uses the consumer Cloud Build SA (gap-04). Product setIamPolicy can self-grant update on the same existing product. - id: gcp-privatecatalog-terraform-version-poison provider: gcp service: cloudprivatecatalogproducer diff --git a/src/privilege-escalation-paths/gcp/securesourcemanager.yaml b/src/privilege-escalation-paths/gcp/securesourcemanager.yaml index 666e6571b9..d37e81e398 100644 --- a/src/privilege-escalation-paths/gcp/securesourcemanager.yaml +++ b/src/privilege-escalation-paths/gcp/securesourcemanager.yaml @@ -59,3 +59,66 @@ confidence: conditional severity: high mitigation: Restrict setIamPolicy (roles/securesourcemanager.instanceOwner, repoAdmin, roles/owner). +- id: gcp-securesourcemanager-hook-oidc-token + provider: gcp + service: securesourcemanager + title: Capture repository webhook OIDC token + source: src/pentesting-cloud/gcp-security/gcp-services/gcp-secure-source-manager-enum.md#relevant-permissions + summary: A service-account-authenticated hook sends an identity token for the repository SA to the selected URI. + requires: + any_of: + - - action: securesourcemanager.hooks.create + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + - - action: securesourcemanager.hooks.update + resource: '*' + - action: iam.serviceAccounts.actAs + resource: '{target.email}' + target: + kind: gcp_service_account + outcome: credentials + scope: any + selector: + gcp_challenge_fact: gcp-securesourcemanager-hook-oidc-token + conditions: + - Repository SA association, service-agent Token Creator, hook event, reachable endpoint and matching downstream + audience. + confidence: conditional + severity: high + mitigation: Restrict hook writes/actAs; review authenticated hook destinations. + references: + - https://docs.cloud.google.com/secure-source-manager/docs/set-up-webhooks + notes: Exact verified source/resource/target fact is mandatory. Missing evidence evaluates UNKNOWN. This is an + audience-bound OIDC identity token, not general OAuth access. + source_revision: 0b36331 +- id: gcp-securesourcemanager-fetch-committed-credential + provider: gcp + service: securesourcemanager + title: Clone a repository containing a stronger cloud credential + source: src/pentesting-cloud/gcp-security/gcp-services/gcp-secure-source-manager-enum.md#relevant-permissions + summary: Repository fetch exposes source files; when a committed file contains a usable stronger credential, the + caller can acquire it. + requires: + all_of: + - action: securesourcemanager.repositories.fetch + resource: '*' + - action: securesourcemanager.instances.access + resource: '*' + target: + kind: gcp_service_account + outcome: credentials + scope: any + selector: + gcp_challenge_fact: gcp-securesourcemanager-fetch-committed-credential + conditions: + - Repository content contains a valid credential for a stronger principal. + - Credential-to-principal relation requires content evidence; repository IAM and instance access must permit clone. + confidence: conditional + severity: high + mitigation: Scan and revoke committed credentials; restrict repository fetch. + references: + - https://docs.cloud.google.com/secure-source-manager/docs/access-control + notes: Exact verified source/resource/target fact is mandatory. Missing evidence evaluates UNKNOWN. Only a validated + stronger service-account credential qualifies; arbitrary content is data. + source_revision: 0b36331 diff --git a/src/privilege-escalation-paths/gcp/storage.yaml b/src/privilege-escalation-paths/gcp/storage.yaml index 92aa91ca5f..d655ea83ba 100644 --- a/src/privilege-escalation-paths/gcp/storage.yaml +++ b/src/privilege-escalation-paths/gcp/storage.yaml @@ -186,3 +186,30 @@ mitigation: Limit storage.objects.get to trusted operators and monitor the target-specific use. references: - src/pentesting-cloud/gcp-security/gcp-post-exploitation/gcp-application-design-center-post-exploitation.md#rolesdesigncenterviewer--read-objects-from-known-cloud-storage-buckets +- id: gcp-storage-object-sa-credential + provider: gcp + service: storage + title: Read credential from Storage object or older generation of a GCP service account + source: src/pentesting-cloud/gcp-security/gcp-services/gcp-storage-enum.md#enumeration + source_revision: 0b36331 + summary: A readable storage object generation contains a verified reusable credential belonging to another GCP + service account. + requires: + all_of: + - action: storage.objects.get + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-storage-object-sa-credential + scope: any + outcome: credentials + conditions: + - id: verified_content + description: Emit only for exact source, resource, target and scope evidence after verifying credential validity; + absent or incomplete content is UNKNOWN, and metadata or secret names alone do not qualify. + confidence: conditional + severity: high + mitigation: Restrict storage.objects.get on sensitive resources; rotate exposed service-account credentials. + references: + - https://docs.cloud.google.com/storage/docs/json_api/v1/objects/get diff --git a/src/privilege-escalation-paths/gcp/workflows.yaml b/src/privilege-escalation-paths/gcp/workflows.yaml index 554af43ce6..ab4963662e 100644 --- a/src/privilege-escalation-paths/gcp/workflows.yaml +++ b/src/privilege-escalation-paths/gcp/workflows.yaml @@ -253,3 +253,30 @@ - https://cloud.google.com/workflows/docs/authenticate-workflow - https://cloud.google.com/workflows/docs/access-control - https://cloud.google.com/workflows/docs/creating-callback-endpoints +- id: gcp-workflows-execution-sa-credential + provider: gcp + service: workflows + title: Read credential from workflow execution arguments or results of a GCP service account + source: src/pentesting-cloud/gcp-security/gcp-services/gcp-workflows-enum.md#enumeration + source_revision: 0b36331 + summary: A readable workflow execution content contains a verified reusable credential belonging to another GCP + service account. + requires: + all_of: + - action: workflows.executions.get + resource: '*' + target: + kind: gcp_service_account + selector: + gcp_challenge_fact: gcp-workflows-execution-sa-credential + scope: any + outcome: credentials + conditions: + - id: verified_content + description: Emit only for exact source, resource, target and scope evidence after verifying credential validity; + absent or incomplete content is UNKNOWN, and metadata or secret names alone do not qualify. + confidence: conditional + severity: high + mitigation: Restrict workflows.executions.get on sensitive resources; rotate exposed service-account credentials. + references: + - https://docs.cloud.google.com/workflows/docs/access-execution-results From c72e65c330bcd78580f904536b9284f7ccfdf3ae Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Mon, 12 Oct 2026 21:28:29 +0200 Subject: [PATCH 12/17] Integrate verified Azure privesc catalog fragments Co-Authored-By: Codex --- .../azure/_excluded_171e422_control.yaml | 8 +- .../azure/_excluded_171e422_entra.yaml | 33 ++-- .../azure/_excluded_audit_g1-entra.yaml | 5 +- .../azure/_excluded_audit_g2-hybrid.yaml | 17 +- .../azure/_excluded_audit_g4-compute.yaml | 6 +- .../azure/_excluded_audit_g8-storage-msg.yaml | 36 ++-- .../azure/_excluded_audit_s06.yaml | 55 ++++++ .../azure/_excluded_entraid.yaml | 6 +- .../azure/_excluded_rbac.yaml | 171 +++++++++++++---- .../azure/_excluded_rbac_refresh_a.yaml | 20 +- .../azure/_excluded_rbac_refresh_b.yaml | 35 ++-- .../azure/_excluded_rbac_refresh_c.yaml | 8 +- src/privilege-escalation-paths/azure/arc.yaml | 39 ---- .../azure/batch.yaml | 36 ++-- .../azure/confidential_ledger.yaml | 31 +-- .../azure/container_registry.yaml | 41 +++- .../azure/cosmos_db.yaml | 36 ---- .../azure/databases.yaml | 48 ++++- .../azure/databricks.yaml | 35 +++- .../azure/digital_twins.yaml | 70 ------- .../azure/entraid_apps.yaml | 56 +++--- .../azure/entraid_governance.yaml | 49 ----- .../azure/key_vault.yaml | 40 ++-- .../azure/kubernetes.yaml | 77 ++------ .../azure/logic_apps.yaml | 67 ++++++- .../azure/managed_applications.yaml | 35 +++- .../azure/monitor.yaml | 30 +++ .../azure/purview.yaml | 36 +++- .../azure/service_bus.yaml | 142 +++++++++++++- .../azure/service_fabric.yaml | 39 +++- .../azure/spring_apps.yaml | 99 +++++++++- .../azure/sre_agent.yaml | 36 +++- .../azure/static_web_apps.yaml | 30 +++ .../azure/storage.yaml | 181 ++++++++++++++++++ .../azure/virtual_machines.yaml | 135 +++++++++---- 35 files changed, 1250 insertions(+), 538 deletions(-) create mode 100644 src/privilege-escalation-paths/azure/_excluded_audit_s06.yaml create mode 100644 src/privilege-escalation-paths/azure/monitor.yaml create mode 100644 src/privilege-escalation-paths/azure/static_web_apps.yaml create mode 100644 src/privilege-escalation-paths/azure/storage.yaml diff --git a/src/privilege-escalation-paths/azure/_excluded_171e422_control.yaml b/src/privilege-escalation-paths/azure/_excluded_171e422_control.yaml index 3578fc648a..f3762bfd8b 100644 --- a/src/privilege-escalation-paths/azure/_excluded_171e422_control.yaml +++ b/src/privilege-escalation-paths/azure/_excluded_171e422_control.yaml @@ -1,5 +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: "Rotates and returns a classic Azure Cache for Redis access key: cache data-plane read/alter and denial of service for clients using the old key; no Azure/Entra identity is gained." + technique: Microsoft.Cache/redis/regenerateKey/action + reason: A credential or permission gain is documented, but it is deferred until azure_service_credential target + for a regenerated Redis key and machine-checked access-key authentication. Rotation yields a replacement credential, + but disabled key auth defeats use. diff --git a/src/privilege-escalation-paths/azure/_excluded_171e422_entra.yaml b/src/privilege-escalation-paths/azure/_excluded_171e422_entra.yaml index 4112c06d7a..4fd34bddd3 100644 --- a/src/privilege-escalation-paths/azure/_excluded_171e422_entra.yaml +++ b/src/privilege-escalation-paths/azure/_excluded_171e422_entra.yaml @@ -1,7 +1,3 @@ -# 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 @@ -67,13 +63,17 @@ 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." + technique: Replay a victim Entra browser session cookie + source_revision: 0b36331 + reason: Requires access to a victim browser profile, a decryptable cookie compatible with the browser protection + in use, and an unexpired session accepted by Entra. These host and session facts are not determined from tenant + permissions. - 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." + technique: PRT-derived P2P certificate and remote host credential theft + source_revision: 0b36331 + reason: Requires a usable user PRT, security context and derived key, a reachable Entra-joined remote host, sufficient + guest privileges and another user PRT present on that host. Those credential, network and host-session facts + are not determined from tenant permissions. - 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 @@ -95,14 +95,19 @@ 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 + technique: nOAuth mutable email claim account takeover source_revision: 171e422 - reason: "Application-side identity confusion / token reuse by the same principal; not expressible from tenant configuration." + reason: A victim account is gained only when a relying-party application maps the unverified mutable email claim + to that account; the application account mapping and sign-in outcome are runtime facts outside the Entra tenant + snapshot. FOCI is a separate token-exchange mechanism. - 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 + technique: Data-only cross-tenant resource keys, SAS and network 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." + reason: Storage/SQL/Cosmos/Service Bus keys and SAS provide resource data access, and peering/Private Link provides + network reach; neither alone yields another principal. ACR Task managed-identity theft is azure-acr-task-write-existing-identity; + compute and Automation identity execution are covered by their service entries. Credential-bearing image or + connection content needs exact content and principal evidence. diff --git a/src/privilege-escalation-paths/azure/_excluded_audit_g1-entra.yaml b/src/privilege-escalation-paths/azure/_excluded_audit_g1-entra.yaml index 6a5622e220..5f04f5ef0b 100644 --- a/src/privilege-escalation-paths/azure/_excluded_audit_g1-entra.yaml +++ b/src/privilege-escalation-paths/azure/_excluded_audit_g1-entra.yaml @@ -1,4 +1,3 @@ -# 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 @@ -74,7 +73,9 @@ - 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. + reason: A possessed, unexpired FOCI-family refresh token may gain delegated authority for another public client + and resource through that client’s pre-consented scopes. Token possession, family eligibility, grant/consent + and Conditional Access exchange outcome are runtime facts; tenant configuration alone cannot assert the edge. - 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 diff --git a/src/privilege-escalation-paths/azure/_excluded_audit_g2-hybrid.yaml b/src/privilege-escalation-paths/azure/_excluded_audit_g2-hybrid.yaml index 9228374dc4..caa18a5eac 100644 --- a/src/privilege-escalation-paths/azure/_excluded_audit_g2-hybrid.yaml +++ b/src/privilege-escalation-paths/azure/_excluded_audit_g2-hybrid.yaml @@ -1,4 +1,3 @@ -# 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 @@ -35,17 +34,21 @@ 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. + technique: Request tokens through a PRT-backed broker, including impersonation of another active user session + source_revision: 0b36331 + reason: Requires execution in a joined device user session or local Administrator/SYSTEM access to impersonate + another active user, plus that user session having a valid PRT. Device compromise, live session state and token + issuance are runtime facts not determined from tenant permissions. - 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. + technique: Azure CLI and PowerShell token caches on a host + source_revision: 0b36331 + reason: Requires host file or memory access to another sign-in cache or a service-principal secret, plus valid + usable credential contents; cache ownership, decryptability and contents are runtime facts not determined from + tenant permissions. - 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 diff --git a/src/privilege-escalation-paths/azure/_excluded_audit_g4-compute.yaml b/src/privilege-escalation-paths/azure/_excluded_audit_g4-compute.yaml index ec78a2a0be..80f05825e0 100644 --- a/src/privilege-escalation-paths/azure/_excluded_audit_g4-compute.yaml +++ b/src/privilege-escalation-paths/azure/_excluded_audit_g4-compute.yaml @@ -1,10 +1,8 @@ -# 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.' + reason: A credential or permission gain is documented, but it is deferred until the collector supplies serviceFabric.certSecretLinks[{clusterId,secretId,thumbprint,isAdmin,active}]. + Without a verified active cluster admin PFX-to-cluster link, a vault secret may be unrelated. - 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 diff --git a/src/privilege-escalation-paths/azure/_excluded_audit_g8-storage-msg.yaml b/src/privilege-escalation-paths/azure/_excluded_audit_g8-storage-msg.yaml index d1beba6936..64a6e0c76a 100644 --- a/src/privilege-escalation-paths/azure/_excluded_audit_g8-storage-msg.yaml +++ b/src/privilege-escalation-paths/azure/_excluded_audit_g8-storage-msg.yaml @@ -1,20 +1,25 @@ -# 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. + reason: A credential or permission gain is documented, but it is deferred until the collector supplies serviceBus.rules[{namespaceId,ruleId,rights}], + namespaces[{id,disableLocalAuth}]. The existing rule must carry the claimed right and SAS auth must be enabled. - 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. + reason: A credential or permission gain is documented, but it is deferred until the collector supplies serviceBus.geoDrRules[{aliasId,namespaceId,rights}], + namespaces[{id,disableLocalAuth}]. Alias existence, rule rights and local authentication decide the resulting + credential. - 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. + reason: A credential or permission gain is documented, but it is deferred until the collector supplies serviceBus.namespaces[{id,disableLocalAuth}], + rules[{namespaceId,ruleId,rights}]. New Manage rule requires enabled SAS auth and both write and key read-back + on the same namespace. - 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. + reason: A credential or permission gain is documented, but it is deferred until the collector supplies serviceBus.entityRules[{entityId,ruleId,rights}], + namespaces[{id,disableLocalAuth}]. Entity-scoped rules cannot be promoted to namespace-wide Manage. - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespacesqueuestopicsauthorizationruleswrite technique: Service Bus entity SAS rule creation source_revision: a66f094ede @@ -39,28 +44,35 @@ - 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. + reason: A credential or permission gain is documented, but it is deferred until the collector supplies storageAccounts[{id,allowSharedKeyAccess,publicNetworkAccess,networkAcls}]. + Shared Key disabled blocks use of listed keys. - 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. + reason: A credential or permission gain is documented, but it is deferred until the collector supplies storageAccounts[{id,allowSharedKeyAccess,publicNetworkAccess,networkAcls}]. + Rotated keys grant no usable data-plane access when Shared Key is disabled. - 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. + reason: A credential or permission gain is documented, but it is deferred until the collector supplies storageAccounts[{id,allowSharedKeyAccess,sasPolicy,enabledServices}]. + The requested SAS service, resource and permission flags must be valid and Shared Key enabled. - 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. + reason: A credential or permission gain is documented, but it is deferred until the collector supplies storageAccounts[{id,allowSharedKeyAccess,enabledServices}]. + A service SAS is limited to the requested service/resource and Shared Key must be enabled. - 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. + reason: A credential or permission gain is documented, but it is deferred until the collector supplies storageAccounts[{id,isHnsEnabled,isSftpEnabled}], + localUsers[{id,homeDirectory,permissionScopes,hasSshKey,hasPassword}]. SFTP and HNS must be enabled; created + user rights are limited to selected containers. - 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. + reason: A credential or permission gain is documented, but it is deferred until the collector supplies storageAccounts[{id,isHnsEnabled,isSftpEnabled}], + localUsers[{id,permissionScopes,hasPassword}]. Password rotation inherits only the existing local user container + scopes. - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-app-configuration-privesc.md#microsoftappconfigurationconfigurationstoreslistkeysaction technique: App Configuration access keys source_revision: a66f094ede diff --git a/src/privilege-escalation-paths/azure/_excluded_audit_s06.yaml b/src/privilege-escalation-paths/azure/_excluded_audit_s06.yaml new file mode 100644 index 0000000000..3a6acfa4cb --- /dev/null +++ b/src/privilege-escalation-paths/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/azure/_excluded_entraid.yaml b/src/privilege-escalation-paths/azure/_excluded_entraid.yaml index 236ffa77c4..e5ba6b6130 100644 --- a/src/privilege-escalation-paths/azure/_excluded_entraid.yaml +++ b/src/privilege-escalation-paths/azure/_excluded_entraid.yaml @@ -1,5 +1,3 @@ -# 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. @@ -26,7 +24,9 @@ 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. + reason: getPasswordSingleSignOnCredentials can reveal a stored third-party application username/password when + password SSO is configured; an external application identity target is required. + source_revision: 0b36331 - 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). diff --git a/src/privilege-escalation-paths/azure/_excluded_rbac.yaml b/src/privilege-escalation-paths/azure/_excluded_rbac.yaml index d23648c7c9..2c8abfe7bb 100644 --- a/src/privilege-escalation-paths/azure/_excluded_rbac.yaml +++ b/src/privilege-escalation-paths/azure/_excluded_rbac.yaml @@ -1,5 +1,3 @@ -# 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-authorization-privesc.md#permission-first-role-discovery technique: Permission-first role discovery reason: Enumeration guidance only; no privilege gain. @@ -80,19 +78,29 @@ 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: Data-plane key for job data; no identity gain. + reason: A credential or permission gain is documented, but it is deferred until azure_service_credential target + for a Quantum workspace key and an any_of action requirement. Either workspace action returns a key; the two + actions are alternatives, not a conjunction. - 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. + reason: A credential or permission gain is documented, but it is deferred until azure_service_credential target + for Purview Atlas Kafka rule, with exact Send/Listen rights; never infer Listen from a returned string. Generated + Event Hubs rule rights and receiver availability are not established by ARM permission alone. - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-redis-privesc.md#microsoftcacheredislistkeysaction technique: Redis listKeys / Managed Redis listKeys/regenerateKey - reason: Cache data access; no identity gain. + reason: A credential or permission gain is documented, but it is deferred until azure_service_credential target + for Redis keyspace access and machine-checked access-key authentication. The key is a Redis login, not an Azure + IAM principal; disabled key auth defeats use. - 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: Application-user impersonation inside Fluid containers (data plane), not an Azure/Entra identity. + reason: The returned Fluid tenant signing key permits JWT signing as Fluid application users; this is application-user + impersonation scoped to the Fluid server, not Azure/Entra identity control. + source_revision: 0b36331 - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-relay-privesc.md#relay-sas-key-disclosure technique: Relay authorization rule listkeys/regenerateKeys - reason: Network-boundary pivot through relays; no new identity. + reason: A credential or permission gain is documented, but it is deferred until azure_service_credential target + with Relay namespace/entity scope and rule Send, Listen, Manage rights. A SAS rule can have different rights; + listener takeover cannot follow from Send alone. - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-desktop-privesc.md#microsoftdesktopvirtualizationhostpoolsretrieveregistrationtokenaction technique: AVD host pool registration token reason: Requires an attacker-controlled compliant, domain/Entra-joined VM; session/credential capture is outside RBAC modelling. @@ -107,10 +115,14 @@ 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). + reason: A credential or permission gain is documented, but it is deferred until external_or_agent_credential target + with secret classification and downstream audience. The response may contain protected material, but listSecrets + alone does not identify a reusable principal. - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sre-agent-privesc.md#microsoftappagentsdataconnectorslistsecretsaction technique: SRE Agent data connector listSecrets - reason: External connector credentials; no Azure identity gain established. + reason: A credential or permission gain is documented, but it is deferred until external_service_credential target + keyed by connector provider and secret audience. A connector secret may authenticate to different backends and + scopes. - 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: Push notification abuse and registration data; no identity gain. @@ -134,7 +146,9 @@ 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: Service data-plane token for media; data access only. + reason: A credential or permission gain is documented, but it is deferred until azure_video_indexer_role target + for short-lived account Contributor token. The token grants VI account data-plane rights, not Azure subscription + administration. - 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. @@ -281,16 +295,24 @@ 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. + reason: Returns a reusable account-wide read/write master key when local key authentication is enabled; a scoped + Cosmos credential target is needed to avoid treating data-plane access as Azure identity control. + source_revision: 0b36331 - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbdatabaseaccountslistconnectionstringsaction technique: Cosmos DB listConnectionStrings - reason: Data-plane key; data access. + reason: For SQL API accounts the connection string embeds a reusable read/write master key; account API and local-key-auth + configuration must be checked before a scoped credential edge. + source_revision: 0b36331 - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbdatabaseaccountsreadonlykeysaction technique: Cosmos DB read-only keys - reason: Data read. + reason: Returns reusable account-wide read-only master keys; a scoped read-only credential target and local-key-auth + check are needed. + source_revision: 0b36331 - 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. + reason: Returns a reusable Semantic Reranker key for billed inference when key authentication is enabled; it grants + no Cosmos document or ARM access. + source_revision: 0b36331 - 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. @@ -299,7 +321,9 @@ reason: No attacker-controlled code; existing pipeline behaviour only. - 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: Returns a GitHub credential for the factory's repo; no Azure identity (rev 171e422; dataset sink-replacement section moved to post-exploitation). + reason: Returns a GitHub OAuth token for the factory integration. Repository rights depend on the token scope + and configured GitHub account; an external application identity target is needed. + source_revision: 0b36331 - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-data-factory-privesc.md#read-plaintext-parameters-from-pipeline-run-history technique: Pipeline run parameter read reason: Data read. @@ -344,16 +368,22 @@ 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. + reason: A credential or permission gain is documented, but it is deferred until azure_service_credential target + for SignalR or Web PubSub access key, service-specific local-auth condition. Key return grants service management + API authority, but Web PubSub may disable local auth. - 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. + reason: A credential or permission gain is documented, but it is deferred until azure_service_credential target + for temporary SignalR client JWT signer and known hub. The transient key mints client tokens, not a durable + Azure principal. - 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. + reason: A credential or permission gain is documented, but it is deferred until azure_application_client target + with Web PubSub hub binding and two-action conjunction. The page tests that generateToken alone gets HTTP 403; + write is also required. - 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. @@ -416,13 +446,16 @@ 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. + reason: A credential or permission gain is documented, but it is deferred until the collector supplies sql.elasticJobs[{agentId,jobId,stepId,credentialId,targetGroupId,targetDatabaseIds}]. + The stored credential and target group must belong to the same runnable job. - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsitessnippetswrite technique: SWA snippet injection reason: Client-side content injection; no Azure identity. - 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: Non-Azure (GitHub/Bitbucket/...) tokens. + reason: A credential or permission gain is documented, but it is deferred until external_service_credential target + with provider OAuth scopes and current-account ownership. The sourcecontrols response can contain OAuth tokens; + downstream rights depend on token scopes. - 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: Non-Azure repository write. @@ -431,7 +464,8 @@ 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: Static content deployment; no managed identity reached. + reason: A credential or permission gain is documented, but it is deferred until the collector supplies staticWebApps.deploymentAuth[{siteId,tokenEnabled,azureTokenAllowed}]. + A returned deployment token must be accepted by the site deployment endpoint. - 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. @@ -440,7 +474,9 @@ reason: Disruption. - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsitescreateinvitationaction technique: SWA user invitation - reason: App-level role, not an Azure principal. + reason: A credential or permission gain is documented, but it is deferred until azure_application_role target + for Static Web App protected-path role, plus invitation acceptance condition. An invitation only becomes a role + after a matching user accepts it. - 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. @@ -452,7 +488,9 @@ 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. + reason: A credential or permission gain is documented, but it is deferred until azure_storage_path target with + HNS ACL/ancestor-execute evaluator and separate read permission. ACL modification or owner change only permits + access after path ACL and read checks; runAsSuperUser bypasses ACL. - 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. @@ -461,13 +499,18 @@ 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. + reason: A credential or permission gain is documented, but it is deferred until azure_file_path target with ownership + and NTFS ACL evaluation. Taking ownership gives ability to edit ACL, not automatic file read. - 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. + reason: A credential or permission gain is documented, but it is deferred until azure_file_path target with NTFS + ACL evaluation and self-grant outcome. modifypermissions changes a file ACL; access depends on the granted ACE + and separate read action. - 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. + reason: A credential or permission gain is documented, but it is deferred until azure_file_path target with superuser + bypass outcome and file data-operation check. actassuperuser is an ACL bypass for file operations, not an ARM + role grant. - 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. @@ -560,8 +603,12 @@ technique: "Function content share code replacement" reason: "Covered by azure-functions-content-storage-write." - 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." + technique: Backup exfiltration + reason: The backup can disclose an Entra application client secret in app settings or connection strings, but + ARM configuration alone does not show whether the backed-up content contains a still-valid secret or identify + its service principal. The site must support backup, and the caller must provide a writable Storage SAS destination + and retrieve the ZIP. Exclude until content and credential validity can be established without inferring an + identity from backup/action alone. - 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." @@ -599,8 +646,11 @@ 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." + technique: Partner kubeconfig / listener token export + reason: The returned kubeconfig and hybrid-connection Listener token may grant appliance or relay access, but + their effective RBAC, relay-token scope and network reachability require response and appliance/relay facts + absent from the ARM configuration snapshot. The deleted azure-arc-resource-bridge-credential-export rule did + not establish an administrator target. - 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." @@ -686,8 +736,10 @@ 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." + technique: Inference account key regeneration + reason: Rotates and returns a reusable Semantic Reranker key for billed inference when key authentication is enabled; + it grants no Cosmos document or ARM access. + source_revision: 0b36331 - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftinferenceserviceinferenceaccountsinvokesemanticrerankeraction technique: "Semantic reranker invocation" reason: "Inference usage; no identity." @@ -704,8 +756,10 @@ 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: "On-prem SQL credential relay; no Azure identity." + technique: DMS IR auth key rogue worker + reason: Returns DMS IR registration keys, enabling a rogue worker when default-ir exists. Capturing source SQL + credentials additionally requires a migration job assigned to that worker. + source_revision: 0b36331 - 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." @@ -713,8 +767,10 @@ 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: "Unity Catalog privileges, not Azure RBAC." + technique: Unity Catalog storage credential abuse + reason: Unity Catalog temporary credentials can grant Azure Storage access through an Access Connector MI. Databricks + UC permissions, storage credential links and Azure Storage scope are required to evaluate this. + source_revision: 0b36331 - 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." @@ -782,8 +838,10 @@ 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: "MQTT broker access; no Azure identity." + technique: MQTT client backdoor + reason: Creating an MQTT client, group and permission binding grants persistent broker publish/subscribe authority + with attacker-held client credentials; this requires a scoped MQTT authority target. + source_revision: 0b36331 - 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." @@ -829,3 +887,40 @@ - 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." +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-arc-resource-bridge-privesc.md#export-customer-kubeconfig-and-ssh-credentials + technique: Export customer Arc Resource Bridge kubeconfig and SSH credentials + reason: The Actions can return appliance kubeconfigs and SSH key material, but the exported kubeconfig role, usable + Kubernetes RBAC, SSH server acceptance, network reachability and relay scope are not in the ARM configuration + snapshot. They do not establish appliance administrator, Kubernetes cluster-admin or Azure administration. A + scoped appliance/SSH credential target and measured host or Kubernetes authorization are needed before an identity + edge can be drawn. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-cosmosDB-privesc.md#microsoftdocumentdbmongoclusterslistconnectionstringsaction--mongoclustersusersread--userswrite + technique: MongoDB vCore native user creation + source_revision: 0b36331 + reason: users/write creates a native password user with configured data-plane rights. It does not register an + Entra principal; listConnectionStrings returns endpoint templates only. A native database-user target is needed + to represent the new credential without implying cluster administrator rights. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsdigitaltwinsinstanceswrite--managed-identity-attach-confused-deputy-foothold + technique: Attach a user-assigned identity to a Digital Twins instance and import with it + source_revision: 0b36331 + reason: Digital Twins only fetches an import-source Blob using its managed identity. The caller does not receive + a general MI token or its other role grants; disclosure depends on chosen NDJSON content and import parser/error + behavior. A scoped Blob-read confused-deputy target and content fact are needed. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsjobsimportswrite--bulk-graph-import-mass-poisoning--mi-confused-deputy-read + technique: Use an import job to read blobs with the Digital Twins instance identity + source_revision: 0b36331 + reason: Digital Twins only fetches an import-source Blob using its managed identity. The caller does not receive + a general MI token or its other role grants; disclosure depends on chosen NDJSON content and import parser/error + behavior. A scoped Blob-read confused-deputy target and content fact are needed. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-entra-id-governance-privesc.md#catalog-scoped-self-grant-privesc + technique: Catalog-scoped self-grant of an Entra role packaged in a catalog the source manages + source_revision: 0b36331 + reason: The cited page packages group membership or ownership, application roles and SharePoint roles. Direct + Entra directory-role packaging is not documented; role-assignable-group gain is already covered by azure-entraid-entitlement-catalog-self-grant-group. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftserialconsoleserialportsconnectaction + technique: Direct Serial Console login with an already known local guest password + source_revision: 0b36331 + reason: The connect action opens a console, but login requires a valid local guest account password already known + to the source. That credential, guest account state, console availability and IMDS reachability are host/runtime + facts absent from the Azure permission snapshot; connect/action alone cannot establish access to the VM managed + identities. diff --git a/src/privilege-escalation-paths/azure/_excluded_rbac_refresh_a.yaml b/src/privilege-escalation-paths/azure/_excluded_rbac_refresh_a.yaml index b240518fba..9311976f4a 100644 --- a/src/privilege-escalation-paths/azure/_excluded_rbac_refresh_a.yaml +++ b/src/privilege-escalation-paths/azure/_excluded_rbac_refresh_a.yaml @@ -1,4 +1,3 @@ -# 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. @@ -46,7 +45,9 @@ 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. + reason: A vaults/write permission can revive secret access only when the vault stores a stale secret-read access + policy for a source-controlled principal and the model can be switched to access policies. Requires a source-principal-to-access-policy + join and current permission model; otherwise UNKNOWN. - 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. @@ -106,7 +107,11 @@ 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_revision: 0b36331 + reason: A managed-app template may create an identity and assign roles through the deployment authorization. The + path is conditional on the exact definition, deployment scope and platform authorization permitting a role assignment + beyond the source rights. Missing authorization/template facts are UNKNOWN; do not infer gain from applications/write + alone. - 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. @@ -116,3 +121,12 @@ - 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. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#aks-cluster-credentials + technique: clusterUser kubeconfig on AKS + reason: The returned clusterUser identity has cluster-admin authority only if its effective Kubernetes RBAC grants + it; local accounts and absence of Entra integration do not prove that binding. The collector must read cluster + RBAC bindings for the returned subject; until then the path is UNKNOWN. +- source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#kubernetes-rbac-operations + technique: User or service-account impersonation to cluster admin + reason: Requires an impersonable user or service account with effective cluster-admin RBAC, including namespace + scope; no subject-to-binding collector exists, so evaluate UNKNOWN until collected. diff --git a/src/privilege-escalation-paths/azure/_excluded_rbac_refresh_b.yaml b/src/privilege-escalation-paths/azure/_excluded_rbac_refresh_b.yaml index 708d1cc57d..fa7604a0b1 100644 --- a/src/privilege-escalation-paths/azure/_excluded_rbac_refresh_b.yaml +++ b/src/privilege-escalation-paths/azure/_excluded_rbac_refresh_b.yaml @@ -1,5 +1,3 @@ -# 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. @@ -62,7 +60,9 @@ 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. + reason: A credential or permission gain is documented, but it is deferred until the collector supplies purview.governedSources[{accountId,sourceId,policyAuthorIds,publisherIds,policyIds,serviceKind}]. + Policy Author, registered source and separate publisher requirements decide whether a write can grant SQL/Storage + access. - 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. @@ -77,7 +77,9 @@ 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: Returns a Redis data-plane credential (cache read/alter, DoS); no Azure/Entra identity. + reason: A credential or permission gain is documented, but it is deferred until azure_service_credential target + for a Managed Redis database key and machine-checked access-key authentication. The key is confined to one database + and both actions are alternatives. - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-relay-privesc.md#azure-relay technique: Azure Relay introduction reason: Introductory section. @@ -119,10 +121,14 @@ 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: Impersonates the application backend inside the SignalR data plane (message interception/injection); no Azure/Entra identity. + reason: A credential or permission gain is documented, but it is deferred until azure_application_server target + for SignalR server connection, with data_action requirement and signer pairing. ServerConnection/write alone + does not prove a usable signed server connection. - 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: Data-plane signing material for client tokens; no Azure/Entra identity. + reason: A credential or permission gain is documented, but it is deferred until azure_service_credential target + for Web PubSub temporary signing material, with service-specific auth endpoint. The report names the wrong provider + action; the heading names Microsoft.SignalRService/WebPubSub/auth/accessKey/action. - 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. @@ -140,25 +146,32 @@ 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. + reason: A credential or permission gain is documented, but it is deferred until the collector supplies springApps.testEndpoints[{serviceId,appId,enabled,url,authRequired}]. + A key is useful only where the test endpoint is enabled; secrets exposure additionally depends on app routes/content. - 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. + reason: A credential or permission gain is documented, but it is deferred until the collector supplies springApps.testEndpoints[{serviceId,appId,enabled,url,authRequired}]. + Rotation returns a key but no app identity gain when the test endpoint is disabled. - 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. + reason: A credential or permission gain is documented, but it is deferred until external_service_credential target + keyed by APM backend and returned credential type. APM backend rights vary; a generic Azure data-plane admin + target would overstate access. - 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. + reason: A credential or permission gain is documented, but it is deferred until the collector supplies springApps.builderBindings[{builderId,appId,deploymentId,consumesFutureBuild,managedIdentityId}]. + A poisoned buildpack reaches an app identity only if a future build consumes that builder. - 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: Escalation inside the SQL engine's own permission model; SQL logins and database roles are not collected and are not Azure/Entra principals. + reason: A credential or permission gain is documented, but it is deferred until azure_sql_principal target and + SQL data-plane permission/role evaluator for ALTER ANY SERVER ROLE, IMPERSONATE and db_owner. ARM RBAC does + not decide SQL login/role membership or EXECUTE AS rights. - 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/azure/_excluded_rbac_refresh_c.yaml b/src/privilege-escalation-paths/azure/_excluded_rbac_refresh_c.yaml index ff377346cd..17a689b99b 100644 --- a/src/privilege-escalation-paths/azure/_excluded_rbac_refresh_c.yaml +++ b/src/privilege-escalation-paths/azure/_excluded_rbac_refresh_c.yaml @@ -1,5 +1,3 @@ -# 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." @@ -37,8 +35,10 @@ 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: "Data-plane access token for media insights; data read only, no Azure or Entra identity." + technique: Restricted-viewer access token - private insights + reason: A credential or permission gain is documented, but it is deferred until azure_video_indexer_role target + for short-lived Restricted Viewer token. The token is scoped to private insights and cannot download original + media. - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-video-indexer-privesc.md#permission-boundary technique: "Permission boundary" reason: "Background section." diff --git a/src/privilege-escalation-paths/azure/arc.yaml b/src/privilege-escalation-paths/azure/arc.yaml index f9504fbb44..49876be308 100644 --- a/src/privilege-escalation-paths/azure/arc.yaml +++ b/src/privilege-escalation-paths/azure/arc.yaml @@ -1,9 +1,3 @@ -# 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 @@ -33,7 +27,6 @@ - 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: "" - - id: azure-arc-hybrid-connectivity-entra-ssh provider: azure service: arc @@ -67,35 +60,3 @@ references: - https://learn.microsoft.com/en-us/azure/azure-arc/servers/ssh-arc-overview notes: "" - -- 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: Appliance listKeys / listClusterUserCredential return admin credentials of the resource bridge appliance cluster. - requires: - all_of: [] - any_of: - - - action: Microsoft.ResourceConnector/appliances/listKeys/action - scope: "{target.scope}" - - - action: Microsoft.ResourceConnector/appliances/listClusterUserCredential/action - scope: "{target.scope}" - target: - kind: azure_dataplane_admin - selector: - any_principal_in_scope: true - scope: inherited_scope - aggregate_as: "Arc resource bridge appliance admins of {target.scope}" - conditions: - - id: appliance_reachable - description: The appliance control plane on the on-premises network must be reachable from the source; the bridge's private-cloud credentials are stored inside it. - 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 the customer and partner credential sections of the page. diff --git a/src/privilege-escalation-paths/azure/batch.yaml b/src/privilege-escalation-paths/azure/batch.yaml index 5c18672c6f..ebc227c669 100644 --- a/src/privilege-escalation-paths/azure/batch.yaml +++ b/src/privilege-escalation-paths/azure/batch.yaml @@ -1,7 +1,3 @@ -# 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} is the Batch account owning the pool. - - id: azure-batch-shared-key-task-submission provider: azure service: batch @@ -35,7 +31,6 @@ references: - https://learn.microsoft.com/en-us/azure/batch/managed-identity-pools notes: regeneratekeys also disrupts legitimate key users. - - id: azure-batch-job-task-submission provider: azure service: batch @@ -71,7 +66,6 @@ references: - https://learn.microsoft.com/en-us/azure/batch/batch-role-based-access-control notes: HackTricks cites the jobs/* and jobSchedules/* wildcards of the built-in role. Microsoft's Batch data-action list has no separate tasks action, so jobs/write (or jobSchedules/write) is the narrowest data action covering task add. - - id: azure-batch-pool-write-starttask provider: azure service: batch @@ -102,7 +96,6 @@ - https://learn.microsoft.com/en-us/rest/api/batchmanagement/pool/update - https://learn.microsoft.com/en-us/azure/batch/managed-identity-pools notes: Attaching a new user-assigned identity to a pool is modelled in azure-batch-pool-write-assign-user-assigned-identity. - - id: azure-batch-pool-write-assign-user-assigned-identity provider: azure service: batch @@ -135,35 +128,38 @@ references: - https://learn.microsoft.com/en-us/azure/batch/managed-identity-pools notes: "" - - id: azure-batch-application-package-poisoning provider: azure service: batch title: Replace a Batch application package version used by pools source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-batch-privesc.md#microsoftbatchbatchaccountsapplicationsversionswrite--activateaction--application-package-supply-chain-poisoning source_revision: 171e422 - summary: Pools or tasks that reference and execute an application package version the source replaced run its code with the pool identities. + summary: Pools or tasks that reference and execute an application package version the source replaced run its + code with the pool identities. requires: all_of: - - action: Microsoft.Batch/batchAccounts/applications/versions/write - scope: "{target.host_resource}" - - action: Microsoft.Batch/batchAccounts/applications/versions/activate/action - scope: "{target.host_resource}" + - action: Microsoft.Batch/batchAccounts/applications/write + scope: '{target.host_resource}' + - action: Microsoft.Batch/batchAccounts/applications/versions/write + scope: '{target.host_resource}' + - action: Microsoft.Batch/batchAccounts/applications/versions/activate/action + scope: '{target.host_resource}' target: kind: azure_managed_identity selector: attached_to_service: Microsoft.Batch/batchAccounts/pools managed_identity_type: user_assigned scope: inherited_scope - aggregate_as: "Pool identities of Batch account {target.host_resource}" + aggregate_as: Pool identities of Batch account {target.host_resource} conditions: - - id: package_referenced_and_executed - description: A pool or task must reference the poisoned package version (or the default version) and execute its contents; packages are deployed when nodes join or tasks start. + - id: package_referenced_and_executed + description: A pool or task must reference the poisoned package version (or the default version) and execute + its contents; packages are deployed when nodes join or tasks start. blockers: - - azure_deny_assignment + - azure_deny_assignment confidence: conditional severity: high - mitigation: Restrict application version write/activate and pin explicit package versions. + mitigation: Restrict applications/write, application version write/activate, and pin explicit package versions. references: - - https://learn.microsoft.com/en-us/azure/batch/batch-application-packages - notes: "" + - https://learn.microsoft.com/en-us/azure/batch/batch-application-packages + notes: '' diff --git a/src/privilege-escalation-paths/azure/confidential_ledger.yaml b/src/privilege-escalation-paths/azure/confidential_ledger.yaml index e40e0c4612..d7ec162f3d 100644 --- a/src/privilege-escalation-paths/azure/confidential_ledger.yaml +++ b/src/privilege-escalation-paths/azure/confidential_ledger.yaml @@ -1,30 +1,35 @@ -# 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 ledger's aadBasedSecurityPrincipals list is part of the ARM resource, so ledgers/write grants the Administrator data-plane role. + summary: Reading the existing ledger configuration and writing a principal list that contains an Administrator + lets the source grant itself the ledger Administrator data-plane role. requires: all_of: - - action: Microsoft.ConfidentialLedger/ledgers/write - scope: "{target.scope}" + - action: Microsoft.ConfidentialLedger/ledgers/read + scope: '{target.scope}' + - action: Microsoft.ConfidentialLedger/ledgers/write + scope: '{target.scope}' target: kind: azure_dataplane_admin selector: any_principal_in_scope: true scope: inherited_scope - aggregate_as: "Confidential Ledger administrators of {target.scope}" - conditions: [] + aggregate_as: Confidential Ledger administrators of {target.scope} + conditions: + - id: administrator_retained + description: The submitted aadBasedSecurityPrincipals/certBasedSecurityPrincipals list must contain at least + one Administrator. Adding the source itself as Administrator satisfies this constraint; preserving current + principals requires reading the list first. blockers: - - azure_deny_assignment + - azure_deny_assignment confidence: derived severity: medium - mitigation: Restrict ledgers/write and monitor aadBasedSecurityPrincipals changes. + mitigation: Restrict ledgers/read and ledgers/write; monitor aadBasedSecurityPrincipals and certBasedSecurityPrincipals + changes. references: - - https://learn.microsoft.com/en-us/rest/api/confidentialledger/ledger/update - - https://learn.microsoft.com/en-us/azure/confidential-ledger/manage-azure-ad-users - notes: "" + - https://learn.microsoft.com/en-us/rest/api/confidentialledger/ledger/update + - https://learn.microsoft.com/en-us/azure/confidential-ledger/manage-azure-ad-users + notes: '' diff --git a/src/privilege-escalation-paths/azure/container_registry.yaml b/src/privilege-escalation-paths/azure/container_registry.yaml index 04ad40b942..4b462a6bf7 100644 --- a/src/privilege-escalation-paths/azure/container_registry.yaml +++ b/src/privilege-escalation-paths/azure/container_registry.yaml @@ -1,6 +1,3 @@ -# 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 @@ -29,7 +26,6 @@ references: - https://learn.microsoft.com/en-us/azure/container-registry/container-registry-tasks-authentication-managed-identity notes: A newly created system-assigned task identity has no roles; value comes from existing identity-bearing tasks. - - id: azure-acr-task-assign-user-assigned-identity provider: azure service: container_registry @@ -62,7 +58,6 @@ references: - https://learn.microsoft.com/en-us/azure/container-registry/container-registry-tasks-authentication-managed-identity notes: '' - - id: azure-acr-push-restart-aci-consumer provider: azure service: container_registry @@ -117,7 +112,6 @@ references: - https://learn.microsoft.com/en-us/azure/container-registry/container-registry-image-lock notes: The repository content pair (both read and write are required for the manifest PUT) applies to registries using ABAC repository permissions. Consumers that only re-pull on their own (scale-out, node replacement, scheduled jobs) are not modelled because the image-to-registry consumer link is not a selector yet. - - id: azure-acr-push-restart-containerapp-consumer provider: azure service: container_registry @@ -173,3 +167,38 @@ - https://learn.microsoft.com/en-us/azure/container-registry/container-registry-rbac-abac-repository-permissions - https://learn.microsoft.com/en-us/azure/container-registry/container-registry-image-tag-version notes: HackTricks observed that replacing the tag does not hot-reload the running revision, while a revision restart pulled the new digest and ran it with the app identity. +- id: azure-acr-verified-image-secret + provider: azure + service: container_registry + title: Pull ACR image with verified principal credential + source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/historical-cross-tenant-vulnerabilities.md#cross-subscription-not-cross-tenant-abuse-worth-noting + source_revision: 0b36331 + summary: Read an image layer containing a validated credential for another cloud principal. + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + requires: + all_of: + - action: Microsoft.ContainerRegistry/registries/pull/read + scope: '{pivot}' + target: + kind: azure_service_principal + selector: + azure_challenge_fact: azure-acr-verified-image-secret + scope: any + aggregate_as: Pull ACR image with verified principal credential targets + conditions: + - id: verified_runtime_evidence + description: Exact source, target and successful credential or token access must be attested; absent evidence + remains UNKNOWN. + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + confidence: conditional + severity: high + mitigation: Remove the vulnerable access path or exposed credential. + references: + - https://learn.microsoft.com/en-us/azure/container-registry/container-registry-roles + notes: 'Collector fact required: azure_privesc_challenge_evidence; exact technique/source/target evidence required, + absent => UNKNOWN.' diff --git a/src/privilege-escalation-paths/azure/cosmos_db.yaml b/src/privilege-escalation-paths/azure/cosmos_db.yaml index f331c70d7c..807190c8e8 100644 --- a/src/privilege-escalation-paths/azure/cosmos_db.yaml +++ b/src/privilege-escalation-paths/azure/cosmos_db.yaml @@ -1,6 +1,3 @@ -# 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 @@ -28,7 +25,6 @@ references: - https://learn.microsoft.com/en-us/azure/cosmos-db/how-to-setup-rbac notes: The page uses a custom role; built-in Cosmos DB Built-in Data Contributor makes definitions/write unnecessary. - - id: azure-cosmos-mongodb-user-definition-write provider: azure service: cosmos_db @@ -60,7 +56,6 @@ references: - https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/how-to-setup-rbac notes: '' - - id: azure-cosmos-mongocluster-admin-password provider: azure service: cosmos_db @@ -90,7 +85,6 @@ references: - https://learn.microsoft.com/en-us/azure/cosmos-db/mongodb/vcore/ notes: '' - - id: azure-cosmos-other-api-role-assignment-write provider: azure service: cosmos_db @@ -137,33 +131,3 @@ references: - https://learn.microsoft.com/en-us/rest/api/cosmos-db-resource-provider/ notes: Action names follow the ARM resource types cassandraRoleAssignments, gremlinRoleAssignments, tableRoleAssignments and mongoMIRoleAssignments in the Cosmos DB resource provider REST API; they are not yet listed on the Microsoft RBAC operations page. - -- 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 can obtain administrative data-plane access on the MongoDB vCore cluster. - requires: - all_of: - - action: Microsoft.DocumentDB/mongoClusters/users/write - scope: '{target.scope}' - target: - kind: azure_dataplane_admin - selector: - any_principal_in_scope: true - scope: inherited_scope - aggregate_as: MongoDB vCore cluster admins of {target.scope} - conditions: - - id: entra_auth_enabled - description: Microsoft Entra authentication must be enabled on the cluster. - - 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: '' diff --git a/src/privilege-escalation-paths/azure/databases.yaml b/src/privilege-escalation-paths/azure/databases.yaml index 9b4e17cbb0..4771729698 100644 --- a/src/privilege-escalation-paths/azure/databases.yaml +++ b/src/privilege-escalation-paths/azure/databases.yaml @@ -1,6 +1,3 @@ -# 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 @@ -28,7 +25,6 @@ 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 @@ -56,7 +52,6 @@ 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 @@ -84,7 +79,6 @@ 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 @@ -114,7 +108,6 @@ 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 @@ -144,7 +137,6 @@ 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 @@ -172,7 +164,6 @@ 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 @@ -200,7 +191,6 @@ references: - https://learn.microsoft.com/en-us/azure/azure-sql/database/authentication-aad-configure notes: Sourced from the HackTricks SQL persistence page, which lists the Managed Instance equivalents of the SQL privesc page's control-plane techniques. - - id: azure-sqlmi-admin-password-reset provider: azure service: databases @@ -230,3 +220,41 @@ references: - https://learn.microsoft.com/en-us/azure/azure-sql/database/authentication-azure-ad-only-authentication notes: Disruptive to clients using the old password. +- id: azure-audit-elastic-jobs-run-arbitrary-t-sql-through-jobagentsjobsstepswrite-executi + provider: azure + service: sql + title: 'Elastic Jobs: run arbitrary T-SQL through jobAgents/jobs/steps/write + executions/write' + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sql-privesc.md#elastic-jobs-run-arbitrary-t-sql-through-jobagentsjobsstepswrite--executionswrite + summary: arbitrary T-SQL as stored credential across target databases + requires: + all_of: + - action: Microsoft.Sql/servers/jobAgents/jobs/steps/write + scope: '{target.scope}' + - action: Microsoft.Sql/servers/jobAgents/jobs/executions/write + scope: '{target.scope}' + - action: Microsoft.Sql/servers/jobAgents/credentials/read + scope: '{target.scope}' + - action: Microsoft.Sql/servers/jobAgents/targetGroups/read + scope: '{target.scope}' + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-audit-elastic-jobs-run-arbitrary-t-sql-through-jobagentsjobsstepswrite-executi + scope: inherited_scope + aggregate_as: 'Elastic Jobs: run arbitrary T-SQL through jobAgents/jobs/steps/write + executions/write on {target.scope}' + outcome: workload_execution + conditions: + - id: same_resource_binding + description: All actions must apply to the same service resource and the referenced child object. + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + 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/azure-sql/database/elastic-jobs-overview + notes: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must + evaluate UNKNOWN. Collector fact required: sql.elasticJobs.' diff --git a/src/privilege-escalation-paths/azure/databricks.yaml b/src/privilege-escalation-paths/azure/databricks.yaml index 27c807b9c5..8de062a3ee 100644 --- a/src/privilege-escalation-paths/azure/databricks.yaml +++ b/src/privilege-escalation-paths/azure/databricks.yaml @@ -1,6 +1,3 @@ -# Azure Databricks techniques (declarative only). -# Source: hacktricks-cloud az-databricks-privesc.md (rev 171e422). - - id: azure-databricks-assign-workspace-admin provider: azure service: databricks @@ -30,3 +27,35 @@ references: - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/analytics notes: Workspace admins may further use identities configured on workspace compute; that is workspace-dependent and not modelled. +- id: azure-databricks-uc-temporary-storage-credential + provider: azure + service: databricks + title: Obtain temporary Azure Storage authority through Unity Catalog + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-databricks-privesc.md#unity-catalog-storage-credential--external-location-abuse + source_revision: 0b36331 + summary: A Unity Catalog principal with rights over a storage credential or external location can request temporary + Azure Storage tokens or SAS through an Access Connector managed identity. + requires: + all_of: [] + target: + kind: azure_verified_authority + scope: inherited_scope + outcome: permission_grant + grants: + - Storage Blob read/write only where the Access Connector and UC privilege permit + selector: + azure_challenge_fact: azure-databricks-uc-temporary-storage-credential + confidence: conditional + severity: high + mitigation: Limit UC storage credential privileges and Access Connector Storage Blob roles. + references: + - https://docs.databricks.com/en/connect/unity-catalog/cloud-storage/azure-managed-identities.html + notes: 'UNKNOWN until UC permission and credential-to-connector facts are collected; no full MI role propagation. + Collector fact required: see request queue.' + source_kind: + - azure_user + - azure_service_principal + conditions: + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. diff --git a/src/privilege-escalation-paths/azure/digital_twins.yaml b/src/privilege-escalation-paths/azure/digital_twins.yaml index c9db184e76..e69de29bb2 100644 --- a/src/privilege-escalation-paths/azure/digital_twins.yaml +++ b/src/privilege-escalation-paths/azure/digital_twins.yaml @@ -1,70 +0,0 @@ -# Azure Digital Twins techniques (declarative only). -# Source: hacktricks-cloud az-digital-twins-privesc.md (rev 171e422). -# Import jobs read the input blob with the instance's managed identity (confused deputy). The gain is -# limited to blob reads of NDJSON content the import parses, not the identity's full privileges. - -- id: azure-digitaltwins-import-job-identity-read - provider: azure - service: digital_twins - title: Use an import job to read blobs with the Digital Twins instance identity - 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 - summary: An import job pointed at a blob the source cannot read makes the instance identity fetch it, leaking parse errors or importing its content into the graph. - requires: - all_of: - - action: Microsoft.DigitalTwins/jobs/imports/write - data_action: true - scope: "{target.host_resource}" - target: - kind: azure_managed_identity - selector: - attached_to_service: Microsoft.DigitalTwins/digitalTwinsInstances - scope: inherited_scope - aggregate_as: "Managed identities of Digital Twins instance {target.host_resource}" - conditions: - - id: partial_blob_read_only - description: Only Storage Blob read through the instance identity is gained, and only for content readable as import NDJSON or surfaced in the job's error output. - blockers: - - azure_deny_assignment - confidence: conditional - severity: medium - mitigation: Restrict jobs/imports/write and grant the instance identity only the import container. - references: - - https://learn.microsoft.com/en-us/azure/digital-twins/concepts-apis-sdks#bulk-import-with-the-jobs-api - notes: Partial identity gain; evaluator should not propagate the identity's ARM role assignments. - -- id: azure-digitaltwins-assign-identity-import - provider: azure - service: digital_twins - title: Attach a user-assigned identity to a Digital Twins instance and import with it - source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-digital-twins-privesc.md#microsoftdigitaltwinsdigitaltwinsinstanceswrite--managed-identity-attach-confused-deputy-foothold - source_revision: 171e422 - summary: An identity attached to an instance the source controls is used by import jobs to read blobs on the source's behalf. - requires: - all_of: - - action: Microsoft.ManagedIdentity/userAssignedIdentities/assign/action - scope: '{target.id}' - - action: Microsoft.DigitalTwins/digitalTwinsInstances/write - scope: '{pivot}' - - action: Microsoft.DigitalTwins/jobs/imports/write - data_action: true - scope: '{pivot}' - pivot_resource_type: Microsoft.Resources/resourceGroups|Microsoft.DigitalTwins/digitalTwinsInstances - target: - kind: azure_managed_identity - selector: - managed_identity_type: user_assigned - azure_identity_assignable_in_scope: true - scope: inherited_scope - aggregate_as: User-assigned identities assignable in {scope} - conditions: - - id: partial_blob_read_only - description: Only Storage Blob read through the identity is gained, and only for content readable as import NDJSON or surfaced in the job's error output. - blockers: - - azure_deny_assignment - confidence: conditional - severity: medium - mitigation: Restrict userAssignedIdentities/assign/action and digitalTwinsInstances/write. - references: - - https://learn.microsoft.com/en-us/azure/digital-twins/how-to-set-up-instance-cli#enable-managed-identity-for-the-instance - notes: Partial identity gain; evaluator should not propagate the identity's ARM role assignments. diff --git a/src/privilege-escalation-paths/azure/entraid_apps.yaml b/src/privilege-escalation-paths/azure/entraid_apps.yaml index 63f9d2897f..b19b6d987e 100644 --- a/src/privilege-escalation-paths/azure/entraid_apps.yaml +++ b/src/privilege-escalation-paths/azure/entraid_apps.yaml @@ -1,19 +1,3 @@ -# 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 @@ -46,7 +30,6 @@ - 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 exactly app registrations whose application object lives in this tenant (Microsoft first-party and other-tenant multi-tenant apps have no local application object). A role assignment scoped to a single app registration (directoryScopeId "/") reaches only that app. allProperties/update includes the credential property set. - - id: azure-entraid-app-myorg-credentials-update provider: azure service: entraid @@ -78,7 +61,6 @@ 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. - - id: azure-entraid-app-owners-update provider: azure service: entraid @@ -107,7 +89,6 @@ references: - https://learn.microsoft.com/en-us/graph/api/application-post-owners?view=graph-rest-1.0 notes: Ownership grants credential management but not the ability 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 @@ -140,7 +121,6 @@ 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 (e.g. via Application.ReadWrite.OwnedBy). Severity should be raised to critical when the owned app's SP holds privileged roles / Graph app roles. Source is the owners/update section, which states that ownership gives control of the app's credentials; az-oauth-apps-phishing.md#entra-id-applications-admin (the previous source) only covers redirect-URI and requested-permission changes, which stay excluded. - - id: azure-entraid-sp-credentials-update provider: azure service: entraid @@ -175,7 +155,6 @@ - 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: Managed-identity service principals are excluded (their credentials are platform-managed). The app instance property lock on the home application blocks credential changes on its service principals; disabling it requires update rights on the application object, which the evaluator should model through the application entries. - - id: azure-entraid-sp-owners-update provider: azure service: entraid @@ -205,7 +184,6 @@ references: - https://learn.microsoft.com/en-us/graph/api/serviceprincipal-post-owners?view=graph-rest-1.0 notes: Owners of a service principal can manage its credentials unless the app instance property lock (servicePrincipalLockConfiguration) blocks it. - - id: azure-entraid-sp-owner-credentials provider: azure service: entraid @@ -235,7 +213,6 @@ references: - https://learn.microsoft.com/en-us/graph/api/serviceprincipal-delete-owners?view=graph-rest-1.0 notes: 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 @@ -265,7 +242,6 @@ - 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). The lock configuration only blocks service-principal-object credentials; app-object credentials remain possible for apps registered in this tenant. - - id: azure-entraid-graph-approleassignment-readwrite-all provider: azure service: entraid @@ -293,7 +269,6 @@ references: - https://learn.microsoft.com/en-us/graph/api/serviceprincipal-post-approleassignments?view=graph-rest-1.0 notes: Microsoft explicitly warns this permission lets an app grant additional privileges to itself. The directory-role reach depends on chaining through RoleManagement.ReadWrite.Directory; newly granted app roles only appear in newly issued tokens. - - id: azure-entraid-agent-blueprint-credentials provider: azure service: entraid @@ -322,7 +297,6 @@ - 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: The directory permission agentIdentityBlueprints/credentials/update is held by Agent ID Administrator, AI Administrator and Global Administrator (built-in role definitions, checked 2026-10). Blueprint owners who can manage the blueprint application are covered by the generic application owner entries; the extra child-agent reach applies to them as well. Entra Agent ID is a newer (preview-era) feature; validate behaviour per tenant. - - id: azure-entraid-graph-delegatedpermissiongrant-allprincipals provider: azure service: entraid @@ -349,3 +323,33 @@ references: - https://learn.microsoft.com/en-us/graph/api/oauth2permissiongrant-post?view=graph-rest-1.0 notes: Bypasses the admin-consent boundary but not user authentication; edges are conditional on user interaction and should not be treated as silent takeover. +- id: azure-entraid-verified-premfa-broci-keyvault + provider: azure + service: entraid_apps + title: Verified pre-MFA broker token to Key Vault + source: src/pentesting-cloud/azure-security/az-basic-information/az-tokens-and-public-applications.md#pre-mfa-tokens-and-downstream-conditional-access-gaps + source_revision: 0b36331 + summary: A broker token issued before MFA succeeds in obtaining Key Vault authority. + source_kind: azure_user + requires: + all_of: [] + target: + kind: azure_verified_authority + selector: + azure_challenge_fact: azure-entraid-verified-premfa-broci-keyvault + scope: any + aggregate_as: Verified pre-MFA broker token to Key Vault targets + conditions: + - id: verified_runtime_evidence + description: Exact source, target and successful credential or token access must be attested; absent evidence + remains UNKNOWN. + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + confidence: conditional + severity: high + mitigation: Remove the vulnerable access path or exposed credential. + references: + - https://learn.microsoft.com/en-us/entra/identity/conditional-access/overview + notes: 'Collector fact required: azure_privesc_challenge_evidence; exact technique/source/target evidence required, + absent => UNKNOWN.' diff --git a/src/privilege-escalation-paths/azure/entraid_governance.yaml b/src/privilege-escalation-paths/azure/entraid_governance.yaml index e4036edc38..a70e36c517 100644 --- a/src/privilege-escalation-paths/azure/entraid_governance.yaml +++ b/src/privilege-escalation-paths/azure/entraid_governance.yaml @@ -1,12 +1,3 @@ -# 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. 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}, -# 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 service: entraid @@ -45,45 +36,6 @@ - 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. - 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 - 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-access-package-guest-auto-assignment provider: azure service: entraid @@ -112,7 +64,6 @@ references: - https://learn.microsoft.com/en-us/entra/id-governance/entitlement-management-access-package-auto-assignment-policy notes: Analogous to azure-entraid-dynamic-group-guest-invite for dynamic groups. - - id: azure-entraid-entitlement-auto-assignment-persistence provider: azure service: entraid diff --git a/src/privilege-escalation-paths/azure/key_vault.yaml b/src/privilege-escalation-paths/azure/key_vault.yaml index de924c84f7..57679fa1ba 100644 --- a/src/privilege-escalation-paths/azure/key_vault.yaml +++ b/src/privilege-escalation-paths/azure/key_vault.yaml @@ -1,6 +1,3 @@ -# Azure Key Vault techniques (declarative only). -# Source: hacktricks-cloud az-key-vault-privesc.md (rev 171e422). - - id: azure-keyvault-secret-read-sp-credentials provider: azure service: key_vault @@ -11,13 +8,11 @@ requires: all_of: [] any_of: - - - action: Microsoft.KeyVault/vaults/accessPolicies/write - scope: '{pivot}' - - - action: Microsoft.KeyVault/vaults/write - scope: '{pivot}' - - - action: Microsoft.KeyVault/vaults/secrets/getSecret/action - data_action: true - scope: '{pivot}' + - - action: Microsoft.KeyVault/vaults/accessPolicies/write + scope: '{pivot}' + - - action: Microsoft.KeyVault/vaults/secrets/getSecret/action + data_action: true + scope: '{pivot}' pivot_resource_type: Microsoft.KeyVault/vaults target: kind: azure_service_principal @@ -26,20 +21,24 @@ scope: any aggregate_as: Service principals with credentials stored in {pivot} conditions: - - id: permission_model - description: accessPolicies/write and vaults/write (which can rewrite the vault's accessPolicies property) apply only when enableRbacAuthorization is false/null; getSecret applies only when it is true. - - id: credential_content_unknown - description: The vault must actually hold a client secret or certificate private key of a service principal; content is not visible from RBAC. - - id: network_reachable - description: Vault firewall/private endpoint must allow the source (vaults/write can change network ACLs). + - id: permission_model + description: accessPolicies/write and vaults/write (which can rewrite the vault's accessPolicies property) apply + only when enableRbacAuthorization is false/null; getSecret applies only when it is true. + - id: credential_content_unknown + description: The vault must actually hold a client secret or certificate private key of a service principal; + content is not visible from RBAC. + - id: network_reachable + description: Vault firewall/private endpoint must allow the source (vaults/write can change network ACLs). blockers: [] confidence: conditional severity: high - mitigation: Use Azure RBAC vault permission model, restrict accessPolicies/write, vaults/write (Contributor, Key Vault Contributor) and Secrets User roles, and avoid storing SP secrets where managed identities suffice. + mitigation: Use Azure RBAC vault permission model, restrict accessPolicies/write, vaults/write (Contributor, Key + Vault Contributor) and Secrets User roles, and avoid storing SP secrets where managed identities suffice. references: - - https://learn.microsoft.com/en-us/azure/key-vault/general/rbac-access-policy - notes: The getSecret alternative is the RBAC-model equivalent requested by the catalog semantics; HackTricks documents only the access-policy grant on this page. HackTricks rev 171e422 states vaults/write alone is not the access-policy write operation; the vaults/write branch relies on a full vault PUT replacing properties.accessPolicies (and on the enableRbacAuthorization toggle described on the same page), so treat that branch as the least certain. Certificates are read through secrets (the private key is only returned by the secret), which this entry already covers. - + - https://learn.microsoft.com/en-us/azure/key-vault/general/rbac-access-policy + notes: The vaults/write toggle is excluded from this entry until the evaluator can prove a stale access policy + for a source-controlled principal with secret read. Direct accessPolicies/write on an access-policy vault and + secrets/getSecret remain covered. - id: azure-keyvault-key-sign-sp-client-assertion provider: azure service: key_vault @@ -77,7 +76,6 @@ references: - https://learn.microsoft.com/en-us/entra/identity-platform/certificate-credentials notes: Exportable certificates are already reachable through secrets/getSecret (azure-keyvault-secret-read-sp-credentials); this entry covers the non-exportable/HSM case. Forgery against non-Entra consumers (custom JWT, SAML, code signing) stays excluded. - - id: azure-keyvault-template-deployment-secret-reference provider: azure service: key_vault diff --git a/src/privilege-escalation-paths/azure/kubernetes.yaml b/src/privilege-escalation-paths/azure/kubernetes.yaml index 3ccdf12a4e..35be32defd 100644 --- a/src/privilege-escalation-paths/azure/kubernetes.yaml +++ b/src/privilege-escalation-paths/azure/kubernetes.yaml @@ -1,6 +1,3 @@ -# 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 @@ -29,36 +26,6 @@ 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: 171e422 - 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: 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 - 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: HackTricks (rev 171e422) states the user kubeconfig is broad only on non-Entra local-account clusters. - - id: azure-hybrid-k8s-list-cluster-admin-credential provider: azure service: kubernetes @@ -85,7 +52,6 @@ mitigation: Restrict listClusterAdminCredential on hybrid clusters. references: [] notes: User-credential actions on connected/provisioned clusters are identity-bound and not modelled as a gain. - - id: azure-aks-azure-rbac-k8s-rbac-write provider: azure service: kubernetes @@ -134,7 +100,6 @@ references: - https://learn.microsoft.com/en-us/azure/aks/manage-azure-rbac notes: Exact data-action names taken from the Azure RBAC provider operations for Microsoft.ContainerService. Kubernetes RBAC escalation prevention means binding write alone is insufficient (bind on the referenced role is also checked), and escalate is useless without role write. - - id: azure-aks-access-profile-list-credential provider: azure service: kubernetes @@ -165,7 +130,6 @@ 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 @@ -199,7 +163,6 @@ - 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: Action names verified on Microsoft Learn (access-private-cluster lists runcommand/action and commandResults/read). BloodHound models this as AZAKSContributor. Network reachability to the API server is not needed. - - id: azure-aks-managedclusters-write-enable-local-accounts provider: azure service: kubernetes @@ -229,7 +192,6 @@ references: - https://learn.microsoft.com/en-us/azure/aks/manage-local-accounts-managed-azure-ad notes: Pairs with azure-aks-list-cluster-admin-credential; this entry removes the local-accounts blocker. - - id: azure-aks-managedclusters-write-admin-group provider: azure service: kubernetes @@ -259,7 +221,6 @@ references: - https://learn.microsoft.com/en-us/azure/aks/enable-authentication-microsoft-entra-id notes: "" - - id: azure-aks-vmss-node-run-command provider: azure service: kubernetes @@ -289,47 +250,40 @@ - 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 any Uniform scale set, including AKS node pools. Kubernetes privileges from node credentials (kubelet, projected tokens) are handled by the k8s catalog node edges and are not claimed here. - - id: azure-aks-azure-rbac-impersonate provider: azure service: kubernetes title: Impersonate privileged Kubernetes groups, users or service accounts through Azure RBAC data actions source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-kubernetes-privesc.md#kubernetes-rbac-operations source_revision: a66f094ede - summary: The source can send API requests as system:masters or another admin identity without creating any binding. + summary: The source can impersonate system:masters through the groups/impersonate data action. requires: all_of: [] any_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}" - - - action: Microsoft.ContainerService/managedClusters/serviceaccounts/impersonate/action - data_action: true - scope: "{target.scope}" + - - action: Microsoft.ContainerService/managedClusters/groups/impersonate/action + data_action: true + 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}" + 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: impersonated_identity_is_admin - description: groups impersonation reaches system:masters directly; users and serviceaccounts impersonation reaches cluster-admin only if an admin-bound user or service account exists. - - id: namespace_scoped_grant - description: Grants scoped to a namespace limit impersonation to that namespace's authorization checks. + - id: azure_rbac_for_k8s_enabled + description: Only when Azure RBAC for Kubernetes authorization is enabled on the cluster. + - id: namespace_scoped_grant + description: Grants scoped to a namespace limit impersonation to that namespace's authorization checks. blockers: [] confidence: conditional severity: critical - mitigation: Do not grant impersonate data actions outside cluster administrators; review custom roles carrying Microsoft.ContainerService/managedClusters/*. + 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: Fleet member equivalents (fleets/members/...) need a fleet-to-member-cluster mapping, and namespace-scoped RBAC Writer secret read (service-account token theft) needs azure-side k8s_service_account targets; neither is expressible in the current schema. - + - https://learn.microsoft.com/en-us/azure/aks/manage-azure-rbac + notes: 'users/impersonate and serviceaccounts/impersonate are separate conditional paths: an impersonable subject + must have effective cluster-admin RBAC. Do not claim cluster admin from those actions without the subject-to-binding + join.' - id: azure-aro-list-credentials provider: azure service: kubernetes @@ -359,7 +313,6 @@ references: - https://learn.microsoft.com/en-us/azure/openshift/tutorial-connect-cluster notes: The hosted-control-plane preview (hcpOpenShiftClusters) is not modelled. - - id: azure-aks-flux-configuration-write provider: azure service: kubernetes diff --git a/src/privilege-escalation-paths/azure/logic_apps.yaml b/src/privilege-escalation-paths/azure/logic_apps.yaml index d502fa0b1f..1335eb4018 100644 --- a/src/privilege-escalation-paths/azure/logic_apps.yaml +++ b/src/privilege-escalation-paths/azure/logic_apps.yaml @@ -1,7 +1,3 @@ -# 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 @@ -30,7 +26,6 @@ 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 @@ -63,7 +58,6 @@ references: - https://learn.microsoft.com/en-us/azure/logic-apps/authenticate-with-managed-identity notes: Covers both identity-assignment sections of the page. - - id: azure-logicapp-connection-access-policy-write provider: azure service: logic_apps @@ -96,7 +90,6 @@ references: - https://learn.microsoft.com/en-us/azure/logic-apps/create-single-tenant-workflows-azure-portal notes: '' - - id: azure-logicapp-connection-list-connection-keys provider: azure service: logic_apps @@ -127,3 +120,63 @@ references: - https://learn.microsoft.com/en-us/azure/connectors/introduction notes: Same target modelling as azure-logicapp-connection-access-policy-write. User-consented connections are the common case; the azure_service_principal kind covers only SP-backed connections, so user-backed ones are not represented. +- id: azure-peaso-microsoftlogicworkflowsrunsactionsrequesthistoriesread + provider: azure + service: logic_apps + title: Recover a reusable principal credential from Logic App run output + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsrunsactionsrequesthistoriesread + source_revision: 0b36331 + summary: A visible run record contains a reusable credential of another principal. + requires: + any_of: + - - action: Microsoft.Logic/workflows/runs/actions/requestHistories/read + scope: '{pivot}' + target: + kind: azure_service_principal + selector: + azure_challenge_fact: azure-peaso-microsoftlogicworkflowsrunsactionsrequesthistoriesread + scope: inherited_scope + outcome: credentials + conditions: + - id: credential_content + description: A collected unredacted bearer credential must match a live target principal. + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict the cited permission and remove unnecessary credential or identity bindings. + references: + - https://learn.microsoft.com/en-us/azure/logic-apps/logic-apps-securing-a-logic-app + notes: 'Collector fact required: azure_logic_app_request_history_credentials.' +- id: azure-peaso-microsoftlogicworkflowsrunsactionsread + provider: azure + service: logic_apps + title: Recover a reusable principal credential from Logic App run output + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-logic-apps-privesc.md#microsoftlogicworkflowsrunsactionsread + source_revision: 0b36331 + summary: A visible run record contains a reusable credential of another principal. + requires: + any_of: + - - action: Microsoft.Logic/workflows/runs/actions/read + scope: '{pivot}' + target: + kind: azure_service_principal + selector: + azure_challenge_fact: azure-peaso-microsoftlogicworkflowsrunsactionsread + scope: inherited_scope + outcome: credentials + conditions: + - id: credential_content + description: A collected unredacted bearer credential must match a live target principal. + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict the cited permission and remove unnecessary credential or identity bindings. + references: + - https://learn.microsoft.com/en-us/azure/logic-apps/logic-apps-securing-a-logic-app + notes: 'Collector fact required: azure_logic_app_action_output_credentials.' diff --git a/src/privilege-escalation-paths/azure/managed_applications.yaml b/src/privilege-escalation-paths/azure/managed_applications.yaml index 319ccf0797..3d89d023f8 100644 --- a/src/privilege-escalation-paths/azure/managed_applications.yaml +++ b/src/privilege-escalation-paths/azure/managed_applications.yaml @@ -1,6 +1,3 @@ -# 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 @@ -27,3 +24,35 @@ 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. +- id: azure-peaso-deploy-as-identity-inside-a-managed-app + provider: azure + service: managed_applications + title: Deploy an authorized managed-app template that grants a new identity privileged RBAC + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-managed-applications-privesc.md#deploy-as-identity-inside-a-managed-app + source_revision: 0b36331 + summary: A deployment template creates a managed identity and grants it a role the source lacks. + requires: + all_of: + - action: Microsoft.Solutions/applicationDefinitions/write + scope: '{pivot}' + - action: Microsoft.Solutions/applications/write + scope: '{pivot}' + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-peaso-deploy-as-identity-inside-a-managed-app + scope: inherited_scope + conditions: + - id: authorized_template + description: The selected definition and application deployment must allow the embedded role assignment at the + target scope. + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict the cited permission and remove unnecessary credential or identity bindings. + references: + - https://learn.microsoft.com/en-us/azure/azure-resource-manager/managed-applications/publish-service-catalog-app + notes: 'Collector fact required: azure_managed_app_deployment_authorizations.' diff --git a/src/privilege-escalation-paths/azure/monitor.yaml b/src/privilege-escalation-paths/azure/monitor.yaml new file mode 100644 index 0000000000..8529553e81 --- /dev/null +++ b/src/privilege-escalation-paths/azure/monitor.yaml @@ -0,0 +1,30 @@ +- id: azure-peaso-microsoftinsightswebtestsread + provider: azure + service: monitor + title: Read a reusable credential stored in an availability test + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-monitor-privesc.md#microsoftinsightswebtestsread + source_revision: 0b36331 + summary: The web test request contains an unexpired bearer, basic or signed-URL credential. + requires: + any_of: + - - action: Microsoft.Insights/webtests/read + scope: '{pivot}' + target: + kind: azure_service_principal + selector: + azure_challenge_fact: azure-peaso-microsoftinsightswebtestsread + scope: inherited_scope + outcome: credentials + conditions: + - id: credential_match + description: A stored request credential must map to a target principal and be usable. + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + blockers: [] + confidence: conditional + severity: high + mitigation: Restrict the cited permission and remove unnecessary credential or identity bindings. + references: + - https://learn.microsoft.com/en-us/azure/azure-monitor/app/availability-overview + notes: 'Collector fact required: azure_webtest_request_credentials.' diff --git a/src/privilege-escalation-paths/azure/purview.yaml b/src/privilege-escalation-paths/azure/purview.yaml index 0a4eaa3007..7f483e36f4 100644 --- a/src/privilege-escalation-paths/azure/purview.yaml +++ b/src/privilege-escalation-paths/azure/purview.yaml @@ -1,7 +1,3 @@ -# 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 @@ -31,7 +27,6 @@ - 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: Granted by Owner and Contributor without Microsoft.Authorization write. Follow-on Purview access policies into governed SQL/Storage sources are data access and are excluded separately. The resulting grant lives in the Purview role model, not in Azure RBAC. - - id: azure-purview-rogue-shir-scan-credentials provider: azure service: purview @@ -63,3 +58,34 @@ references: - https://learn.microsoft.com/en-us/purview/manage-integration-runtimes notes: Chains azure-purview-add-root-collection-admin. A source that already holds Purview Data Source Admin reaches the same targets, but Purview data-plane roles are not collected. +- id: azure-audit-microsoftpurviewpolicyelementswrite-purview-access-policies-into-governe + provider: azure + service: purview + title: Microsoft.Purview/policyElements/write — Purview access policies into governed SQL/Storage + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-purview-privesc.md#microsoftpurviewpolicyelementswrite--purview-access-policies-into-governed-sqlstorage + summary: Purview-governed SQL or Storage data access granted to chosen principal + requires: + all_of: + - action: Microsoft.Purview/policyElements/write + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + scope: inherited_scope + aggregate_as: Microsoft.Purview/policyElements/write — Purview access policies into governed SQL/Storage on + {target.scope} + outcome: permission_grant + selector: + azure_challenge_fact: azure-audit-microsoftpurviewpolicyelementswrite-purview-access-policies-into-governe + conditions: + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + 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/rest/api/purview/accounts/list-keys?view=rest-purview-2021-12-01 + notes: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must + evaluate UNKNOWN. Collector fact required: purview.governedSources.' diff --git a/src/privilege-escalation-paths/azure/service_bus.yaml b/src/privilege-escalation-paths/azure/service_bus.yaml index 04574b952f..76c013a637 100644 --- a/src/privilege-escalation-paths/azure/service_bus.yaml +++ b/src/privilege-escalation-paths/azure/service_bus.yaml @@ -1,9 +1,3 @@ -# Azure Service Bus techniques (declarative only). -# Source: hacktricks-cloud az-servicebus-privesc.md (re-reviewed at rev a66f094ede). -# Second-order escalation through privileged consumers of the namespace, like consumer_poisoning.yaml: -# until trigger bindings are collected, managed identities holding messages/receive/action on the namespace -# are reported conditional (consumer_binding_not_collected) and every other identity unknown. - - id: azure-servicebus-message-injection-consumer provider: azure service: service_bus @@ -55,3 +49,139 @@ - https://learn.microsoft.com/en-us/azure/service-bus-messaging/authenticate-application - https://learn.microsoft.com/en-us/azure/service-bus-messaging/service-bus-sas notes: Rule-creation headings (authorizationRules/write) need a key read-back, which the listKeys alternatives cover. Receive headings are data access and stay excluded. +- id: azure-audit-authorization-rule-key-disclosure-and-rotation + provider: azure + service: servicebus + title: Authorization-rule key disclosure and rotation + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#authorization-rule-key-disclosure-and-rotation + summary: new standalone SAS credential with rule-scoped rights + requires: + all_of: [] + any_of: + - - action: Microsoft.ServiceBus/namespaces/authorizationRules/listKeys/action + scope: '{target.scope}' + - - action: Microsoft.ServiceBus/namespaces/authorizationRules/regenerateKeys/action + scope: '{target.scope}' + target: + kind: azure_verified_authority + scope: inherited_scope + aggregate_as: Authorization-rule key disclosure and rotation on {target.scope} + outcome: permission_grant + selector: + azure_challenge_fact: azure-audit-authorization-rule-key-disclosure-and-rotation + conditions: + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + 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/service-bus-messaging/service-bus-python-how-to-use-topics-subscriptions?tabs=passwordless + notes: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must + evaluate UNKNOWN. Collector fact required: serviceBus.rules.' +- id: azure-audit-microsoftservicebusnamespacesdisasterrecoveryconfigsauthorizationrulesli + provider: azure + service: servicebus + title: Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/authorizationRules/listkeys/action + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespacesdisasterrecoveryconfigsauthorizationruleslistkeysaction + summary: new alias credential with rule-scoped rights + requires: + all_of: + - action: Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/authorizationRules/listkeys/action + scope: '{target.scope}' + target: + kind: azure_verified_authority + scope: inherited_scope + aggregate_as: Microsoft.ServiceBus/namespaces/disasterRecoveryConfigs/authorizationRules/listkeys/action on + {target.scope} + outcome: permission_grant + selector: + azure_challenge_fact: azure-audit-microsoftservicebusnamespacesdisasterrecoveryconfigsauthorizationrulesli + conditions: + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + 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/service-bus-messaging/service-bus-python-how-to-use-topics-subscriptions?tabs=passwordless + notes: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must + evaluate UNKNOWN. Collector fact required: serviceBus.geoDrRules.' +- id: azure-audit-microsoftservicebusnamespacesqueuestopicsauthorizationruleslistkeysactio + provider: azure + service: servicebus + title: Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/ListKeys/action OR Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/regenerateKeys/action + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespacesqueuestopicsauthorizationruleslistkeysaction-or-microsoftservicebusnamespacesqueuestopicsauthorizationrulesregeneratekeysaction + summary: entity-scoped SAS credential + requires: + all_of: [] + any_of: + - - action: Microsoft.ServiceBus/namespaces/queues/authorizationRules/listKeys/action + scope: '{target.scope}' + - - action: Microsoft.ServiceBus/namespaces/queues/authorizationRules/regenerateKeys/action + scope: '{target.scope}' + - - action: Microsoft.ServiceBus/namespaces/topics/authorizationRules/listKeys/action + scope: '{target.scope}' + - - action: Microsoft.ServiceBus/namespaces/topics/authorizationRules/regenerateKeys/action + scope: '{target.scope}' + target: + kind: azure_verified_authority + scope: inherited_scope + aggregate_as: Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/ListKeys/action OR Microsoft.ServiceBus/namespaces/[queues|topics]/authorizationRules/regenerateKeys/action + on {target.scope} + outcome: permission_grant + selector: + azure_challenge_fact: azure-audit-microsoftservicebusnamespacesqueuestopicsauthorizationruleslistkeysactio + conditions: + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + 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/service-bus-messaging/service-bus-python-how-to-use-topics-subscriptions?tabs=passwordless + notes: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must + evaluate UNKNOWN. Collector fact required: serviceBus.entityRules.' +- id: azure-audit-microsoftservicebusnamespacesauthorizationruleswrite + provider: azure + service: servicebus + title: Microsoft.ServiceBus/namespaces/AuthorizationRules/write + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-servicebus-privesc.md#microsoftservicebusnamespacesauthorizationruleswrite + summary: new namespace SAS principal with attacker-selected Manage rights + requires: + all_of: + - action: Microsoft.ServiceBus/namespaces/authorizationRules/write + scope: '{target.scope}' + - action: Microsoft.ServiceBus/namespaces/authorizationRules/listKeys/action + scope: '{target.scope}' + target: + kind: azure_verified_authority + scope: inherited_scope + aggregate_as: Microsoft.ServiceBus/namespaces/AuthorizationRules/write on {target.scope} + outcome: permission_grant + selector: + azure_challenge_fact: azure-audit-microsoftservicebusnamespacesauthorizationruleswrite + conditions: + - id: same_resource_binding + description: All actions must apply to the same service resource and the referenced child object. + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + 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/service-bus-messaging/service-bus-python-how-to-use-topics-subscriptions?tabs=passwordless + notes: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must + evaluate UNKNOWN. Collector fact required: serviceBus.namespaces.' diff --git a/src/privilege-escalation-paths/azure/service_fabric.yaml b/src/privilege-escalation-paths/azure/service_fabric.yaml index ad4a1e643e..1ce68c52b2 100644 --- a/src/privilege-escalation-paths/azure/service_fabric.yaml +++ b/src/privilege-escalation-paths/azure/service_fabric.yaml @@ -1,10 +1,3 @@ -# 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-deploy-node-identity provider: azure service: service_fabric @@ -49,7 +42,6 @@ - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/compute#microsoftservicefabric - https://learn.microsoft.com/en-us/azure/service-fabric/how-to-managed-identity-managed-cluster-virtual-machine-scale-sets notes: Template-based deployments additionally need Microsoft.Resources/deployments write. For managed clusters the node scale sets live in a service-managed resource group. Running code on a node also exposes the cluster certificate in the node certificate store (Service Fabric data-plane admin, not an Azure principal). - - id: azure-servicefabric-application-user-assigned-identity provider: azure service: service_fabric @@ -94,7 +86,6 @@ - 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: Theft of an existing application's identity from other code on the node depends on per-activation secrets and process isolation and is not modelled separately; node scale-set identities are covered by azure-servicefabric-application-deploy-node-identity. - - id: azure-servicefabric-managed-nodetype-user-assigned-identity provider: azure service: service_fabric @@ -131,3 +122,33 @@ references: - https://learn.microsoft.com/en-us/azure/service-fabric/how-to-managed-identity-managed-cluster-virtual-machine-scale-sets notes: The classic-cluster variant changes the paired scale set directly and is covered by azure-vmss-model-write. +- id: azure-audit-cluster-client-certificate-theft-data-plane-admin + provider: azure + service: service_fabric + title: Cluster / client certificate theft → data-plane admin + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-service-fabric-privesc.md#cluster--client-certificate-theft--data-plane-admin + summary: cluster certificate identity, able to deploy apps and reach node identity + requires: + all_of: + - action: Microsoft.KeyVault/vaults/secrets/getSecret/action + scope: '{target.scope}' + target: + kind: azure_verified_authority + scope: inherited_scope + aggregate_as: Cluster / client certificate theft → data-plane admin on {target.scope} + outcome: permission_grant + selector: + azure_challenge_fact: azure-audit-cluster-client-certificate-theft-data-plane-admin + conditions: + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + 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/service-fabric/service-fabric-cluster-security + notes: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must + evaluate UNKNOWN. Collector fact required: serviceFabric.certSecretLinks.' diff --git a/src/privilege-escalation-paths/azure/spring_apps.yaml b/src/privilege-escalation-paths/azure/spring_apps.yaml index 53d0d957de..b14e4a68df 100644 --- a/src/privilege-escalation-paths/azure/spring_apps.yaml +++ b/src/privilege-escalation-paths/azure/spring_apps.yaml @@ -1,8 +1,3 @@ -# Azure Spring Apps techniques (declarative only). -# 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. - - id: azure-springapps-deployment-write-app-identity provider: azure service: spring_apps @@ -34,7 +29,6 @@ - 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. Updating an existing deployment needs only deployments/write; 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 @@ -70,3 +64,96 @@ - 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: The pivot is a Spring Apps service instance; the new or updated app is its child. +- id: azure-audit-listtestkeys-public-test-endpoints + provider: azure + service: spring_apps + title: listTestKeys / public test endpoints + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#listtestkeys--public-test-endpoints + summary: app endpoint key and, conditionally, application secrets + requires: + all_of: + - action: Microsoft.AppPlatform/Spring/listTestKeys/action + scope: '{target.scope}' + target: + kind: azure_verified_authority + scope: inherited_scope + aggregate_as: listTestKeys / public test endpoints on {target.scope} + outcome: permission_grant + selector: + azure_challenge_fact: azure-audit-listtestkeys-public-test-endpoints + conditions: + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + 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/spring-apps/basic-standard/retirement-announcement + notes: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must + evaluate UNKNOWN. Collector fact required: springApps.testEndpoints.' +- id: azure-audit-microsoftappplatformspringregeneratetestkeyaction + provider: azure + service: spring_apps + title: Microsoft.AppPlatform/Spring/regenerateTestKey/action + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#microsoftappplatformspringregeneratetestkeyaction + summary: replacement app endpoint key and conditional secrets + requires: + all_of: + - action: Microsoft.AppPlatform/Spring/regenerateTestKey/action + scope: '{target.scope}' + target: + kind: azure_verified_authority + scope: inherited_scope + aggregate_as: Microsoft.AppPlatform/Spring/regenerateTestKey/action on {target.scope} + outcome: permission_grant + selector: + azure_challenge_fact: azure-audit-microsoftappplatformspringregeneratetestkeyaction + conditions: + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + 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/spring-apps/basic-standard/retirement-announcement + notes: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must + evaluate UNKNOWN. Collector fact required: springApps.testEndpoints.' +- id: azure-audit-custom-container-build-service-supply-chain + provider: azure + service: spring_apps + title: Custom container / build-service supply chain + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#custom-container--build-service-supply-chain + summary: attacker code executes in future app deployment as its identity + requires: + all_of: [] + any_of: + - - action: Microsoft.AppPlatform/Spring/buildServices/builders/write + scope: '{target.scope}' + - - action: Microsoft.AppPlatform/Spring/buildServices/builders/buildpackBindings/write + scope: '{target.scope}' + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-audit-custom-container-build-service-supply-chain + scope: inherited_scope + aggregate_as: Custom container / build-service supply chain on {target.scope} + outcome: workload_execution + conditions: + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + 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/spring-apps/basic-standard/retirement-announcement + notes: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must + evaluate UNKNOWN. Collector fact required: springApps.builderBindings.' diff --git a/src/privilege-escalation-paths/azure/sre_agent.yaml b/src/privilege-escalation-paths/azure/sre_agent.yaml index c6e99645f3..de7388efc7 100644 --- a/src/privilege-escalation-paths/azure/sre_agent.yaml +++ b/src/privilege-escalation-paths/azure/sre_agent.yaml @@ -1,6 +1,3 @@ -# Azure SRE Agent privilege escalation techniques (declarative only). -# Source: hacktricks-cloud az-sre-agent-privesc.md (rev 171e422; re-reviewed at a66f094ede). - - id: azure-sre-agent-drive-managed-identity provider: azure service: sre_agent @@ -45,7 +42,6 @@ - https://learn.microsoft.com/en-us/azure/sre-agent/overview - https://learn.microsoft.com/en-us/azure/sre-agent/run-modes notes: threads/approve/action alone only approves actions the agent already proposed, so it is not an alternative here. - - id: azure-sre-agent-assign-user-assigned-identity provider: azure service: sre_agent @@ -80,3 +76,35 @@ references: - https://learn.microsoft.com/en-us/azure/sre-agent/overview notes: agents/write is also the instruction channel used by azure-sre-agent-drive-managed-identity. +- id: azure-audit-drive-the-agents-managed-identity-instruction-tool-config-injection-agen + provider: azure + service: sre_agent + title: Drive the agent's managed identity — instruction / tool-config injection (agents/threads, agents/write, + ...) + 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- + summary: approve privileged agent remediation as its MI + requires: + all_of: + - action: Microsoft.App/agents/threads/approve/action + scope: '{target.scope}' + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-audit-drive-the-agents-managed-identity-instruction-tool-config-injection-agen + scope: inherited_scope + aggregate_as: Drive the agent's managed identity — instruction / tool-config injection (agents/threads, agents/write, + ...) on {target.scope} + outcome: workload_execution + conditions: + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + 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/sre-agent/overview + notes: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must + evaluate UNKNOWN. Collector fact required: sreAgents.pendingApprovals.' diff --git a/src/privilege-escalation-paths/azure/static_web_apps.yaml b/src/privilege-escalation-paths/azure/static_web_apps.yaml new file mode 100644 index 0000000000..1417542939 --- /dev/null +++ b/src/privilege-escalation-paths/azure/static_web_apps.yaml @@ -0,0 +1,30 @@ +- id: azure-audit-microsoftwebstaticsiteslistsecretsaction + provider: azure + service: static_web_apps + title: Microsoft.Web/staticSites/listSecrets/action + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#microsoftwebstaticsiteslistsecretsaction + summary: deployment token allowing arbitrary site content + requires: + all_of: + - action: Microsoft.Web/staticSites/listSecrets/action + scope: '{target.scope}' + target: + kind: azure_verified_authority + scope: inherited_scope + aggregate_as: Microsoft.Web/staticSites/listSecrets/action on {target.scope} + outcome: permission_grant + selector: + azure_challenge_fact: azure-audit-microsoftwebstaticsiteslistsecretsaction + conditions: + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + 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/static-web-apps/snippets + notes: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must + evaluate UNKNOWN. Collector fact required: staticWebApps.deploymentAuth.' diff --git a/src/privilege-escalation-paths/azure/storage.yaml b/src/privilege-escalation-paths/azure/storage.yaml new file mode 100644 index 0000000000..da8bb0b27a --- /dev/null +++ b/src/privilege-escalation-paths/azure/storage.yaml @@ -0,0 +1,181 @@ +- id: azure-audit-microsoftstoragestorageaccountslistkeysaction + provider: azure + service: storage + title: Microsoft.Storage/storageAccounts/listkeys/action + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslistkeysaction + summary: account key authenticating all four storage services + requires: + all_of: + - action: Microsoft.Storage/storageAccounts/listKeys/action + scope: '{target.scope}' + target: + kind: azure_verified_authority + scope: inherited_scope + aggregate_as: Microsoft.Storage/storageAccounts/listkeys/action on {target.scope} + outcome: permission_grant + selector: + azure_challenge_fact: azure-audit-microsoftstoragestorageaccountslistkeysaction + conditions: + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + 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: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must + evaluate UNKNOWN. Collector fact required: storageAccounts.' +- id: azure-audit-microsoftstoragestorageaccountsregeneratekeyaction + provider: azure + service: storage + title: Microsoft.Storage/storageAccounts/regenerateKey/action + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsregeneratekeyaction + summary: replacement account key, also unchanged key in response + requires: + all_of: + - action: Microsoft.Storage/storageAccounts/regenerateKey/action + scope: '{target.scope}' + target: + kind: azure_verified_authority + scope: inherited_scope + aggregate_as: Microsoft.Storage/storageAccounts/regenerateKey/action on {target.scope} + outcome: permission_grant + selector: + azure_challenge_fact: azure-audit-microsoftstoragestorageaccountsregeneratekeyaction + conditions: + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + 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: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must + evaluate UNKNOWN. Collector fact required: storageAccounts.' +- id: azure-audit-microsoftstoragestorageaccountslistaccountsasaction + provider: azure + service: storage + title: Microsoft.Storage/storageAccounts/listAccountSas/action + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslistaccountsasaction + summary: attacker-chosen account SAS + requires: + all_of: + - action: Microsoft.Storage/storageAccounts/listAccountSas/action + scope: '{target.scope}' + target: + kind: azure_verified_authority + scope: inherited_scope + aggregate_as: Microsoft.Storage/storageAccounts/listAccountSas/action on {target.scope} + outcome: permission_grant + selector: + azure_challenge_fact: azure-audit-microsoftstoragestorageaccountslistaccountsasaction + conditions: + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + 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: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must + evaluate UNKNOWN. Collector fact required: storageAccounts.' +- id: azure-audit-microsoftstoragestorageaccountslistservicesasaction + provider: azure + service: storage + title: Microsoft.Storage/storageAccounts/listServiceSas/action + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslistservicesasaction + summary: attacker-chosen service SAS + requires: + all_of: + - action: Microsoft.Storage/storageAccounts/listServiceSas/action + scope: '{target.scope}' + target: + kind: azure_verified_authority + scope: inherited_scope + aggregate_as: Microsoft.Storage/storageAccounts/listServiceSas/action on {target.scope} + outcome: permission_grant + selector: + azure_challenge_fact: azure-audit-microsoftstoragestorageaccountslistservicesasaction + conditions: + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + 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: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must + evaluate UNKNOWN. Collector fact required: storageAccounts.' +- id: azure-audit-microsoftstoragestorageaccountslocaluserswrite-microsoftstoragestorageac + provider: azure + service: storage + title: Microsoft.Storage/storageAccounts/localusers/write (Microsoft.Storage/storageAccounts/localusers/read) + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslocaluserswrite-microsoftstoragestorageaccountslocalusersread + summary: new SFTP credential with container rights + requires: + all_of: + - action: Microsoft.Storage/storageAccounts/localUsers/write + scope: '{target.scope}' + target: + kind: azure_verified_authority + scope: inherited_scope + aggregate_as: Microsoft.Storage/storageAccounts/localusers/write (Microsoft.Storage/storageAccounts/localusers/read) + on {target.scope} + outcome: permission_grant + selector: + azure_challenge_fact: azure-audit-microsoftstoragestorageaccountslocaluserswrite-microsoftstoragestorageac + conditions: + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + 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: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must + evaluate UNKNOWN. Collector fact required: storageAccounts.' +- id: azure-audit-microsoftstoragestorageaccountslocalusersregeneratepasswordaction + provider: azure + service: storage + title: Microsoft.Storage/storageAccounts/localusers/regeneratePassword/action + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountslocalusersregeneratepasswordaction + summary: replacement SFTP password inheriting user rights + requires: + all_of: + - action: Microsoft.Storage/storageAccounts/localUsers/regeneratePassword/action + scope: '{target.scope}' + target: + kind: azure_verified_authority + scope: inherited_scope + aggregate_as: Microsoft.Storage/storageAccounts/localusers/regeneratePassword/action on {target.scope} + outcome: permission_grant + selector: + azure_challenge_fact: azure-audit-microsoftstoragestorageaccountslocalusersregeneratepasswordaction + conditions: + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + 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: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must + evaluate UNKNOWN. Collector fact required: storageAccounts.' diff --git a/src/privilege-escalation-paths/azure/virtual_machines.yaml b/src/privilege-escalation-paths/azure/virtual_machines.yaml index e80441e70b..9b05d1db42 100644 --- a/src/privilege-escalation-paths/azure/virtual_machines.yaml +++ b/src/privilege-escalation-paths/azure/virtual_machines.yaml @@ -1,9 +1,3 @@ -# 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 @@ -32,7 +26,6 @@ references: - https://learn.microsoft.com/en-us/azure/virtual-machines/extensions/features-windows notes: Covers the VMAccess password/SSH-key reset (which additionally uses virtualMachines/read+write in the CLI flow) and the DSC extension flow. Scale-set model extensions (virtualMachineScaleSets/extensions/write) are modelled separately in azure-vmss-model-write. - - id: azure-vm-runcommand-action provider: azure service: virtual_machines @@ -61,7 +54,6 @@ references: - https://learn.microsoft.com/en-us/azure/virtual-machines/windows/run-command notes: "" - - id: azure-vm-managed-runcommands-write provider: azure service: virtual_machines @@ -90,7 +82,6 @@ references: - https://learn.microsoft.com/en-us/azure/virtual-machines/windows/run-command-managed notes: "" - - id: azure-vmss-vm-managed-runcommands-write provider: azure service: virtual_machines @@ -119,7 +110,6 @@ references: - https://learn.microsoft.com/en-us/azure/virtual-machines/windows/run-command-managed notes: Also includes AKS node pools backed by VMSS (kubelet/agentpool identities) when the source has rights in the node resource group. - - id: azure-arc-machine-runcommands-write provider: azure service: virtual_machines @@ -148,7 +138,6 @@ references: - https://learn.microsoft.com/en-us/azure/azure-arc/servers/run-command notes: On the Arc machine the identity token requires local admin/himds group access, which root/SYSTEM run commands have. - - id: azure-vm-gallery-application-install provider: azure service: virtual_machines @@ -180,7 +169,6 @@ references: - https://learn.microsoft.com/en-us/azure/virtual-machines/vm-applications-how-to notes: Pivot gallery can be newly created if galleries/write is held on a resource group. - - id: azure-vm-entra-login provider: azure service: virtual_machines @@ -220,7 +208,6 @@ - https://learn.microsoft.com/en-us/entra/identity/devices/howto-vm-sign-in-azure-ad-linux - https://learn.microsoft.com/en-us/azure/virtual-machines/instance-metadata-service notes: IMDS is reachable by any local process by default, so even non-admin login exposes the identities. - - id: azure-vm-create-with-user-assigned-identity provider: azure service: virtual_machines @@ -261,7 +248,6 @@ references: - https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-configure-managed-identities notes: Pivot is the resource group where the source can create the VM and NIC. 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 @@ -307,7 +293,6 @@ references: - https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-configure-managed-identities notes: Conditional code-execution routes (customData re-provisioning, Serial Console, VM Applications, OS disk swap, guest configuration) are modelled by azure-vm-assign-user-assigned-identity-indirect-exec. - - id: azure-vm-assign-user-assigned-identity-indirect-exec provider: azure service: virtual_machines @@ -359,7 +344,6 @@ - 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 azure-vm-assign-user-assigned-identity-existing so the conditional routes do not raise the confidence of the direct run-command / extension / login routes. The gallery application and disk requirements carry no scope because the gallery or disk can be any one the source can write (or create). - - id: azure-vmss-vm-runcommand-action provider: azure service: virtual_machines @@ -389,45 +373,51 @@ - 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 notes: The page documents the VM action; the scale-set instance equivalent is a documented Microsoft.Compute operation with the same semantics. AKS node pools backed by VMSS are reachable when the source has the right in the node resource group (AKS normally protects it with a deny assignment). - - id: azure-vm-serial-console-connect provider: azure service: virtual_machines - title: Use Serial Console with a reboot to take over the guest OS + title: Use Serial Console and an ARM restart for guest recovery source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-virtual-machines-and-network-privesc.md#microsoftserialconsoleserialportsconnectaction - source_revision: 171e422 - summary: Interactive Serial Console access combined with a VM restart can give root/SYSTEM in the guest (boot-loader or single-user recovery, or an existing local password account), exposing the VM's managed identities. + source_revision: 0b36331 + summary: Interactive Serial Console access combined with an ARM VM restart can reach a guest recovery shell or + reset a local password, exposing the VM managed identities when recovery succeeds. requires: all_of: - - action: Microsoft.SerialConsole/serialPorts/connect/action - scope: "{target.host_resource}" - - action: Microsoft.Compute/virtualMachines/restart/action - scope: "{target.host_resource}" + - action: Microsoft.SerialConsole/serialPorts/connect/action + scope: '{target.host_resource}' + - action: Microsoft.Compute/virtualMachines/restart/action + scope: '{target.host_resource}' target: kind: azure_managed_identity selector: attached_to_service: Microsoft.Compute/virtualMachines scope: inherited_scope - aggregate_as: "Managed identities of VM {target.host_resource}" + aggregate_as: Managed identities of VM {target.host_resource} conditions: - - id: boot_diagnostics_enabled - description: Boot diagnostics must be enabled on the VM (enabling it needs virtualMachines/write). With a custom boot-diagnostics storage account, the source also needs access to that account and it must allow Shared Key access. - - id: serial_console_not_disabled - description: Serial Console must not be disabled for the subscription or inside the guest. - - id: guest_recovery_path - description: The guest must allow a takeover through the console, such as an unprotected boot loader or single-user mode, an enabled SAC/CMD channel on Windows, or a local password account known to the source. - - id: interactive_session - description: The console is interactive (portal or CLI extension), so the source's sign-in, including Conditional Access, applies. + - id: boot_diagnostics_enabled + description: Boot diagnostics must be enabled on the VM (enabling it needs virtualMachines/write). With a custom + boot-diagnostics storage account, the source also needs access to that account and it must allow Shared Key + access. + - id: serial_console_not_disabled + description: Serial Console must not be disabled for the subscription or inside the guest. + - id: guest_recovery_path + description: The guest must allow console recovery after restart, such as an unprotected boot loader or single-user + mode, or an enabled SAC/CMD channel on Windows. + - id: interactive_session + description: The console is interactive (portal or CLI extension), so the source's sign-in, including Conditional + Access, applies. blockers: - - azure_deny_assignment + - azure_deny_assignment confidence: conditional severity: high - mitigation: Disable Serial Console where it is not needed, protect boot loaders, restrict serialPorts/connect/action and VM restart rights, and keep VM identities least-privileged. + mitigation: Disable Serial Console where it is not needed, protect boot loaders, restrict serialPorts/connect/action + and VM restart rights, and keep VM identities least-privileged. references: - - https://learn.microsoft.com/en-us/troubleshoot/azure/virtual-machines/linux/serial-console-linux - - https://learn.microsoft.com/en-us/troubleshoot/azure/virtual-machines/windows/serial-console-windows - notes: Microsoft documents Virtual Machine Contributor or higher as the requirement; that role includes both actions. The same feature exists for scale-set instances, which this entry does not model. - + - https://learn.microsoft.com/en-us/troubleshoot/azure/virtual-machines/linux/serial-console-linux + - https://learn.microsoft.com/en-us/troubleshoot/azure/virtual-machines/windows/serial-console-windows + notes: This entry covers the ARM-initiated restart and guest-recovery route. Direct login with an already known + local guest password does not require virtualMachines/restart/action, but the credential is not present in the + permission snapshot. The same feature exists for scale-set instances, which this entry does not model. - id: azure-vm-os-disk-swap provider: azure service: virtual_machines @@ -469,7 +459,6 @@ references: - https://learn.microsoft.com/en-us/azure/virtual-machines/windows/os-disk-swap notes: The pivot disk can be newly created where the source holds disks/write. Attaching an existing disk as a data disk (data access only) is excluded separately. - - id: azure-vmss-model-write provider: azure service: virtual_machines @@ -504,7 +493,6 @@ - https://learn.microsoft.com/en-us/azure/virtual-machine-scale-sets/virtual-machine-scale-sets-upgrade-policy - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/compute notes: Microsoft.Compute/virtualMachineScaleSets/virtualMachines/manualUpgrade/action is the documented per-instance upgrade action but is not in the local permission catalog, so it is described as a condition instead of a requirement. - - id: azure-vm-customdata-reimage provider: azure service: virtual_machines @@ -539,3 +527,68 @@ mitigation: Restrict virtualMachines/write, reimage/action and redeploy/action (Virtual Machine Contributor, Contributor) and alert on osProfile changes and reimage operations. references: - https://learn.microsoft.com/en-us/azure/virtual-machines/custom-data +- id: azure-vm-verified-ssrf-imds + provider: azure + service: virtual_machines + title: Verified VM SSRF to managed identity + source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/historical-cross-tenant-vulnerabilities.md#trusted-ip-and-metadata-abuse + source_revision: 0b36331 + summary: A verified SSRF on a VM retrieves its managed-identity token. + source_kind: azure_challenge_foothold + requires: + all_of: [] + target: + kind: azure_managed_identity + selector: + azure_challenge_fact: azure-vm-verified-ssrf-imds + scope: any + aggregate_as: Verified VM SSRF to managed identity targets + conditions: + - id: verified_runtime_evidence + description: Exact source, target and successful credential or token access must be attested; absent evidence + remains UNKNOWN. + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + confidence: conditional + severity: high + mitigation: Remove the vulnerable access path or exposed credential. + references: + - https://learn.microsoft.com/en-us/entra/identity/managed-identities-azure-resources/how-to-use-vm-token + notes: 'Collector fact required: azure_privesc_challenge_evidence; exact technique/source/target evidence required, + absent => UNKNOWN.' +- id: azure-gallery-verified-image-secret + provider: azure + service: virtual_machines + title: Read shared gallery image with verified cloud credential + source: src/pentesting-cloud/azure-security/az-cross-tenant-and-cross-subscription-attacks/resource-and-service-sharing-attacks.md#resource--service-sharing-matrix + source_revision: 0b36331 + summary: Read an accessible gallery image version containing a validated cloud credential. + source_kind: + - azure_user + - azure_service_principal + - azure_managed_identity + requires: + all_of: + - action: Microsoft.Compute/galleries/images/versions/read + scope: '{pivot}' + target: + kind: azure_service_principal + selector: + azure_challenge_fact: azure-gallery-verified-image-secret + scope: any + aggregate_as: Read shared gallery image with verified cloud credential targets + conditions: + - id: verified_runtime_evidence + description: Exact source, target and successful credential or token access must be attested; absent evidence + remains UNKNOWN. + - id: collector_fact_required + description: Exact source, target, scope and requested collector facts must be verified; missing facts remain + UNKNOWN. + confidence: conditional + severity: high + mitigation: Remove the vulnerable access path or exposed credential. + references: + - https://learn.microsoft.com/en-us/azure/virtual-machines/share-gallery + notes: 'Collector fact required: azure_privesc_challenge_evidence; exact technique/source/target evidence required, + absent => UNKNOWN.' From 6ebdeed1f812398f9c77147fb5d0b16145bd54d5 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Mon, 12 Oct 2026 21:32:37 +0200 Subject: [PATCH 13/17] Integrate verified Azure post-exploitation catalog fragments Co-Authored-By: Codex --- .../azure/_excluded_171e422_compute.yaml | 50 +++-- .../azure/_excluded_audit_g1-entra.yaml | 12 +- ...excluded_audit_pa_az_post_persist_s06.yaml | 61 ++++++ .../azure/_excluded_verify_azure.yaml | 188 +++++++++++------- .../azure/api_management.yaml | 34 ++++ .../azure/app_configuration.yaml | 37 ++++ .../azure/automation.yaml | 67 +++++++ .../azure/container_registry.yaml | 31 +++ .../azure/storage.yaml | 31 +++ .../azure/virtual_desktop.yaml | 34 +++- 10 files changed, 459 insertions(+), 86 deletions(-) create mode 100644 src/privilege-escalation-paths/azure/_excluded_audit_pa_az_post_persist_s06.yaml create mode 100644 src/privilege-escalation-paths/azure/app_configuration.yaml diff --git a/src/privilege-escalation-paths/azure/_excluded_171e422_compute.yaml b/src/privilege-escalation-paths/azure/_excluded_171e422_compute.yaml index 887a1797af..a65849fa9f 100644 --- a/src/privilege-escalation-paths/azure/_excluded_171e422_compute.yaml +++ b/src/privilege-escalation-paths/azure/_excluded_171e422_compute.yaml @@ -62,8 +62,11 @@ 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. + technique: '`Microsoft.ApiManagement/service/gateways/getConfiguration/action` — bulk policy/secret pull (data + action, bypasses the Administrative log)' + reason: Gateway configuration can contain an Entra service-principal secret, but the configuration snapshot does + not reveal or validate its content or map it to a principal. A content collector and identity join are needed; + otherwise this is data disclosure only. - 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: Self-hosted gateway key; gateway impersonation, no Azure/Entra principal. @@ -105,7 +108,8 @@ 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. + reason: ACR image config and historical layers can contain Entra credentials; pull permission alone does not establish + their content, credential validity, or mapped principal. A complete layer scan and identity join are needed. - 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. @@ -195,7 +199,10 @@ reason: Workspace access token authorizes the Playwright service only; no Azure/Entra principal. - 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. + reason: Secret-auth linker configuration may disclose a reusable credential for its backing service without direct + rights on that service. A principal edge needs the exact linker-to-target resource join and a verified secret-returned + fact; missing or denied collection is UNKNOWN. Managed-identity and service-principal connections return no + reusable backing secret. - 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. @@ -252,34 +259,53 @@ 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. + reason: The packet capture can contain reusable tokens or session cookies only if the selected VM sends them in + observable cleartext traffic. A readable capture destination, deployed Network Watcher extension, actual victim + traffic, and token validity are runtime/content facts; the ARM write grant alone identifies no credential or + target principal. - 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. + reason: The A-record change can redirect linked-VNet clients, but credential gain requires clients to resolve + that name, connect to the attacker endpoint, disclose reusable authentication material, and accept its TLS/authentication + behavior. DNS configuration alone cannot identify a captured principal. - 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. + reason: MX control can intercept password-reset or email-OTP messages only if the affected domain uses this zone + and a victim service sends a usable message during the hijack. The message contents, expiry, and account-recovery + policy are external facts; no account is obtained from the DNS write alone. - 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. + reason: A forwarding-rule change can steer linked-VNet DNS, but a credential edge requires a winning resolution + rule, client traffic to the chosen name, TLS or application trust of the attacker endpoint, and reusable authentication + material in that traffic. Those runtime facts are absent from the ARM permission snapshot. - 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. + reason: Origin repoint can expose proxied cookies or bearer tokens only when an active route uses this origin, + requests carrying reusable authentication material arrive, and the attacker can receive the origin leg. Route + use, traffic contents, and token validity are runtime facts, so the write grant alone cannot name a gained principal. - 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. + reason: Header injection grants application authorization only if the origin trusts the injected header; route + override yields credentials only if the rule is attached, matching requests carry reusable authentication material, + and the attacker receives them. Origin trust and request contents are application/runtime facts absent from + ARM RBAC. - 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. + reason: Backend-pool repoint or HTTPS downgrade can expose credentials only if an active frontend routes matching + authentication requests through the modified backend or downgraded listener and those requests contain reusable + material. Routing, client behavior, and traffic content cannot be inferred from backendPools/write. - 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. + reason: Gateway write can repoint a live backend or replace a listener certificate, but a credential gain requires + affected authentication traffic, a working attacker-controlled endpoint or trusted replacement certificate, + and reusable tokens or passwords in requests. Listener routing, client trust, and traffic content are not established + by gateway write permission. - 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. diff --git a/src/privilege-escalation-paths/azure/_excluded_audit_g1-entra.yaml b/src/privilege-escalation-paths/azure/_excluded_audit_g1-entra.yaml index 5f04f5ef0b..1774e7763e 100644 --- a/src/privilege-escalation-paths/azure/_excluded_audit_g1-entra.yaml +++ b/src/privilege-escalation-paths/azure/_excluded_audit_g1-entra.yaml @@ -24,8 +24,10 @@ - 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. + reason: A policy edit only removes activation gates; it does not itself grant a role. Privileged Role Administrator + controls Entra directory-role assignment, not Azure-resource RBAC at every scope. For directory roles, eligibility + is azure-entraid-pim-eligible-role-activation; for Azure-resource roles, a separate eligible assignment at the + same scope and its activation policy must be joined before any gain is inferred. - 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 @@ -34,8 +36,10 @@ - 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. + reason: Directory-role AdminAssign may be covered by directory role-management grants, but Azure-resource Microsoft.Authorization/roleEligibilityScheduleRequests/write + is distinct from roleAssignments/write. A custom role can plant eligible Owner/User Access Administrator for + a controlled principal without active assignment write; model it only after an evaluator joins eligibility, + principal control, role, scope and activation policy. - 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 diff --git a/src/privilege-escalation-paths/azure/_excluded_audit_pa_az_post_persist_s06.yaml b/src/privilege-escalation-paths/azure/_excluded_audit_pa_az_post_persist_s06.yaml new file mode 100644 index 0000000000..6822b3dcee --- /dev/null +++ b/src/privilege-escalation-paths/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/azure/_excluded_verify_azure.yaml b/src/privilege-escalation-paths/azure/_excluded_verify_azure.yaml index 79b3528897..d3df68e1cd 100644 --- a/src/privilege-escalation-paths/azure/_excluded_verify_azure.yaml +++ b/src/privilege-escalation-paths/azure/_excluded_verify_azure.yaml @@ -45,8 +45,9 @@ - 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. + reason: Readable blobs, including Terraform state and .env files, can hold Entra credentials; a blob-read grant + alone does not establish the blob content, credential validity, or mapped principal. A complete content scan + and identity join are needed. - 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 @@ -270,13 +271,15 @@ - 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 + reason: The config/write code-execution path is modelled by azure-appservice-config-write; 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 + 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. + reason: DCR writes can cause AMA to ship host files into a readable workspace, but an ARM snapshot cannot show + that the chosen guest file exists, contains a usable credential, or maps to another principal. The host file + content and VM-to-file-to-credential join are required; do not emit a principal edge from DCR write 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 @@ -317,8 +320,10 @@ - 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. + reason: Changing parameters can disable auditing or cause init_connect SQL to run on a later non-administrator + database login, but this section documents no privilege-granting SQL, usable result channel, or gained target + identity. A separate database login is not required for init_connect to run; the future client connection and + successful privilege-changing side effect remain unverified. - source: src/pentesting-cloud/azure-security/az-post-exploitation/az-mysql-post-exploitation.md#microsoftdbformysqlflexibleserversstopaction technique: Microsoft.DBforMySQL/flexibleServers/stop/action source_revision: a66f094ede @@ -575,15 +580,15 @@ - 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. + reason: Documented application-credential injection is already covered by azure-entraid-app-credentials-update + and azure-entraid-app-owner-credentials in azure/entraid_apps.yaml (Graph Application.ReadWrite.All by azure-entraid-graph-application-readwrite-all). + This source is a persistence summary, not a separate permission-to-principal path. - 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. + reason: TMSL/XMLA can add a model Read or Admin member that remains after server-admin removal. This is a new + native model authorization, but the catalog has no source entitlement for Analysis Services server-admin data-plane + access or model-role membership snapshot; servers/write does not by itself prove the data-plane command occurred. - 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 @@ -617,8 +622,9 @@ - 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. + reason: The .add control command can create durable Kusto-native database or cluster admin membership. ARM principalAssignments/write + and AddPrincipals/action entries use different permissions; neither proves existing data-plane Admin entitlement + or a native membership change, which require a Kusto data-plane inventory. - 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 @@ -684,21 +690,24 @@ 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_revision: 0b36331 + reason: 'Duplicate identity takeover path: adding an app FIC grants token exchange as the target application service + principal. azure-entraid-app-credentials-update covers application credential update; azure-entraid-app-owner-credentials + covers the owned app route, including app-only Application.ReadWrite.OwnedBy. External issuer/subject control + and matching token are runtime conditions.' - 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_revision: 0b36331 + reason: 'Duplicate of azure-guestconfiguration-assignment-write and azure-guestconfiguration-assignment-write-arc: + the same assignment write runs attacker package code as SYSTEM/root; on a VM or Arc host with an attached managed + identity, it can read that identity token. ApplyAndAutoCorrect repeats the same edge after drift.' - 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_revision: 0b36331 + reason: A backup blob is encrypted and restorable only in the same subscription and Azure geography. An identity + edge needs later restore, permission to read the restored value, proof the backed-up secret or certificate contains + an SP credential, and proof it remains valid. Those content and future-operation facts are unavailable in a + read-only snapshot; backup/action alone is not secret read. - 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 @@ -769,14 +778,17 @@ 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_revision: 0b36331 + reason: The authorizations can grant a controlled principal Owner or Contributor on the managed resource group + without roleAssignments/write. This is a real new MRG-scoped RBAC grant; see proposed azure-managedapp-authorizations-mrg-rbac. + A generic edge needs a collector/evaluator join from definition authorizations and application creation to the + actual MRG, principal, role and tenant. - 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_revision: 0b36331 + reason: JIT activation can grant an eligible principal a temporary elevated role on the managed resource group. + It requires the configured jitAccessPolicy, source eligibility, any consumer approval and an active grant window; + see proposed azure-managedapp-jit-mrg-role-activation. The current inventory cannot establish these facts. - 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 @@ -981,9 +993,9 @@ - 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. + reason: An App Configuration snapshot can retain an Entra credential, but snapshot-read permission alone does + not show the key-value contents, credential validity, or target principal. A complete content scan and identity + join are needed. - 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 @@ -1002,17 +1014,14 @@ - 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. + reason: Historical Automation job streams can contain tokens or passwords, but job-read permission alone does + not show whether a usable Azure/Entra credential was printed or which principal owns it. A complete stream scan + and identity join are needed. - 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. + reason: Runbook source can contain hardcoded Entra credentials, but content-read permission alone does not identify + a usable credential or its principal. A complete source scan and identity join are needed. - 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 @@ -1038,17 +1047,13 @@ - 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. + reason: A restored VM disk can contain cached credentials, but a restore action alone does not establish that + the disk is readable/decrypted or holds a still-valid Azure/Entra credential mapped to a principal. - 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. + reason: Instant item recovery can expose files, but the recovery-point actions alone do not establish that the + mounted files contain a usable Azure/Entra credential mapped to a principal. - 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 @@ -1071,10 +1076,8 @@ - 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. + reason: A Site Recovery test clone can expose VM files, but test-failover permission alone does not establish + access to a usable Azure/Entra credential on the clone or identify its principal. - 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 @@ -1388,11 +1391,12 @@ 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. + technique: OneLake direct export and shortcut use + source_revision: 0b36331 + reason: Direct OneLake export uses the caller's existing lakehouse read access; creating a shortcut requires target + Read and alone adds no privilege. Reading an existing external shortcut with stored connection credentials, + or querying it as the item owner, can grant target-storage Read absent from the caller. That delegated-read + subcase awaits a service-scoped target and shortcut/connection/owner authorization join in the evaluator. - 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 @@ -1412,9 +1416,11 @@ 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_revision: 0b36331 + reason: Adding an attacker-controlled SMART authority with allowedDataActions Read grants new victim-service PHI + Read through attacker-issued tokens. The catalog currently lacks a FHIR data-reader target and a selector for + writable SMART authorization configuration, so the path cannot yet be evaluated without mislabeling it as Entra + impersonation or data-plane admin. - 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 @@ -1510,8 +1516,9 @@ - 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. + reason: The role bundles listKeys and compute writes. VM execution is covered by azure-vm-os-disk-swap; direct + Storage Shared Key authority still needs an evaluated allowSharedKeyAccess predicate and an account-only data-plane + target (draft azure-storage-account-listkeys-dataplane). The role name adds no extra requirement. - 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 @@ -1593,9 +1600,9 @@ - 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. + reason: Azure-resource PIM eligibility can become active privilege through SelfActivate. This Azure RBAC path + is already tracked in _excluded_audit_g1-entra.yaml as needing eligibility-schedule requirement and target-role/scope + support; directory-role activation is covered by azure-entraid-pim-eligible-role-activation. - source: src/pentesting-cloud/azure-security/az-post-exploitation/az-pim-post-exploitation.md#reconnaissance-value technique: Reconnaissance value source_revision: a66f094ede @@ -1877,3 +1884,46 @@ 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. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicebackupaction--full-service-exfiltration-to-attacker-storage + technique: Extract credentials from APIM full-service backup + source_revision: 0b36331 + reason: The backup action copies APIM data to a destination. An identity edge needs the produced backup blob, + a parsed still-valid Entra credential, and a mapped target principal; neither the ARM configuration snapshot + nor the backup permission establishes those facts. The existing azure-apim-restore-backup-managed-identity-token + entry uses restore/action, not backup/action, so it does not cover this proposed credential-extraction path. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementservicegatewayslistdebugcredentialsaction--servicegatewayslisttraceaction--live-requestresponse-wiretap + technique: Capture caller bearer tokens through APIM trace + source_revision: 0b36331 + reason: The trace action exposes a selected transaction. Caller impersonation needs a later caller request, an + unredacted Authorization header, a still-valid Entra bearer token with a useful audience, and a mapped caller + identity; these runtime facts are absent from configuration. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-api-management-post-exploitation.md#microsoftapimanagementserviceloggerswrite--servicediagnosticswrite--persistent-traffic-exfil-to-attacker-event-hub + technique: Collect caller bearer tokens with APIM diagnostics + source_revision: 0b36331 + reason: A diagnostic can send traffic to a logger, but caller impersonation needs later authenticated traffic, + an unmasked Authorization header at the attacker sink, token validity/audience, and a mapped caller identity; + configuration alone cannot establish them. +- 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: Recover VM credentials from restored backup disks + source_revision: 0b36331 + reason: Restore grants a copy of VM disks. An identity edge needs the restored host filesystem, readable decrypted + credential material, current token/password validity, and a mapped Azure/Entra principal; the vault permission + and recovery-point metadata do not establish these facts. +- source: src/pentesting-cloud/azure-security/az-post-exploitation/az-backup-and-recovery-services-post-exploitation.md#instant-item-level-recovery-quietest-exfil + technique: Recover credentials through Backup instant item recovery + source_revision: 0b36331 + reason: Instant item recovery mounts backup files. An identity edge needs the mounted filesystem, an actual usable + credential or token in those files, and a mapped Azure/Entra principal; the recovery-point actions do not establish + these host-content facts. +- 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: Recover credentials from Site Recovery test-failover clone + source_revision: 0b36331 + reason: Test failover creates a VM clone. An identity edge needs access to its disks or runtime, a usable credential + on the clone, and a mapped Azure/Entra principal; the failover permission and protected-item configuration do + not establish those facts. +- source: src/pentesting-cloud/azure-security/az-persistence/az-dev-center-persistence.md#code-and-artifact-backdoors + technique: Poison ADE environment definitions to execute under deployment identity + source_revision: 0b36331 + reason: The stronger ADE deployment identity is reached only if a future environment deployment consumes the poisoned + Git definition. ARM inventory does not reveal Git write authority, catalog commit/content, or the future deploy + event; azure-devcenter-ade-deployment-identity additionally requires projects/users/environments/userWrite/action. diff --git a/src/privilege-escalation-paths/azure/api_management.yaml b/src/privilege-escalation-paths/azure/api_management.yaml index 7c94f55034..d65389589b 100644 --- a/src/privilege-escalation-paths/azure/api_management.yaml +++ b/src/privilege-escalation-paths/azure/api_management.yaml @@ -267,3 +267,37 @@ references: - https://learn.microsoft.com/en-us/azure/api-management/diagnostic-logs-reference notes: Captured caller tokens of end users are not modelled; only the APIM identity tokens attached by existing policies. +- 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: 0b36331 + 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 is UNKNOWN. + - id: gateway_assignment + description: Only assigned gateway policy XML and values returned in this gateway configuration are reachable. + 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: Draft requires azure.apim.gateway_config_credential_holders; the evaluator must join only verified holders, + and return UNKNOWN if that fact is missing or incomplete. diff --git a/src/privilege-escalation-paths/azure/app_configuration.yaml b/src/privilege-escalation-paths/azure/app_configuration.yaml new file mode 100644 index 0000000000..a4bd8a54b8 --- /dev/null +++ b/src/privilege-escalation-paths/azure/app_configuration.yaml @@ -0,0 +1,37 @@ +# Azure privilege escalation paths. + +- 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: 0b36331 + summary: Read a verified usable credential from an App Configuration snapshot and gain its Entra service principal + 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 a collected, mapped, still-valid service-principal credential in the readable content creates + this edge; uncollected, partial, or unverified content is UNKNOWN. + - id: snapshot_access + description: The snapshot must already exist and be readable; 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: Draft requires azure.app_configuration.snapshot_credential_holders; the evaluator must join only verified + holders, and return UNKNOWN if that fact is missing or incomplete. diff --git a/src/privilege-escalation-paths/azure/automation.yaml b/src/privilege-escalation-paths/azure/automation.yaml index e37b968d56..df61165252 100644 --- a/src/privilege-escalation-paths/azure/automation.yaml +++ b/src/privilege-escalation-paths/azure/automation.yaml @@ -432,3 +432,70 @@ references: - https://learn.microsoft.com/en-us/azure/automation/shared-resources/variables notes: Same consumer-dependent class as azure-automation-trigger-existing-runbook; overwriting an encrypted variable with a known value is a side effect, not an identity gain. +- id: azure-automation-job-output-credential + provider: azure + service: automation + title: Read tokens and credentials from prior Automation job output + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-automation-accounts-post-exploitation.md#harvest-secrets-from-prior-job-output-and-streams + source_revision: 0b36331 + summary: Read a verified usable credential from historical Automation job output and gain its Entra service principal + permissions. + requires: + all_of: + - action: Microsoft.Automation/automationAccounts/jobs/read + scope: '{pivot}' + any_of: + - - action: Microsoft.Automation/automationAccounts/jobs/output/read + scope: '{pivot}' + - - action: Microsoft.Automation/automationAccounts/jobs/streams/read + scope: '{pivot}' + 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 is UNKNOWN. + 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: Draft requires azure.automation.job_output_credential_holders; the evaluator must join only verified holders, + and return UNKNOWN if that fact is missing or incomplete. +- id: azure-automation-runbook-source-credential + provider: azure + service: automation + title: Read hardcoded credentials from runbook source + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-automation-accounts-post-exploitation.md#read-runbook-source-for-hardcoded-secrets + source_revision: 0b36331 + 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}' + 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 is UNKNOWN. + 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: Draft requires azure.automation.runbook_content_credential_holders; the evaluator must join only verified + holders, and return UNKNOWN if that fact is missing or incomplete. diff --git a/src/privilege-escalation-paths/azure/container_registry.yaml b/src/privilege-escalation-paths/azure/container_registry.yaml index 4b462a6bf7..879877a2eb 100644 --- a/src/privilege-escalation-paths/azure/container_registry.yaml +++ b/src/privilege-escalation-paths/azure/container_registry.yaml @@ -202,3 +202,34 @@ - https://learn.microsoft.com/en-us/azure/container-registry/container-registry-roles notes: 'Collector fact required: azure_privesc_challenge_evidence; exact technique/source/target evidence required, absent => UNKNOWN.' +- 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: 0b36331 + 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 is UNKNOWN. + 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: Draft requires azure.acr.image_layer_credential_holders; the evaluator must join only verified holders, + and return UNKNOWN if that fact is missing or incomplete. diff --git a/src/privilege-escalation-paths/azure/storage.yaml b/src/privilege-escalation-paths/azure/storage.yaml index da8bb0b27a..7c66cc1bd1 100644 --- a/src/privilege-escalation-paths/azure/storage.yaml +++ b/src/privilege-escalation-paths/azure/storage.yaml @@ -179,3 +179,34 @@ - https://learn.microsoft.com/en-us/azure/role-based-access-control/permissions/storage#microsoftstorage notes: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must evaluate UNKNOWN. Collector fact required: storageAccounts.' +- id: azure-storage-blob-content-credential + provider: azure + service: storage + title: Read Entra credentials embedded in blobs + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-blob-storage-post-exploitation.md#microsoftstoragestorageaccountsblobservicescontainersblobsread + source_revision: 0b36331 + 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 collected, mapped, still-valid service-principal credential in the readable content creates + this edge; uncollected, partial, or unverified content is UNKNOWN. + 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: Draft requires azure.storage.blob_credential_holders; the evaluator must join only verified holders, and + return UNKNOWN if that fact is missing or incomplete. diff --git a/src/privilege-escalation-paths/azure/virtual_desktop.yaml b/src/privilege-escalation-paths/azure/virtual_desktop.yaml index 690073f220..f5af16cab6 100644 --- a/src/privilege-escalation-paths/azure/virtual_desktop.yaml +++ b/src/privilege-escalation-paths/azure/virtual_desktop.yaml @@ -29,7 +29,7 @@ description: The command runs in the launching user's session; reaching the host identity requires IMDS to be reachable from that context (not blocked by host firewall). blockers: - azure_deny_assignment - confidence: unknown + confidence: conditional severity: high mitigation: Restrict Desktop Virtualization Application Group Contributor, alert on application filePath / commandLineArguments changes, and keep session-host identities least-privileged. references: @@ -69,3 +69,35 @@ - https://learn.microsoft.com/en-us/azure/virtual-desktop/manage-app-groups - https://learn.microsoft.com/en-us/azure/virtual-desktop/rbac notes: The session-host managed identity half of the same technique is azure-avd-application-write-session-host-rce. Users are those holding Desktop Virtualization User on the application group (directly or through groups). +- id: azure-avd-appattach-share-overwrite-assigned-user + provider: azure + service: virtual_desktop + title: Overwrite an assigned App Attach image to reach launching users + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-virtual-desktop-post-exploitation.md#common-techniques + summary: Writing the exact Azure Files image of an App Attach package can run an accepted replacement in a user + session when the assigned user launches the app. + requires: + all_of: + - action: Microsoft.Storage/storageAccounts/fileServices/fileshares/files/write + data_action: true + scope: '{pivot}' + pivot_resource_type: Microsoft.Storage/storageAccounts + target: + kind: azure_user + selector: + azure_challenge_fact: azure-avd-appattach-share-overwrite-assigned-user + scope: tenant + outcome: credentials + aggregate_as: Assigned users of App Attach packages stored on {pivot} + conditions: + - id: accepted_package_and_user_launch + description: The replacement image must pass package certificate trust and an assigned user must launch the + application; reusable session tokens are conditional. + confidence: conditional + severity: high + mitigation: Restrict writes to App Attach image shares and verify package signatures and assignments. + references: + - https://learn.microsoft.com/en-us/azure/virtual-desktop/app-attach-setup + - https://learn.microsoft.com/en-us/rest/api/desktopvirtualization/app-attach-package/list-by-subscription?view=rest-desktopvirtualization-2025-10-10 + notes: Inert until exact azure_avd_appattach_share_bindings evidence is collected. The generic host-managed-identity + outcome is azure-v3-09-file-share-overwrite; user sessions need separate target evidence. From 968c97dbcae4e59915351805e98f278efe894bd9 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Mon, 12 Oct 2026 21:34:30 +0200 Subject: [PATCH 14/17] Integrate verified Azure unauthenticated and services exclusions Co-Authored-By: Codex --- .../azure/_excluded_audit_g7-data-ai.yaml | 4 +- .../azure/_excluded_pa_az_services_s01.yaml | 32 +++ .../azure/_excluded_unauth_s07.yaml | 186 ++++++++++++++++++ .../azure/_excluded_verify_azure.yaml | 22 +++ .../azure/automation.yaml | 53 ----- 5 files changed, 242 insertions(+), 55 deletions(-) create mode 100644 src/privilege-escalation-paths/azure/_excluded_pa_az_services_s01.yaml create mode 100644 src/privilege-escalation-paths/azure/_excluded_unauth_s07.yaml diff --git a/src/privilege-escalation-paths/azure/_excluded_audit_g7-data-ai.yaml b/src/privilege-escalation-paths/azure/_excluded_audit_g7-data-ai.yaml index 01f5991985..1e1ff3c4cf 100644 --- a/src/privilege-escalation-paths/azure/_excluded_audit_g7-data-ai.yaml +++ b/src/privilege-escalation-paths/azure/_excluded_audit_g7-data-ai.yaml @@ -21,8 +21,8 @@ - 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. + reason: The managed-identity token path is covered by azure-ai-search-skillset-write-identity-token. An AI Search admin key separately grants application-plane administration of indexes, skillsets, indexers and data sources, and document access when API-key authentication is enabled; this is not merely data access. Model that service-plane privilege with a Search-resource target and a machine-checked disableLocalAuth=false condition. + - 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 diff --git a/src/privilege-escalation-paths/azure/_excluded_pa_az_services_s01.yaml b/src/privilege-escalation-paths/azure/_excluded_pa_az_services_s01.yaml new file mode 100644 index 0000000000..f77dd35ab3 --- /dev/null +++ b/src/privilege-escalation-paths/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/azure/_excluded_unauth_s07.yaml b/src/privilege-escalation-paths/azure/_excluded_unauth_s07.yaml new file mode 100644 index 0000000000..c5d2735738 --- /dev/null +++ b/src/privilege-escalation-paths/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/azure/_excluded_verify_azure.yaml b/src/privilege-escalation-paths/azure/_excluded_verify_azure.yaml index d3df68e1cd..d6bb06cad9 100644 --- a/src/privilege-escalation-paths/azure/_excluded_verify_azure.yaml +++ b/src/privilege-escalation-paths/azure/_excluded_verify_azure.yaml @@ -1927,3 +1927,25 @@ reason: The stronger ADE deployment identity is reached only if a future environment deployment consumes the poisoned Git definition. ARM inventory does not reveal Git write authority, catalog commit/content, or the future deploy event; azure-devcenter-ade-deployment-identity additionally requires projects/users/environments/userWrite/action. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-vms-unauth.md#public-gallery-images + technique: Recover credentials embedded in a public community gallery image + source_revision: 0b36331 + reason: Community gallery discovery needs an Azure customer account, but no permission over the publisher's resources. Gaining + another identity needs an accessible image that actually contains a usable credential, its current validity, and a mapped + target principal; publisher URI metadata and the Azure configuration snapshot establish none of these content facts. The + existing sensitive-information-in-images exclusion concerns private gallery or managed-image reads and VM deployment permissions. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-vms-unauth.md#public-extensions + technique: Recover credentials embedded in a publicly listed VM extension image + source_revision: 0b36331 + reason: Listing public extension publisher and type metadata does not reveal package contents. Gaining another identity + needs the extension package to be retrievable and to contain a usable credential mapped to a target principal; these content + and validity facts are absent from configuration. The existing sensitive-information-in-vm-extensions exclusion assumes + permissions to inspect private extensions or applications and install one in a VM. +- source: src/pentesting-cloud/azure-security/az-unauthenticated-enum-and-initial-entry/az-vms-unauth.md#ssrf-to-imds-token-theft + technique: Use public VM application SSRF to obtain its managed-identity token from IMDS + source_revision: 0b36331 + reason: The page describes an anonymous application exploit, with no Azure RBAC permission. Token theft needs a vulnerable + public VM application, SSRF access from that VM to IMDS, control or forwarding of the Metadata header, disclosure of the + token response, and an attached managed identity; application exploitability and response behavior are runtime facts absent + from the Azure configuration snapshot. VM management-action entries require authenticated ARM permissions and do not cover + this path. diff --git a/src/privilege-escalation-paths/azure/automation.yaml b/src/privilege-escalation-paths/azure/automation.yaml index df61165252..22e2c7e7ef 100644 --- a/src/privilege-escalation-paths/azure/automation.yaml +++ b/src/privilege-escalation-paths/azure/automation.yaml @@ -162,59 +162,6 @@ - https://learn.microsoft.com/en-us/azure/automation/shared-resources/credentials notes: User sibling of azure-automation-runbook-credential-assets (PSCredential assets usually hold user name/password pairs); MFA or Conditional Access on the user may block interactive reuse. -- 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/draft/write - scope: "{pivot}" - - action: Microsoft.Automation/automationAccounts/runbooks/draft/content/write - scope: "{pivot}" - - action: Microsoft.Automation/automationAccounts/runbooks/publish/action - scope: "{pivot}" - - action: Microsoft.Automation/automationAccounts/jobs/write - scope: "{pivot}" - - - action: Microsoft.Automation/automationAccounts/runbooks/write - scope: "{pivot}" - - action: Microsoft.Automation/automationAccounts/runbooks/draft/content/write - scope: "{pivot}" - - action: Microsoft.Automation/automationAccounts/runbooks/publish/action - scope: "{pivot}" - - action: Microsoft.Automation/automationAccounts/jobs/write - scope: "{pivot}" - - - action: Microsoft.Automation/automationAccounts/runbooks/draft/write - scope: "{pivot}" - - action: Microsoft.Automation/automationAccounts/runbooks/draft/content/write - scope: "{pivot}" - - action: Microsoft.Automation/automationAccounts/runbooks/draft/testJob/write - scope: "{pivot}" - pivot_resource_type: Microsoft.Automation/automationAccounts - target: - kind: azure_managed_identity - selector: - attached_to_service: - - Microsoft.Compute/virtualMachines - - Microsoft.HybridCompute/machines - azure_host_linked_to_pivot: automation_hybrid_worker - scope: any - aggregate_as: "Managed identities of Hybrid Worker VMs / Arc machines of Automation account {pivot}" - conditions: - - id: worker_is_azure_vm - description: Only Hybrid Workers that are Azure VMs / Arc machines with managed identities expose cloud identities; on-prem workers yield OS context only. - blockers: [] - confidence: derived - 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: Jobs also run as SYSTEM/root on the worker. Arc-enabled server workers expose the Arc machine identity (worker vmResourceId is the Microsoft.HybridCompute/machines id), hence both host types in attached_to_service. - - id: azure-automation-assign-user-assigned-identity provider: azure service: automation From 83799c06456dd4742dd79177b566cbf018aa58f5 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Mon, 12 Oct 2026 21:37:29 +0200 Subject: [PATCH 15/17] Integrate verified Azure services privilege paths Co-Authored-By: Codex --- .../azure/_excluded_rbac.yaml | 2 +- .../azure/_excluded_rbac_refresh_c.yaml | 3 + .../azure/app_services.yaml | 29 ++++++++ .../azure/service_linker.yaml | 36 ++++++++++ .../azure/spring_apps.yaml | 66 ++++++++++++++++++ .../azure/sre_agent.yaml | 58 ++++++++++++++++ .../azure/storage.yaml | 67 +++++++++++++++++++ 7 files changed, 260 insertions(+), 1 deletion(-) create mode 100644 src/privilege-escalation-paths/azure/service_linker.yaml diff --git a/src/privilege-escalation-paths/azure/_excluded_rbac.yaml b/src/privilege-escalation-paths/azure/_excluded_rbac.yaml index 2c8abfe7bb..d5b79a0b61 100644 --- a/src/privilege-escalation-paths/azure/_excluded_rbac.yaml +++ b/src/privilege-escalation-paths/azure/_excluded_rbac.yaml @@ -24,7 +24,7 @@ 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. + reason: The permission grants raw VHD data access. The VHD may contain usable cloud credentials, but their presence, validity and target principal depend on disk contents that an Azure RBAC snapshot cannot determine. - 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. diff --git a/src/privilege-escalation-paths/azure/_excluded_rbac_refresh_c.yaml b/src/privilege-escalation-paths/azure/_excluded_rbac_refresh_c.yaml index 17a689b99b..388f42d4d1 100644 --- a/src/privilege-escalation-paths/azure/_excluded_rbac_refresh_c.yaml +++ b/src/privilege-escalation-paths/azure/_excluded_rbac_refresh_c.yaml @@ -90,3 +90,6 @@ - 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." +- source: src/pentesting-cloud/azure-security/az-services/vms/README.md#goalstate--extensionsconfig + technique: Inspect Azure WireServer GoalState or ExtensionsConfig for extension secrets + reason: The page describes possible secrets in extension-specific configuration, but an Azure RBAC snapshot cannot establish that a guest process can reach WireServer, that a configured extension exposes a usable secret at runtime, or which principal that secret authenticates. The request requires an existing in-guest foothold; RBAC paths to guest execution and the VM's attached managed identities are covered in virtual_machines.yaml. diff --git a/src/privilege-escalation-paths/azure/app_services.yaml b/src/privilege-escalation-paths/azure/app_services.yaml index 6060ec317d..2f392f80c4 100644 --- a/src/privilege-escalation-paths/azure/app_services.yaml +++ b/src/privilege-escalation-paths/azure/app_services.yaml @@ -515,3 +515,32 @@ references: - https://learn.microsoft.com/en-us/rest/api/appservice/web-apps/get-process-dump notes: The Kudu path with publishing credentials or publish/action is already covered by azure-appservice-kudu-publish-action and the publishing-credential entries. +- id: azure-app-services-read-configured-third-party-credentials + provider: azure + service: app_services + title: Read configured third-party source-control OAuth tokens + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md#read-configured-third-party-credentials + source_revision: 0b36331 + summary: Read the stored third-party source-control OAuth tokens (GitHub, Bitbucket, Dropbox, OneDrive) exposed to the account → pivot into those external accounts (repos, files) with the returned tokens. + requires: + all_of: + - action: Microsoft.Web/sourcecontrols/read + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + azure_challenge_fact: azure-app-services-read-configured-third-party-credentials + scope: inherited_scope + aggregate_as: Pending service authority for app_services + outcome: application_admin + grants: + - The configured third-party GitHub, Bitbucket, Dropbox or OneDrive OAuth identity. + conditions: + - id: collector_fact_required + description: The azure_web_sourcecontrols inventory must identify the exact target and rights; absent or incomplete facts remain UNKNOWN. + confidence: conditional + severity: medium + mitigation: Restrict the listed permissions to trusted operators and rotate or revoke resulting credentials or grants. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/azure-security/az-privilege-escalation/az-static-web-apps-privesc.md + notes: 'Collector fact required: azure_web_sourcecontrols. UNKNOWN until configured token, owner, and scope are inventoried.' diff --git a/src/privilege-escalation-paths/azure/service_linker.yaml b/src/privilege-escalation-paths/azure/service_linker.yaml new file mode 100644 index 0000000000..588df5898a --- /dev/null +++ b/src/privilege-escalation-paths/azure/service_linker.yaml @@ -0,0 +1,36 @@ +- id: azure-service-linker-read-connection-configuration-to-exfiltrate-the-backing-secret + provider: azure + service: service_linker + title: Read a Service Linker backing credential + source: src/pentesting-cloud/azure-security/az-post-exploitation/az-service-connector-post-exploitation.md#read-connection-configuration-to-exfiltrate-the-backing-secret + source_revision: 0b36331 + summary: for every secret-based connection, listConfigurations / generateConfigurations return the plaintext connection string with the embedded secret (e.g. AZURE_STORAGEBLOB_CONNECTIONSTRING=...;AccountKey=;..., a SQL/PostgreSQL password, a Cosmos DB key). The crucial part is that Service Connector Contributor is scoped to Microsoft.ServiceLinker/* only — it does not include Microsoft.Storage/storageAccounts/listKeys, Microsoft.DocumentDB/.../listKeys, the DB listKeys/admin actions, or Key Vault data actions — yet the config read hands back the underlying secret anyway. So a principal holdi + requires: + all_of: [] + any_of: + - - action: Microsoft.ServiceLinker/linkers/read + scope: '{target.scope}' + - action: Microsoft.ServiceLinker/linkers/listConfigurations/action + scope: '{target.scope}' + - - action: Microsoft.ServiceLinker/linkers/read + scope: '{target.scope}' + - action: Microsoft.ServiceLinker/linkers/generateConfigurations/action + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + azure_challenge_fact: azure-service-linker-read-connection-configuration-to-exfiltrate-the-backing-secret + scope: inherited_scope + aggregate_as: Pending service authority for service_linker + outcome: application_admin + grants: + - Each source linker’s backing Storage, SQL, PostgreSQL or Cosmos DB credential returned in its configuration. + conditions: + - id: collector_fact_required + description: The azure_service_linkers inventory must identify the exact target and rights; absent or incomplete facts remain UNKNOWN. + confidence: conditional + severity: medium + mitigation: Restrict the listed permissions to trusted operators and rotate or revoke resulting credentials or grants. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/azure-security/az-post-exploitation/az-service-connector-post-exploitation.md + notes: 'Collector fact required: azure_service_linkers. UNKNOWN until the linker authentication type and target credential principal are collected; never persist secret values.' diff --git a/src/privilege-escalation-paths/azure/spring_apps.yaml b/src/privilege-escalation-paths/azure/spring_apps.yaml index b14e4a68df..60b6ce8407 100644 --- a/src/privilege-escalation-paths/azure/spring_apps.yaml +++ b/src/privilege-escalation-paths/azure/spring_apps.yaml @@ -157,3 +157,69 @@ - https://learn.microsoft.com/en-us/azure/spring-apps/basic-standard/retirement-announcement notes: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must evaluate UNKNOWN. Collector fact required: springApps.builderBindings.' +- id: azure-spring-apps-microsoftappplatformspringapmslistsecretkeysaction + provider: azure + service: spring_apps + title: Obtain Spring Apps APM integration credentials + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#microsoftappplatformspringapmslistsecretkeysaction + source_revision: 0b36331 + summary: returns the secret keys of a Spring Apps APM (Application Performance Monitor) integration. An APM config holds the credentials Spring Apps uses to ship telemetry to a monitoring backend — e.g. an Application Insights connection string, or a New Relic license key / Dynatrace API token / AppDynamics / Elastic APM secret. Stealing them grants access to the org's monitoring backend (read telemetry that itself often leaks internal hostnames, SQL, headers and tokens; inject or forge telemetry) and, for third-party SaaS APMs, a credential to pivot into that external account. Distinct from the config + requires: + all_of: + - action: Microsoft.AppPlatform/Spring/apms/listSecretKeys/action + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + azure_challenge_fact: azure-spring-apps-microsoftappplatformspringapmslistsecretkeysaction + scope: inherited_scope + aggregate_as: Pending service authority for spring_apps + outcome: application_admin + grants: + - The named APM integration key or telemetry-backend token configured on the Spring Apps service. + conditions: + - id: collector_fact_required + description: The azure_spring_apms inventory must identify the exact target and rights; absent or incomplete facts remain UNKNOWN. + confidence: conditional + severity: medium + mitigation: Restrict the listed permissions to trusted operators and rotate or revoke resulting credentials or grants. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md + notes: 'Collector fact required: azure_spring_apms. UNKNOWN until backend and credential type are known; telemetry ingestion-only keys are not privileged principals.' +- id: azure-spring-apps-config-server-bindings-secret-exposure + provider: azure + service: spring_apps + title: Read Spring Apps environment and binding secrets + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md#config-server--bindings--secret-exposure + source_revision: 0b36331 + summary: The page explicitly describes environment-variable and binding secret exposure; a secret-bearing configuration is a credential target when present. + requires: + all_of: [] + any_of: + - - action: Microsoft.AppPlatform/Spring/apps/read + scope: '{target.scope}' + data_action: true + - - action: Microsoft.AppPlatform/Spring/apps/bindings/read + scope: '{target.scope}' + data_action: true + - - action: Microsoft.AppPlatform/Spring/configService/read + scope: '{target.scope}' + data_action: true + target: + kind: azure_dataplane_admin + selector: + azure_challenge_fact: azure-spring-apps-config-server-bindings-secret-exposure + scope: inherited_scope + aggregate_as: Pending service authority for spring_apps + outcome: application_admin + grants: + - Actual configured application environment or binding credential; no target if no secret value exists. + conditions: + - id: collector_fact_required + description: The azure_spring_app_secrets inventory must identify the exact target and rights; absent or incomplete facts remain UNKNOWN. + confidence: conditional + severity: medium + mitigation: Restrict the listed permissions to trusted operators and rotate or revoke resulting credentials or grants. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/azure-security/az-privilege-escalation/az-spring-apps-privesc.md + notes: 'Collector fact required: azure_spring_app_secrets. UNKNOWN until actual secret-bearing configuration and its principal are identified; poisoned config requires runtime consumption.' diff --git a/src/privilege-escalation-paths/azure/sre_agent.yaml b/src/privilege-escalation-paths/azure/sre_agent.yaml index de7388efc7..dd6c494e21 100644 --- a/src/privilege-escalation-paths/azure/sre_agent.yaml +++ b/src/privilege-escalation-paths/azure/sre_agent.yaml @@ -108,3 +108,61 @@ - https://learn.microsoft.com/en-us/azure/sre-agent/overview notes: 'Draft is disabled until the stated schema feature or collector fact is implemented; unresolved facts must evaluate UNKNOWN. Collector fact required: sreAgents.pendingApprovals.' +- id: azure-sre-agent-microsoftappagentsdataconnectorslistsecretsaction + provider: azure + service: sre_agent + title: Read an SRE Agent connector credential + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sre-agent-privesc.md#microsoftappagentsdataconnectorslistsecretsaction + source_revision: 0b36331 + summary: Returns the cleartext protected configuration of one connector (dataSource and protected CustomHeader values normally redacted on GET) -> reusable credentials to source code, telemetry, incident-management systems, or other external data. Scope is the downstream service permissions of each returned credential; callable against a known connector ID without agent/connector read. + requires: + all_of: + - action: Microsoft.App/agents/dataconnectors/listSecrets/action + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + azure_challenge_fact: azure-sre-agent-microsoftappagentsdataconnectorslistsecretsaction + scope: inherited_scope + aggregate_as: Pending service authority for sre_agent + outcome: application_admin + grants: + - The exact SRE Agent OAuth/private-key credential or named data connector credential returned by listSecrets. + conditions: + - id: collector_fact_required + description: The azure_sre_connector_secrets inventory must identify the exact target and rights; absent or incomplete facts remain UNKNOWN. + confidence: conditional + severity: medium + mitigation: Restrict the listed permissions to trusted operators and rotate or revoke resulting credentials or grants. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/azure-security/az-privilege-escalation/az-sre-agent-privesc.md + notes: 'Collector fact required: azure_sre_connector_secrets. UNKNOWN until a reusable credential and its target principal/rights are identified.' +- id: azure-sre-agent-microsoftappagentslistsecretsaction + provider: azure + service: sre_agent + title: Read an SRE Agent protected credential + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-sre-agent-privesc.md#microsoftappagentslistsecretsaction + source_revision: 0b36331 + summary: Control-plane action returning the protected secrets of an SRE Agent (can include private key material / generated OAuth key). Callable against a known agent ID without Microsoft.App/agents/read -> credential disclosure; downstream scope is whatever the recovered key grants. + requires: + all_of: + - action: Microsoft.App/agents/listSecrets/action + scope: '{target.scope}' + target: + kind: azure_dataplane_admin + selector: + azure_challenge_fact: azure-sre-agent-microsoftappagentslistsecretsaction + scope: inherited_scope + aggregate_as: Pending service authority for sre_agent + outcome: application_admin + grants: + - The exact SRE Agent OAuth/private-key credential or named data connector credential returned by listSecrets. + conditions: + - id: collector_fact_required + description: The azure_sre_agent_secrets inventory must identify the exact target and rights; absent or incomplete facts remain UNKNOWN. + confidence: conditional + severity: medium + mitigation: Restrict the listed permissions to trusted operators and rotate or revoke resulting credentials or grants. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/azure-security/az-privilege-escalation/az-sre-agent-privesc.md + notes: 'Collector fact required: azure_sre_agent_secrets. UNKNOWN until the protected value is known to be a reusable privileged credential.' diff --git a/src/privilege-escalation-paths/azure/storage.yaml b/src/privilege-escalation-paths/azure/storage.yaml index 7c66cc1bd1..648261220a 100644 --- a/src/privilege-escalation-paths/azure/storage.yaml +++ b/src/privilege-escalation-paths/azure/storage.yaml @@ -210,3 +210,70 @@ - https://learn.microsoft.com/en-us/rest/api/storageservices/get-blob notes: Draft requires azure.storage.blob_credential_holders; the evaluator must join only verified holders, and return UNKNOWN if that fact is missing or incomplete. +- id: azure-storage-hns-acl-takeover-and-blob-super-user-data-action + provider: azure + service: storage + title: Rewrite ADLS Gen2 path ACLs for new access + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#hns-acl-takeover-and-blob-super-user-data-action + source_revision: 0b36331 + summary: modifyPermissions can grant the caller previously denied file access when ancestor execute and a read grant are present; the exclusion treats the gain as ordinary data read. + requires: + all_of: [] + any_of: + - - action: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/modifyPermissions/action + scope: '{target.scope}' + data_action: true + - - action: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/manageOwnership/action + scope: '{target.scope}' + data_action: true + - - action: Microsoft.Storage/storageAccounts/blobServices/containers/blobs/runAsSuperUser/action + scope: '{target.scope}' + data_action: true + target: + kind: azure_dataplane_admin + selector: + azure_challenge_fact: azure-storage-hns-acl-takeover-and-blob-super-user-data-action + scope: inherited_scope + aggregate_as: Pending service authority for storage + outcome: application_admin + grants: + - Target ADLS Gen2 path whose POSIX ACL the principal can modify; access requires ancestor execute plus data read. + conditions: + - id: collector_fact_required + description: The azure_adls_acl_paths inventory must identify the exact target and rights; absent or incomplete facts remain UNKNOWN. + confidence: conditional + severity: medium + mitigation: Restrict the listed permissions to trusted operators and rotate or revoke resulting credentials or grants. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md + notes: 'Collector fact required: azure_adls_acl_paths. UNKNOWN until path ACL, ancestors, and separate data-read grant are collected.' +- id: azure-storage-microsoftstoragestorageaccountsfileservicesfilesharesfilesmodifypermissionsact + provider: azure + service: storage + title: Rewrite Azure Files NTFS ACLs for new access + source: src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md#microsoftstoragestorageaccountsfileservicesfilesharesfilesmodifypermissionsaction + source_revision: 0b36331 + summary: The action can rewrite NTFS ACLs to grant the caller previously denied file permissions; separate file read is required for content. + requires: + all_of: + - action: Microsoft.Storage/storageAccounts/fileServices/fileshares/files/modifypermissions/action + scope: '{target.scope}' + data_action: true + target: + kind: azure_dataplane_admin + selector: + azure_challenge_fact: azure-storage-microsoftstoragestorageaccountsfileservicesfilesharesfilesmodifypermissionsact + scope: inherited_scope + aggregate_as: Pending service authority for storage + outcome: application_admin + grants: + - Target Azure Files path whose NTFS ACL the principal can modify; access requires a separate file data read action. + conditions: + - id: collector_fact_required + description: The azure_files_acls inventory must identify the exact target and rights; absent or incomplete facts remain UNKNOWN. + confidence: conditional + severity: medium + mitigation: Restrict the listed permissions to trusted operators and rotate or revoke resulting credentials or grants. + references: + - https://github.com/HackTricks-wiki/hacktricks-cloud/blob/0b36331/src/pentesting-cloud/azure-security/az-privilege-escalation/az-storage-privesc.md + notes: 'Collector fact required: azure_files_acls. UNKNOWN until NTFS ACL and separate file read/write grant are collected.' From 2a7a278c3ecc1a6e72f7a7750eaebfdbf13383c3 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Mon, 12 Oct 2026 21:40:22 +0200 Subject: [PATCH 16/17] Integrate verified Kubernetes and cross-provider privilege catalog fragments Co-Authored-By: Codex --- .../_excluded_challenge_crossprovider.yaml | 6 + .../azure/_excluded_crossprovider_s05.yaml | 173 ++++++++++++++++ .../azure/_excluded_crossprovider_s06.yaml | 187 ++++++++++++++++++ .../gcp/_excluded.yaml | 6 + .../gcp/challenge-v3.yaml | 62 +++++- .../k8s/_excluded.yaml | 102 +++++++++- .../k8s/cloud_pivot.yaml | 71 +++++-- .../k8s/workloads.yaml | 150 +++++++++++--- 8 files changed, 701 insertions(+), 56 deletions(-) create mode 100644 src/privilege-escalation-paths/azure/_excluded_crossprovider_s05.yaml create mode 100644 src/privilege-escalation-paths/azure/_excluded_crossprovider_s06.yaml diff --git a/src/privilege-escalation-paths/azure/_excluded_challenge_crossprovider.yaml b/src/privilege-escalation-paths/azure/_excluded_challenge_crossprovider.yaml index b53d9f049e..b09237838a 100644 --- a/src/privilege-escalation-paths/azure/_excluded_challenge_crossprovider.yaml +++ b/src/privilege-escalation-paths/azure/_excluded_challenge_crossprovider.yaml @@ -16,3 +16,9 @@ - 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. + +- source: src/pentesting-cloud/digital-ocean-pentesting/do-basic-information.md#api-keys + technique: Read another user’s doctl token from host config + reason: Reading another user’s doctl config could yield that user’s PAT, but host file readability, token validity, + owner, scopes and team role are runtime facts. DigitalOcean is not a supported catalog provider; no DigitalOcean + identity or PAT selector exists in the schema. diff --git a/src/privilege-escalation-paths/azure/_excluded_crossprovider_s05.yaml b/src/privilege-escalation-paths/azure/_excluded_crossprovider_s05.yaml new file mode 100644 index 0000000000..a81dbe1a72 --- /dev/null +++ b/src/privilege-escalation-paths/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/azure/_excluded_crossprovider_s06.yaml b/src/privilege-escalation-paths/azure/_excluded_crossprovider_s06.yaml new file mode 100644 index 0000000000..7ce924bb59 --- /dev/null +++ b/src/privilege-escalation-paths/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/gcp/_excluded.yaml b/src/privilege-escalation-paths/gcp/_excluded.yaml index 769447a1f9..32ba85393a 100644 --- a/src/privilege-escalation-paths/gcp/_excluded.yaml +++ b/src/privilege-escalation-paths/gcp/_excluded.yaml @@ -2757,3 +2757,9 @@ technique: Read public Google Groups messages that may contain pasted secrets reason: A public Google Groups archive discloses messages, not group membership; a credential gain requires a usable secret actually pasted in a message and validation of its owner and current validity. + +- source: src/pentesting-cloud/workspace-security/README.md#password-spraying + technique: Obtain a Workspace user password by password spraying + reason: Successful guessing of a victim password is an identity gain, but the page supplies only a spray tool. + A valid password, accepted authentication, MFA state and exact victim are runtime facts absent from a configuration + snapshot. diff --git a/src/privilege-escalation-paths/gcp/challenge-v3.yaml b/src/privilege-escalation-paths/gcp/challenge-v3.yaml index d23edb6f0e..e3bb284ce8 100644 --- a/src/privilege-escalation-paths/gcp/challenge-v3.yaml +++ b/src/privilege-escalation-paths/gcp/challenge-v3.yaml @@ -468,9 +468,7 @@ Exact source, target, scope and prerequisite proof are required. requires: all_of: [] - source_kind: - - gcp_user - - gcp_service_account + source_kind: gcp_challenge_foothold target: kind: gcp_group selector: @@ -489,6 +487,7 @@ mitigation: Restrict the named capability and verify the exact execution, credential or trust relationship. notes: Collector request recorded in privesc-v3-collector-requests.md. Absent or incomplete evidence is UNKNOWN/unresolved; verified evidence remains conditional. + - id: gcp-v3-18-create-a-second-google-workspace-super-admin provider: gcp service: workspace @@ -1436,3 +1435,60 @@ mitigation: Restrict the named capability and verify the exact execution, credential or trust relationship. notes: Collector request recorded in privesc-v3-collector-requests.md. Absent or incomplete evidence is UNKNOWN/unresolved; verified evidence remains conditional. + +- id: gcp-workspace-admin-password-reset-2sv-takeover + provider: gcp + service: workspace + title: Take over a Workspace user with password reset and 2SV control + source: src/pentesting-cloud/workspace-security/gws-admin-privesc.md#account-takeover-reset-password--strip-2-step-verification + summary: An admin able to reset a user password and disable 2SV or generate backup codes can sign in as that user. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_workspace_user + selector: + gcp_challenge_fact: gcp-workspace-admin-password-reset-2sv-takeover + scope: any + aggregate_as: Exact verified target of Take over a Workspace user with password reset and 2SV control + conditions: + - id: exact_verified_prerequisites + description: Join the exact admin, target user and OU; require effective User Management or Help Desk password-reset + privilege plus Security Manage 2SV privilege, and either disable-2SV or backup-code ability. Exclude super-admin + targets and unresolved login challenges. Sign-in remains conditional. + confidence: conditional + severity: high + mitigation: Restrict the relevant Workspace or external-directory rights and monitor changes to the exact target. + references: + - https://support.google.com/a/answer/33319 + - https://support.google.com/a/answer/9176734 + notes: A missing or incomplete collector fact evaluates UNKNOWN; a verified fact remains conditional. + +- id: gcp-workspace-directory-sync-activation-mailbox + provider: gcp + service: workspace + title: Claim a newly synced Workspace user through its activation mailbox + 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 + summary: An actor controlling the mapped activation mailbox of a newly synced user can set that user’s Google + password and inherit its group grants. + requires: + all_of: [] + source_kind: gcp_challenge_foothold + target: + kind: gcp_workspace_user + selector: + gcp_challenge_fact: gcp-workspace-directory-sync-activation-mailbox + scope: any + aggregate_as: Exact verified target of Claim a newly synced Workspace user through its activation mailbox + conditions: + - id: exact_verified_prerequisites + description: Require exact new unactivated user selected by Directory Sync, enabled activation email, mapped + primary or recovery mailbox controlled by the source, and no SSO flow that prevents local password sign-in. + Existing-account mailbox access does not suffice. Activation and sign-in remain conditional. + confidence: conditional + severity: high + mitigation: Restrict the relevant Workspace or external-directory rights and monitor changes to the exact target. + references: + - https://knowledge.workspace.google.com/admin/users/set-up-user-sync + - https://knowledge.workspace.google.com/admin/users/directory-sync-faq + notes: A missing or incomplete collector fact evaluates UNKNOWN; a verified fact remains conditional. diff --git a/src/privilege-escalation-paths/k8s/_excluded.yaml b/src/privilege-escalation-paths/k8s/_excluded.yaml index b72ee8e385..f8d8f35685 100644 --- a/src/privilege-escalation-paths/k8s/_excluded.yaml +++ b/src/privilege-escalation-paths/k8s/_excluded.yaml @@ -33,7 +33,12 @@ reason: GCP-to-Kubernetes edge driven by GCP IAM; belongs to the gcp catalog (gcp-container-privesc). - 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. + reason: A validating webhook cannot mutate objects, but it can receive the complete AdmissionReview for a later + matching Secret create/update. Observation is data disclosure unless that exact review contains a still-valid + credential for another identity; such an event and credential are runtime/content facts unavailable to a configuration + snapshot. Mutating webhook code injection is k8s-workloads-mutating-webhook-injection; weakening an existing + configuration is k8s-admission-webhook-configuration-weaken. + - source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/storage-and-networking.md#services-status-cve-2020-8554 technique: services/status LoadBalancer IP spoofing (CVE-2020-8554) reason: Traffic interception (MiTM); no new identity. @@ -292,7 +297,12 @@ reason: Covered by k8s-workloads-pods-create (automountServiceAccountToken is not treated as a blocker). - source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.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). + reason: The disposable PROOF marker in this example is data, not an identity. If the referenced same-namespace + Secret contains a usable token or certificate for another principal, Pod creation can expose that identity; + the generic Argo CD Pod-mount path is proposed as k8s-workloads-pods-mount-argocd-cluster-credential, subject + to credential evidence and admission. The init-container field omission is only a policy-specific route to that + edge. + - source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#scoped-resourcequota-gap technique: Scoped ResourceQuota gap reason: Resource-exhaustion / DoS. @@ -396,7 +406,11 @@ 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. + reason: The manifest creates a synthetic Opaque username/password Secret and a Pod that reads that same Secret; + it does not demonstrate obtaining another principal's credentials. Creating a Pod to run as a stronger ServiceAccount + is covered by k8s-workloads-pods-create. Mounting a pre-existing static Google service-account key is covered + by k8s-cloud-pivot-secret-static-gcp-sa-key. + - 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. @@ -585,3 +599,85 @@ - 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. + +- source: src/pentesting-cloud/kubernetes-security/kubernetes-basic-information/access-and-common-concepts.md#kubeconfig-contexts-and-kubectl + technique: Malicious kubeconfig exec credential plugin + reason: An attacker must control a local kubeconfig or its referenced executable and induce another user to run + a client command. Execution and the user's local credentials are workstation runtime facts outside the Kubernetes + and cloud configuration snapshot; no Kubernetes API permission or identifiable catalog target follows from the + kubeconfig warning alone. + +- source: src/pentesting-cloud/kubernetes-security/kubernetes-persistence/workloads-and-gitops.md#helm-release-source-as-a-return-path + technique: Patch existing Flux HelmRelease values under a stronger applier + reason: HelmRelease patch/update permission alone does not show that an existing release accepts the change or + that its chart renders attacker-controlled values into a privileged object. The selected chart content, ownership + and later reconciliation, effective deployer ServiceAccount, and admission result must be verified; the current + snapshot does not collect these content and runtime facts. + +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#pivot-through-an-allowed-application + technique: URL fetcher acts as allowed network intermediary + reason: NetworkPolicy and Service objects cannot establish that the application accepts a caller-controlled destination, + forwards the request, or is authorized by the backend. The application's fetch behavior and a successful live + second hop are required to prove use of the intermediary's access. + +- source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/internal-network-attacks.md#abusing-exposed-kubernetes-management-services + technique: Use exposed management app stronger Kubernetes credential + reason: Service exposure does not show that the caller can authenticate to or exploit NiFi, Kubeflow, Argo Workflows, + Weave Scope, or Dashboard. Each application's runtime authentication, reachable endpoint, credential use, and + effective Kubernetes grants must be verified; no common Kubernetes RBAC source permission establishes this edge. + +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#other-gitops-and-platform-controller-source-changes + technique: Crossplane ProviderConfig kubeconfig applies into remote cluster + reason: Object write permission does not identify the referenced ProviderConfig's Secret credential or the remote + cluster and its effective RBAC. The ProviderConfig-to-Secret reference, kubeconfig content/credential validity, + remote endpoint, and remote authorization must be collected and joined before this can target a remote principal. + The existing Crossplane entry covers only InjectedIdentity in the local cluster. + +- source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/validating-admission-policies.md#tested-admission-control-mutations + source_revision: 0b36331 + technique: Create validating webhook to receive a later credential-bearing Secret AdmissionReview + reason: The webhook receives a Secret only if a later create or update request matches its rules and the API server + reaches its trusted TLS endpoint. An existing token Secret is never sent retroactively. The later request, delivered + AdmissionReview content, token validity, and ownership of a stronger identity are runtime/content facts absent + from a configuration snapshot; create validatingwebhookconfigurations alone cannot establish a credential edge. + Noncredential Secret observations remain data disclosure. + +- source: src/pentesting-ci-cd/argocd-security.md#public-api--ui-attacks + technique: Use Argo CD application write through its own API/RBAC to deploy attacker manifests + reason: The Argo CD API uses Argo CD RBAC rather than Kubernetes applications CRD write grants. Effective Argo + CD policy, API authentication, project constraints, sync state and controller identity are not collected; the + existing Kubernetes entry covers only direct CRD writes. + +- source: src/pentesting-ci-cd/argocd-security.md#trusted-git-repository-abuse + technique: Push attacker manifests to an Argo CD trusted Git repository + reason: A Git push is useful only for a repository and path consumed by an Application that can sync into an allowed + destination. SCM rights, repository-to-Application mapping, project restrictions and sync state are uncollected. + +- source: src/pentesting-ci-cd/argocd-security.md#public-api--ui-attacks + technique: Steal Argo CD repository credentials or local/project tokens + reason: Repository SSH keys, GitHub App credentials and local/project API tokens are distinct from registered-cluster + Secrets. Their secret type, bytes, validity, scopes and the source’s read permission are not collected. + +- source: src/pentesting-ci-cd/argocd-security.md#unauthenticated-repo-server-rce-via-kustomize-options + technique: Reach internal repo-server gRPC and execute attacker repository payload + reason: The repo-server exploit requires network reachability to its internal gRPC endpoint, an affected version/request + behavior and attacker repository content. Kubernetes pod creation or API read alone proves none of these runtime + facts. + +- source: src/pentesting-ci-cd/argocd-security.md#redis-cache-poisoning-to-deploy-manifests + technique: Poison Argo CD Redis manifest and Git-ref cache to make controller apply a manifest + reason: Redis cache poisoning requires reachable Redis with usable authentication, writable mfst and git-refs + entries, a susceptible Argo CD version, sync and permissible project/controller rights. Cache contents and runtime + networking are absent. + +- source: src/pentesting-ci-cd/argocd-security.md#applicationset-attacks + technique: Control ApplicationSet Git or pull-request generator input to create privileged Applications + reason: ApplicationSet generator input can create privileged Applications only when attacker-controlled Git or + PR data feeds template fields that permit the desired destination and sync. Generator/template fields, SCM rights, + project policy and sync state are uncollected; direct CRD write also needs these joins. + +- source: src/pentesting-ci-cd/argocd-security.md#post-exploitation + technique: Steal Argo CD pod-mounted repository, cloud, Redis or cluster credentials + reason: A pod shell may expose mounted repository, cloud or Redis credentials, but the mounted bytes, validity + and target principal are not collected. The existing pods/exec entry covers the pod ServiceAccount, and the + cluster-Secret entry covers readable Argo CD registered-cluster Secrets. diff --git a/src/privilege-escalation-paths/k8s/cloud_pivot.yaml b/src/privilege-escalation-paths/k8s/cloud_pivot.yaml index c130661aff..cae3c53d88 100644 --- a/src/privilege-escalation-paths/k8s/cloud_pivot.yaml +++ b/src/privilege-escalation-paths/k8s/cloud_pivot.yaml @@ -348,36 +348,69 @@ title: Ordinary pod reaches the node metadata service source: src/pentesting-cloud/kubernetes-security/kubernetes-post-exploitation/kubernetes-pivoting-to-clouds.md#node-iam-role-to-cluster-admin source_revision: a66f094ede - summary: The source can obtain the privileges of the node cloud identity by creating any pod when pods can reach the instance metadata service. + 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}"} + - 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}" + 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] + - 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: derived severity: high - mitigation: Block pod access to IMDS (hop limit 1, disablePodIMDS, GKE Workload Identity, egress policies) and use workload identities instead. + 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. + - 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: Creating a Pod or workload controller also requires the workload to pass admission; the admission_policy, + admission_webhook, kyverno_policy, and gatekeeper_constraint blockers above apply. Once an ordinary Pod is admitted, + IMDS hop limit and network reachability decide whether it can obtain node credentials. Exec into an existing + Pod gives the same network reach and is modelled implicitly through the ServiceAccount chain. - id: k8s-cloud-hostnetwork-pod-node-identity provider: k8s diff --git a/src/privilege-escalation-paths/k8s/workloads.yaml b/src/privilege-escalation-paths/k8s/workloads.yaml index 6d8b353607..10cd9c1c6b 100644 --- a/src/privilege-escalation-paths/k8s/workloads.yaml +++ b/src/privilege-escalation-paths/k8s/workloads.yaml @@ -410,35 +410,42 @@ title: Create a Flux Kustomization without a ServiceAccount so kustomize-controller applies it source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#flux-kustomization-without-a-tenant-serviceaccount source_revision: 171e422 - summary: The source can obtain the privileges of the Flux kustomize-controller ServiceAccount by creating a Kustomization (and a source it controls) that the controller reconciles with its own identity. + summary: The source can obtain the privileges of the Flux kustomize-controller ServiceAccount by creating a Kustomization + that selects attacker-controlled content in an existing or newly created Flux source and is reconciled with + the controller identity. requires: all_of: - - {verb: create, resource: kustomizations, api_group: kustomize.toolkit.fluxcd.io, namespace: "{pivot.namespace}"} - any_of: - - - {verb: create, resource: gitrepositories, api_group: source.toolkit.fluxcd.io, namespace: "{pivot.namespace}"} - - - {verb: create, resource: ocirepositories, api_group: source.toolkit.fluxcd.io, namespace: "{pivot.namespace}"} - - - {verb: create, resource: buckets, api_group: source.toolkit.fluxcd.io, namespace: "{pivot.namespace}"} + - verb: create + resource: kustomizations + api_group: kustomize.toolkit.fluxcd.io + namespace: '{pivot.namespace}' target: kind: k8s_service_account selector: k8s_sa_name: kustomize-controller scope: cluster - aggregate_as: "Flux kustomize-controller of {cluster}" + aggregate_as: Flux kustomize-controller of {cluster} conditions: - - id: flux_default_service_account_flag - description: The controller flag --default-service-account (Flux multi-tenancy lockdown) makes Kustomizations without spec.serviceAccountName impersonate a tenant ServiceAccount instead; controller arguments are not collected. - - id: flux_controller_rbac - description: The default Flux install binds cluster-admin to kustomize-controller (cluster-reconciler ClusterRoleBinding); the reached privileges are those of that binding. - - id: source_controlled_by_attacker - description: The source object must point to content the principal controls; source-controller network egress and --no-cross-namespace-refs may restrict it. + - id: flux_default_service_account_flag + description: The controller flag --default-service-account makes Kustomizations without spec.serviceAccountName + impersonate a tenant ServiceAccount instead; controller arguments are not collected. + - id: flux_controller_rbac + description: The reached privileges are the kustomize-controller ServiceAccount's effective bindings, which + must exceed the caller's grants. + - id: source_controlled_by_attacker + description: The Kustomization must reference an existing or newly created source artifact containing attacker-controlled + content; source-controller egress and --no-cross-namespace-refs can restrict the reference. This fact is not + proved by create permission alone. blockers: [] confidence: conditional severity: critical - mitigation: Enable Flux multi-tenancy lockdown (--default-service-account, --no-cross-namespace-refs) and restrict who can create Kustomizations and Flux sources. + mitigation: Enable Flux multi-tenancy lockdown (--default-service-account, --no-cross-namespace-refs), restrict + Kustomization creation, and protect the referenced source content. references: - - https://fluxcd.io/flux/components/kustomize/kustomizations/#role-based-access-control - - https://fluxcd.io/flux/installation/configuration/multitenancy/ - notes: Selected by ServiceAccount name in any namespace (usually flux-system). Patching an existing Kustomization's path/sourceRef is modelled by k8s-workloads-flux-kustomization-patch-controller-identity. + - https://fluxcd.io/flux/components/kustomize/kustomizations/#role-based-access-control + - https://fluxcd.io/flux/installation/configuration/multitenancy/ + notes: Selected by ServiceAccount name in any namespace (usually flux-system). Patching an existing Kustomization's + path/sourceRef is modelled by k8s-workloads-flux-kustomization-patch-controller-identity. - id: k8s-workloads-flux-kustomization-patch-controller-identity provider: k8s @@ -517,32 +524,42 @@ title: Create a Flux HelmRelease without a ServiceAccount so helm-controller installs it source: src/pentesting-cloud/kubernetes-security/kubernetes-privilege-escalation/controllers-and-admission.md#gitops-and-platform-controller-deputies source_revision: 171e422 - summary: The source can obtain the privileges of the Flux helm-controller ServiceAccount by creating a HelmRelease (and a chart source it controls) that the controller installs with its own identity. + summary: The source can obtain the privileges of the Flux helm-controller ServiceAccount by creating a HelmRelease + that renders attacker-controlled chart content from an existing or newly created referenceable source under + the controller identity. requires: all_of: - - {verb: create, resource: helmreleases, api_group: helm.toolkit.fluxcd.io, namespace: "{pivot.namespace}"} - any_of: - - - {verb: create, resource: helmrepositories, api_group: source.toolkit.fluxcd.io, namespace: "{pivot.namespace}"} - - - {verb: create, resource: gitrepositories, api_group: source.toolkit.fluxcd.io, namespace: "{pivot.namespace}"} - - - {verb: create, resource: ocirepositories, api_group: source.toolkit.fluxcd.io, namespace: "{pivot.namespace}"} + - verb: create + resource: helmreleases + api_group: helm.toolkit.fluxcd.io + namespace: '{pivot.namespace}' target: kind: k8s_service_account selector: k8s_sa_name: helm-controller scope: cluster - aggregate_as: "Flux helm-controller of {cluster}" + aggregate_as: Flux helm-controller of {cluster} conditions: - - id: flux_default_service_account_flag - description: With --default-service-account the HelmRelease impersonates a tenant ServiceAccount; controller arguments are not collected. - - id: flux_controller_rbac - description: The default Flux install binds cluster-admin to helm-controller. + - id: flux_default_service_account_flag + description: With --default-service-account, or an explicit spec.serviceAccountName, the HelmRelease uses a + tenant ServiceAccount instead of helm-controller; controller arguments and the proposed HelmRelease spec must + be checked. + - id: flux_controller_rbac + description: The reached privileges are helm-controller's effective bindings, which must exceed the caller's + grants. + - id: source_and_rendered_content_controlled_by_attacker + description: The new HelmRelease must reference an existing or newly created source whose selected chart revision + or values the attacker controls and whose rendered objects exercise the stronger privilege. Reference policy, + reconciliation, and admission must allow the objects; source-create permission alone proves none of these + facts. blockers: [] confidence: conditional severity: critical - mitigation: Enable Flux multi-tenancy lockdown and restrict HelmRelease and Flux source creation. + mitigation: Enable Flux multi-tenancy lockdown, restrict HelmRelease creation, and protect the referenced chart + source and values. references: - - https://fluxcd.io/flux/components/helm/helmreleases/#role-based-access-control - - https://fluxcd.io/flux/installation/configuration/multitenancy/ + - https://fluxcd.io/flux/components/helm/helmreleases/#role-based-access-control + - https://fluxcd.io/flux/installation/configuration/multitenancy/ notes: Chart values, hooks and dependencies all render under the controller identity (see helm-template-injection.md). - id: k8s-workloads-argocd-application-controller-identity @@ -580,3 +597,74 @@ - https://argo-cd.readthedocs.io/en/stable/user-guide/projects/ - https://argo-cd.readthedocs.io/en/stable/operator-manual/security/ notes: Direct Kubernetes API writes bypass Argo CD's own RBAC (argocd-rbac-cm). The default cluster-scoped install grants the application controller all verbs on all resources; destinations in other registered clusters use their stored credentials (not modelled). Writing appprojects in the Argo CD namespace removes the project restrictions and is covered by the same condition. + +- 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: 0b36331 + 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 + 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: unknown + 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: Draft only. The current selector reads labels, never Secret data; the evaluator must keep this edge UNKNOWN + until the credential-evidence fact is collected. Runtime admission and credential validity may still keep it + UNKNOWN. The same edge covers the Jenkins Pod-YAML discussion. From e81a9974ec6b58a9313d713c5ea14b571d656530 Mon Sep 17 00:00:00 2001 From: Carlos Polop Date: Mon, 12 Oct 2026 21:42:27 +0200 Subject: [PATCH 17/17] Integrate verified CI and platform exclusions into privesc catalog Co-Authored-By: Codex --- .../aws/_excluded_b.yaml | 6 +- .../aws/_excluded_ci_cd.yaml | 41 ++ .../azure/_excluded_ci_cd.yaml | 450 ++++++++++++++++++ .../k8s/_excluded_ci_cd.yaml | 16 + 4 files changed, 511 insertions(+), 2 deletions(-) create mode 100644 src/privilege-escalation-paths/aws/_excluded_ci_cd.yaml create mode 100644 src/privilege-escalation-paths/azure/_excluded_ci_cd.yaml create mode 100644 src/privilege-escalation-paths/k8s/_excluded_ci_cd.yaml diff --git a/src/privilege-escalation-paths/aws/_excluded_b.yaml b/src/privilege-escalation-paths/aws/_excluded_b.yaml index ddaee338ad..2cf9a32e6f 100644 --- a/src/privilege-escalation-paths/aws/_excluded_b.yaml +++ b/src/privilege-escalation-paths/aws/_excluded_b.yaml @@ -222,8 +222,10 @@ - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetfunctionconfiguration--read-environment-variables source_revision: a53b46392c technique: lambda:GetFunctionConfiguration - reason: Configuration access can reveal an identity credential in Environment.Variables, but no target principal - follows from permission alone; require verified credential and distinct identity. + reason: lambda:GetFunctionConfiguration can return plaintext Lambda environment values, including credentials + copied from SSM or Secrets Manager at deployment; a customer-managed KMS key may also require kms:Decrypt. + A principal edge requires a live credential value and a verified mapping to another identity; the configuration + snapshot supplies neither secret classification nor credential validity. - source: src/pentesting-cloud/aws-security/aws-privilege-escalation/aws-lambda-privesc/README.md#lambdagetlayerversion--download-layer-code source_revision: a53b46392c diff --git a/src/privilege-escalation-paths/aws/_excluded_ci_cd.yaml b/src/privilege-escalation-paths/aws/_excluded_ci_cd.yaml new file mode 100644 index 0000000000..91fcebed5a --- /dev/null +++ b/src/privilege-escalation-paths/aws/_excluded_ci_cd.yaml @@ -0,0 +1,41 @@ +# Reviewed source techniques without a supported principal escalation edge. +- source: src/pentesting-ci-cd/serverless.com-security.md#tutorial + source_revision: 0b36331 + technique: Serverless Dashboard collaborator deploys through SFRole AdministratorAccess + reason: Requires Serverless Dashboard collaborator deployment authority and an SFRole trust/external-id binding + to the AWS account. Dashboard membership and deploy rights are not in the AWS snapshot. +- source: src/pentesting-ci-cd/serverless.com-security.md#access-keys-and-license-keys-security + source_revision: 0b36331 + technique: Leaked SERVERLESS_ACCESS_KEY grants dashboard deployment authority + reason: Requires the actual live SERVERLESS_ACCESS_KEY value and its Dashboard scope; cloud configuration + does not establish key theft or validity. +- source: src/pentesting-ci-cd/terraform-security.md#terraform-plan + source_revision: 0b36331 + technique: Poison HCL with external data source for plan-time execution + reason: Requires attacker HCL to be consumed by terraform plan with external provider execution and runner + credentials. SCM-to-runner mapping and Terraform config are uncollected. +- source: src/pentesting-ci-cd/terraform-security.md#malicious-terraform-provider-in-a-project + source_revision: 0b36331 + technique: Pin attacker provider/lock hash for init+plan execution + reason: Requires attacker provider and lockfile to be accepted by terraform init/plan on a credential-bearing + runner. Provider installation and runner mapping are uncollected. +- source: src/pentesting-ci-cd/terraform-security.md#terraform-apply + source_revision: 0b36331 + technique: Inject local-exec provisioner for apply-time credentials + reason: Requires malicious local-exec configuration to reach terraform apply after approval on a runner with + target credentials. Plan alone does not execute it. +- source: src/pentesting-ci-cd/terraform-security.md#secrets-dumps + source_revision: 0b36331 + technique: Add nonsensitive output to print secret variable + reason: Requires a usable secret variable and permission to write the output plus read applied output; variable + content and future apply are uncollected. +- source: src/pentesting-ci-cd/terraform-security.md#terraform-cloud-speculative-plan-rce-and-credential-exfiltration + source_revision: 0b36331 + technique: Terraform Cloud plan token executes external data source and steals injected AWS/GCP credentials + reason: Requires Terraform Cloud speculative-plan permission on the workspace, accepted external data source, + and injected AWS/GCP credentials. Workspace ACL, run settings, and cloud identity join are absent. +- source: src/pentesting-ci-cd/terraform-security.md#compromising-terraform-cloud + source_revision: 0b36331 + technique: Steal plaintext Terraform CLI token from credentials.tfrc.json + reason: Requires read of the actual credentials.tfrc.json token, token validity, and target workspace scope. + Local file content and token possession are runtime facts. diff --git a/src/privilege-escalation-paths/azure/_excluded_ci_cd.yaml b/src/privilege-escalation-paths/azure/_excluded_ci_cd.yaml new file mode 100644 index 0000000000..eeea245ecc --- /dev/null +++ b/src/privilege-escalation-paths/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/k8s/_excluded_ci_cd.yaml b/src/privilege-escalation-paths/k8s/_excluded_ci_cd.yaml new file mode 100644 index 0000000000..a9cbdff8b5 --- /dev/null +++ b/src/privilege-escalation-paths/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.